agentsclimarketplace

Powerbi motion

Skill jamartinezpastor/powerbi-motion/powerbi-motion

Generate a single landscape MP4 video highlighting the most relevant insights from a Microsoft Power BI report. Use whenever the user wants Power BI data, semantic-model measures, or report KPIs turned into motion graphics, animated summaries, or shareable clips for Slack, email, social, or briefings — even without the word animation. Triggers include animate this report, make a video from these KPIs, motion summary, Power BI to video, or any Power BI model + visual-storytelling request.From its SKILL.md

Install
npx -y skills add jamartinezpastor/powerbi-motion --skill powerbi-motion

Assembled from the repository path, not quoted from the project. Check it against their README if it does not work.

2 things to look at

  • no licenseNo license file was found in the repository. Code published without one is not open source by default, so using it at work is a question for whoever answers licensing questions where you are.
  • 0 stars0 stars. Stars are a popularity signal and not a quality one, but at this level it is likely that nobody has read this closely except its author, and you would be relying on your own review.

SKILL.md

8.9 KB, ~2.0k tokens by cl100k_base, as published. Nobody here has run it

Power BI Motion

Pipeline: discover → propose → render, human-in-the-loop at propose. Never render before the user approves the storyboard.

Output discipline (governs every turn)

This skill produces one MP4, not prose. Per turn the ONLY visible outputs are:

  • Stage 2: one framing line (≤ 12 words) + the interactive storyboard widget. Nothing else — no data summaries, no interim findings, no recommendations on which to pick, no commentary after the widget.
  • Stage 3: one sentence confirming what was produced + the file link (present_files) + one next-step line only if the user must act.
  • A short blocker line only if something real is missing (no MCP, no data, no candidates, no ffmpeg).

Do Stage 1 silently. If a measure is broken, it becomes a storyboard candidate — that IS the surfacing. Target under 200 tokens of visible text for Stage 1+2. If the user asks for analysis/summary of the report instead of animation, this skill is the wrong tool — answer normally without this pipeline.

Prerequisites (verify, then stop if missing)

  1. Power BI MCP connected (powerbi-modeling-mcp:* local, or the Remote MCP for published models). Never invent data if absent.
  2. Pillow (pip install pillow --break-system-packages) and ffmpeg on PATH. That's the entire dependency chain — there is no Node, no npx, no browser, no HyperFrames anymore (see references/limitations.md for why that was retired).

Report missing prerequisites as one combined message and wait.

Stage 1 — Discover (silent)

  1. Inventory tables/measures/relationships via MCP listing tools.
  2. Detect model class: a Date table (or DateTime column joined to the fact table) with ≥ 4 periods → temporal (scripts/propose_insights.py); otherwise categorical (scripts/propose_insights_categorical.py).
  3. Audit all measures in ONE query — see recipe 2.0 in references/powerbi-mcp-recipes.md (single EVALUATE ROW(...) with every measure). Out-of-bounds results (% outside [-100,100], negative counts, blanks where data exists, NaN) become broken_measure candidates. Never silently use a broken measure.
  4. Run the minimal probe set (see recipes; batch aggressively — 3-4 MCP round-trips total is the norm).

There is no theme-extraction step. The render always uses the fixed built-in Power BI Motion palette — see "Visual style" below.

Read references/insight-detection.md before classifying; references/powerbi-mcp-recipes.md before querying.

Stage 2 — Propose (widget only)

Run the detector. Present at most 7 candidates as an interactive widget (Visualizer or host equivalent) — checkbox cards, never a prose/table list. Each card: class label, KPI + headline value, delta line (≤ 12 words), narration in quotes (≤ 14 words), confidence, rough duration. Default-check 2-3 that form a coherent narrative. Submit button sends the selected IDs via sendPrompt. Stop and wait; treat ambiguous replies ("looks good") as a request for confirmation, not approval.

Insight classes: references/insight-detection.md. Visual treatment per class: references/visual-grammar.md.

Stage 3 — Render

Two modes (ask if unclear; default Mode A for audience-facing output):

  • Mode A — narrated report: one MP4; intro card → per-chapter title+setup cards → insight scenes → outro.
  • Mode B — standalone clips: one MP4 per insight, no framing (same renderer, one chapter per config).

Steps:

  1. Build report_config.json: {report:{title,subtitle,brand?}, outro:{recap}, source:{dataset,period}, chapters:[{title, setup, data:{insight:{class,narration}, ...}}]}. No theme key, no starter key — those no longer exist. See the class → payload contract below for what data needs per class.
  2. One command renders it: python3 scripts/generate_video.py --config report_config.json --out renders/<slug>.mp4. That's the whole pipeline — no assemble step, no separate GIF step, no HyperFrames call. It validates the config up front and refuses to render with an actionable error rather than producing a blank or broken clip.
  3. present_files the single .mp4. Nothing else lands in the output directory — no companion GIF, HTML, or JSON. If you need the DAX audit trail, that's the config file already sitting in your own working directory; it is not a deliverable.

Visual style (fixed, not configurable)

Every render uses the same built-in Power BI Motion look — a deliberate simplification, not a missing feature:

  • Palette: Power BI Desktop / Fluent UI defaults (blue #118DFF primary, coral #FD625E accent, teal #01B8AA secondary series, near-black text, off-white canvas). Hardcoded in generate_video.py's THEME dict.
  • Canvas is never pure white. It's Fluent's #F3F2F1 (Power BI Desktop's own canvas grey). This is a contrast-safety rule, not a cosmetic choice: a pure-white canvas plus any light-colored text element is a white-on-white bug waiting to happen. Off-white canvas + white card surfaces + dark/colored text is always safe. If you ever add a new painter, keep that invariant — never light-on-light.
  • Landscape, 1280×720, 24fps. Square format (the old default) cut off longer titles and member labels at the screen edges; 16:9 gives roughly double the horizontal wrap budget at the same font size. 24fps measured as the speed/smoothness sweet spot for this renderer (see references/limitations.md).
  • Per-chapter duration is computed from on-screen text, not a flat constant — a chapter with four long member labels and a two-line narration holds longer than a one-line KPI callout. See reading_seconds() in the script and "Reading-time model" in references/visual-grammar.md. Don't pass a manual duration override; fix the narration length instead if a chapter feels rushed or padded.

Insight class → payload contract

data.insight.class selects the painter, and each painter has a data contract. generate_video.py validates this before opening ffmpeg and refuses to render with an actionable error — but get it right at authoring time:

Class familyClassesRequiresRenders
Card gridoutlier, extreme_value, record, share_rarity, contributionnon-empty data.members ([{member, value or deltaPct, isOutlier}])KPI card grid, outlier gets a colored accent bar
Share barshare_dominance, mix_shift, concentrationnon-empty data.members ([{member, shareNow}])stacked bar
Time linetrend, anomaly, threshold_crossingnon-empty data.series ([{period, value}])line over ordered periods, with gridlines
Brokenbroken_measuredata.measurediagnosis card

Choosing between them is a data-shape question, not a style question:

  • Insight compares groups/segments (stance, accuracy brackets, regions…) → card grid family. This is the common case for categorical models.
  • Insight moves along an ordered axis (months, quarters) → time line family.
  • Never fabricate a time series to satisfy the time-line contract. If the dataset has no time axis (aggregate snapshots, one-row-per-entity), a "threshold" insight is really a group comparison: use extreme_value with brackets as members.
  • Classes outside the table (e.g. no_finding) are rejected, not silently defaulted. Reframe the insight into one of the shapes above — a flat "no effect" story fits the card grid with near-equal member values.
  • Optional data.subtitle adds context to the card-grid header (e.g. "YoY change" — only when the delta really is year-over-year). No temporal wording is ever added automatically.
  • outro at config top level: {"recap": "..."} (a bare string is accepted and auto-wrapped).

Hard rules

  • Never render unapproved data. The proposal stage is non-optional.
  • Animate the delta, not the value. No meaningful delta → not in the storyboard.
  • Source attribution in every clip (bottom-left: dataset · period · Power BI Motion).
  • No invented numbers. Failed/absurd DAX → surface and stop.
  • One insight per clip.
  • No prose deliverable — the widget is Stage 2, the MP4 is Stage 3.
  • Only the .mp4 is a deliverable. Don't hand the user a GIF, HTML file, or JSON snapshot alongside it.

When NOT to use

Static chart wanted → Visualizer/matplotlib. Model modification → Power BI Modeling MCP directly. Report analysis/summary wanted → normal response, no pipeline. Real-time animation inside Power BI → out of scope.

What ships with it: 8 files

92.0 KB alongside SKILL.md, 3 of them executable

Keep looking

Skills are one crate of 325,949. Ordering is by how many stacks a row turns up in, so the top of any crate is what has actually been picked rather than what has the most stars.