npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2026 – Pkg Stats / Ryan Hefner

@jinlee794/showrunner-mcp

v0.4.3

Published

MCP server for programmatic video generation — storyboard JSON in, MP4 out.

Readme


No Remotion. No subscription. No framework lock-in. Just Playwright frames, GSAP timelines, D3 charts, and ffmpeg encoding.

How It Works

AI Agent ──▶ storyboard JSON ──▶ Showrunner MCP Server
                                        │
                                   Zod validate
                                   ├── invalid → errors array
                                   └── valid ──▶ Assemble page per scene
                                                  ├── Theme CSS
                                                  ├── Scene HTML (Handlebars)
                                                  ├── GSAP bundle
                                                  └── D3 bundle
                                                         │
                                               Playwright (headless Chromium)
                                                         │
                                                    Scene type?
                                               ┌─────────┴─────────┐
                                          chart scenes        other scenes
                                          D3 builds SVG     Static HTML layout
                                               └─────────┬─────────┘
                                                  GSAP timeline (paused)
                                                         │
                                                  seek(0..1) per frame
                                                  Frame capture loop
                                                         │
                                                    ffmpeg encode
                                                         │
                                                   Output target
                                               ┌─────────┴─────────┐
                                             local              Azure
                                           File path          Blob URL

Each scene template builds a paused GSAP timeline. Chart scenes (chart-bar, chart-line, chart-donut) use D3 to construct SVG elements (scales, axes, paths, arcs) then hand off to GSAP for animation. The renderer scrubs .progress(0..1) for every frame, screenshots, and encodes. Deterministic — same input always produces the same frames.

Prerequisites

  • Node.js ≥ 20
  • ffmpeg on PATH
  • Playwright Chromium (auto-installed on first run)

Install

This package is published to GitHub Packages. Configure npm to use it:

# One-time setup: tell npm where to find @jinlee794 packages
echo "@jinlee794:registry=https://npm.pkg.github.com" >> ~/.npmrc

# Authenticate (use a GitHub PAT with read:packages scope)
npm login --registry=https://npm.pkg.github.com

# Install globally
npm install -g @jinlee794/showrunner-mcp

# Or run directly via npx
npx @jinlee794/showrunner-mcp --help

Quick Start

Use via npx (recommended)

# Render a storyboard to MP4
npx @jinlee794/showrunner-mcp render storyboard.json

# Render with options
npx @jinlee794/showrunner-mcp render storyboard.json --quality high --output output/final.mp4

# Render to GIF
npx @jinlee794/showrunner-mcp render storyboard.json --gif

# Validate a storyboard without rendering
npx @jinlee794/showrunner-mcp validate storyboard.json

# List available scene types
npx @jinlee794/showrunner-mcp scenes

Use from source

# Clone and install
git clone https://github.com/JinLee794/Showrunner.git
cd Showrunner
npm install

# Build
npm run build

# Render the demo storyboard
npx showrunner render fixtures/demo-storyboard.json

Showrunner MCP Server

stdio (local dev)

npx @jinlee794/showrunner-mcp

Agent config (VS Code / Claude Desktop / any MCP client):

{
  "mcpServers": {
    "showrunner": {
      "command": "npx",
      "args": ["-y", "@jinlee794/showrunner-mcp"],
      "env": {
        "npm_config_@jinlee794:registry": "https://npm.pkg.github.com"
      }
    }
  }
}

HTTP (remote / Azure)

TRANSPORT=http PORT=8080 npx @jinlee794/showrunner-mcp

Agent config:

{
  "mcpServers": {
    "showrunner": {
      "url": "https://<your-host>/mcp",
      "transport": "http"
    }
  }
}

Tools

| Tool | Description | Returns | |---|---|---| | render_video | Render a full storyboard to MP4 (with optional muxed voice-over + VTT transcript) | { path, duration, frames, fileSize, transcriptPath?, narration? } | | render_gif | Render a storyboard to animated GIF with speed/size control | { path, duration, frames, fileSize } | | render_scene | Render a single scene to MP4/GIF | { path } | | preview_storyboard | Generate interactive HTML preview (no Playwright/ffmpeg) | { path } | | validate_storyboard | Dry-run validation with error reporting | { valid, errors?, summary? } | | list_scene_types | Dynamically list available scene types + themes from the current install | { sceneTypes: Array<{ type, description, dataSchema }>, themes: string[] } | | synthesize_narration | Azure Speech TTS → MP3 + VTT/SRT transcript (no video) | { audioPath, transcriptPath, durationSec, scenes[] } |

Scene Types

See the full Scene Catalog → for animated GIF previews, detailed data schemas, and copy-paste sample JSON for every scene type.

| Type | Description | |---|---| | title-card | Full-screen branded intro with logo, title, subtitle | | section-header | Transition slide between sections | | pipeline-funnel | Horizontal bars with staggered spring animation + count-up values | | milestone-timeline | Vertical timeline with status dots and owner labels | | risk-callout | Cards with severity stripes and context text | | action-items | Numbered checklist with priority indicators | | deal-team | Avatar grid with role labels | | kpi-scorecard | 2×2 / 3×2 KPI cards with count-up and trend arrows | | chart-bar | Animated bar chart with staggered spring | | chart-line | SVG path draw-on line chart | | chart-donut | Clockwise-fill donut with center count-up | | table | Animated row-by-row table | | quote-highlight | Quote with word-by-word reveal and sentiment accent | | comparison | Side-by-side comparison with alternating slide-in | | closing | Branded outro with tagline and CTA | | code-terminal | Typing terminal with prompt/output/success lines | | image-card | Full-bleed image with caption overlay and Ken Burns effects | | bullet-list | Animated bullet list with icons, sub-text, and highlights | | stat-counter | Big count-up numbers with progress bars and change indicators | | text-reveal | Cinematic text with typewriter, word-reveal, and highlight effects |

Storyboard Schema

{
  "title": "Q2 Pipeline Review",
  "theme": "corporate-dark",
  "fps": 30,
  "resolution": [1920, 1080],
  "scenes": [
    {
      "type": "title-card",
      "duration": 4,
      "transition": "fade",
      "data": {
        "title": "Q2 Pipeline Review",
        "subtitle": "Enterprise Accounts",
        "date": "April 2026"
      }
    },
    {
      "type": "kpi-scorecard",
      "duration": 6,
      "transition": "fade",
      "data": {
        "kpis": [
          { "label": "Pipeline", "value": 28400000, "unit": "$", "trend": "up", "animateCount": true },
          { "label": "Win Rate", "value": 34, "unit": "%", "trend": "up", "animateCount": true }
        ]
      }
    },
    {
      "type": "closing",
      "duration": 3,
      "transition": "fade",
      "data": { "tagline": "Generated by AI" }
    }
  ]
}

See fixtures/sample-storyboard.json and fixtures/demo-storyboard.json for full examples.

Voice-over & Transcripts (Azure Speech)

Announcement: Azure Speech Narration Is Live

Showrunner now ships with first-class speech support. You can add narration directly in storyboard JSON, render MP4 with baked-in voice-over, and automatically generate synced transcript files.

  • Azure Speech neural voices (per-scene text or raw SSML)
  • Automatic scene timing extension when narration runs longer
  • Transcript sidecars in vtt, srt, or both
  • Works in CLI and MCP tools (render_video and synthesize_narration)

This is opt-in and environment-authenticated by design: credentials stay in local/server environment variables, never in storyboard payloads.

Opt-in narration. Add a voiceover field to any scene and (optionally) a top-level narration config; Showrunner synthesizes per-scene audio with Azure Speech, concatenates it onto the video timeline, muxes it into the MP4, and writes a synced .vtt transcript sidecar (word-boundary accurate).

Auth is passthrough. The MCP server only reads credentials from its local process environment — never from the storyboard JSON. This keeps keys out of agent context and lets you bring either a subscription key or a short-lived Entra/STS bearer token.

# Option A: subscription key
export AZURE_SPEECH_REGION=eastus
export AZURE_SPEECH_KEY=<your-key>

# Option B: Entra / STS bearer token (10-minute lifetime — refresh on your side)
export AZURE_SPEECH_REGION=eastus
export AZURE_SPEECH_TOKEN=<your-token>

# Optional — custom endpoint (sovereign / private cloud)
export AZURE_SPEECH_ENDPOINT=https://<region>.tts.speech.microsoft.com/

# Install the optional SDK (only needed when narration is enabled)
npm install microsoft-cognitiveservices-speech-sdk

Storyboard schema additions

{
  "title": "Q2 Pipeline Review",
  "narration": {
    "voice": "en-US-JennyNeural",
    "language": "en-US",
    "style": "newscast",
    "autoExtendScenes": true,
    "gapMs": 150,
    "transcriptFormat": "vtt"
  },
  "scenes": [
    {
      "type": "title-card",
      "duration": 4,
      "data": { "title": "Q2 Pipeline Review" },
      "voiceover": {
        "text": "Here's your Q2 pipeline review — enterprise accounts edition.",
        "style": "cheerful",
        "rate": "+5%"
      }
    },
    {
      "type": "closing",
      "duration": 3,
      "data": { "tagline": "Generated by AI" },
      "voiceover": {
        "ssml": "<speak version=\"1.0\" xml:lang=\"en-US\" xmlns:mstts=\"https://www.w3.org/2001/mstts\"><voice name=\"en-US-GuyNeural\"><mstts:express-as style=\"calm\">Thanks for watching.</mstts:express-as></voice></speak>"
      }
    }
  ]
}

| Field | Purpose | |---|---| | narration.voice | Default Azure Neural voice (e.g. en-US-JennyNeural, en-US-AriaNeural) | | narration.language | BCP-47 locale used when wrapping plain text in SSML | | narration.style | Default expressive style (newscast, cheerful, chat, …) | | narration.autoExtendScenes | When narration is longer than scene.duration, extend the scene automatically (default true) | | narration.gapMs | Silence padding between scenes (default 150) | | narration.transcriptFormat | vtt (default), srt, both, or none | | narration.region / narration.endpoint | Override env AZURE_SPEECH_REGION / AZURE_SPEECH_ENDPOINT | | scene.voiceover.text | Plain text — auto-wrapped in SSML | | scene.voiceover.ssml | Raw SSML — used verbatim, overrides all other voiceover fields | | scene.voiceover.voice / style / styleDegree / rate / pitch | Per-scene overrides |

CLI

# Render video with baked-in voice-over + transcript sidecar
AZURE_SPEECH_REGION=eastus AZURE_SPEECH_KEY=... \
  npx showrunner render storyboard.json --output out/brief.mp4
# → out/brief.mp4  +  out/brief.vtt

MCP

tool: synthesize_narration
args: { "storyboard": { ... }, "audioOutputPath": "/tmp/brief.mp3" }
→ { audioPath, transcriptPath, durationSec, voice, scenes: [{ sceneStartMs, wordCount, ... }] }

Call synthesize_narration first to preview/validate voices, or just call render_video on a storyboard that has voiceover fields — narration is added automatically.

Themes

| Theme | Description | |---|---| | corporate-dark | Dark navy, white text, gold accent (default) | | corporate-light | White background, dark text, blue accent | | minimal | Near-white, subtle grays | | microsoft | Microsoft brand guidelines | | custom | Uses branding overrides from storyboard |

Transitions

Applied between consecutive scenes with a 0.5s overlap:

| Type | Effect | |---|---| | cut | Hard cut, no overlap | | fade | Cross-fade (default) | | slide-left | Outgoing slides left, incoming slides from right | | slide-up | Outgoing slides up, incoming slides from below | | zoom | Outgoing zooms + fades, incoming scales in |

Render Quality

| Quality | Frame format | CRF | Best for | |---|---|---|---| | high | PNG | 18 | Final output | | medium | JPEG 90% | 23 | Default / preview | | fast | JPEG 70% | 28 | Iteration |

Technology Stack

| Layer | Technology | Role | |---|---|---| | Data visualization | D3.js v7 | SVG chart construction — scales, axes, bars, arcs, line paths | | Animation | GSAP v3 | Timeline-based motion — springs, staggers, easing, count-up | | Templating | Handlebars | Scene HTML generation from storyboard data | | Browser | Playwright | Headless Chromium for deterministic frame capture | | Encoding | ffmpeg | H.264 MP4 and GIF output | | Validation | Zod | Storyboard schema validation | | Server | MCP SDK | stdio + HTTP tool server for AI agents |

Animation System

GSAP (GreenSock) drives all motion. Each scene template builds a paused gsap.timeline() with springs, staggers, easing, and count-up animations. The renderer calls window.__seek(progress) per frame — fully deterministic, no requestAnimationFrame, no timing jitter.

Key GSAP features used: stagger, back.out / elastic.out / power3.out easing, snap: { textContent: 1 } for count-up, nested timeline composition.

D3 + GSAP: How Charts Work

Chart scenes use a two-library pattern — D3 for construction, GSAP for animation:

Renderer ──▶ Playwright Page: setContent(base.html + scene.html)
                 │                  (Page loads GSAP + D3 bundles)
                 │
                 ├──▶ D3: Parse embedded JSON data block
                 │    D3: Build scales (scaleLinear, scaleBand, scaleOrdinal)
                 │    D3: Generate geometry (rects, arcs, line paths)
                 │    D3: Append SVG elements to DOM
                 │         (D3 is done — no further re-renders)
                 │
                 ├──▶ GSAP: __buildTimeline() returns paused gsap.timeline()
                 │    GSAP: Target D3-generated SVG elements
                 │          (scaleY, strokeDashoffset, opacity, textContent snap)
                 │
                 └──▶ Loop: every frame (30 fps × duration)
                        Renderer → Page: window.__seek(progress)
                        Page → GSAP: timeline.progress(n)
                        GSAP → Page: Update SVG attributes
                        Renderer: Screenshot to frame buffer
                                    │
                              Pipe frames to ffmpeg

This separation keeps D3 doing what it's best at (data → geometry mapping) and GSAP doing what it's best at (timeline-scrubbed animation), with no runtime conflicts.

| Chart type | D3 handles | GSAP animates | |---|---|---| | chart-bar | x/y scales, axis ticks, bar rects | Staggered scaleY grow + value count-up | | chart-line | Line generator, area fill, x/y axes | strokeDashoffset draw-on + dot pop-in | | chart-donut | Arc generator, pie layout, slices | Clockwise stroke draw + center count-up |

Project Structure

src/
├── server.ts ──▶ tools/ ──▶ renderer/
│                               ├── index.ts
│                               ├── frame-capture.ts ──▶ browser-pool.ts
│                               ├── encoder.ts
│                               ├── transitions.ts
│                               └── preview.ts
├── motion/
│   ├── gsap-bundle.ts
│   ├── d3-bundle.ts
│   └── presets.ts
├── templates/
│   ├── base.html ──▶ scenes/ (21 templates)
│   └── themes/
└── schema/
    └── storyboard.ts (Zod)
src/
├── server.ts                # Showrunner MCP server — stdio + HTTP transports
├── tools/                   # MCP tool handlers
├── renderer/
│   ├── index.ts             # Main render pipeline
│   ├── frame-capture.ts     # Playwright frame loop
│   ├── encoder.ts           # ffmpeg encoding
│   ├── transitions.ts       # Scene transition compositing
│   ├── browser-pool.ts      # Warm browser management
│   └── preview.ts           # HTML preview generator
├── output/
│   ├── local.ts             # File path output
│   └── blob.ts              # Azure Blob Storage output
├── motion/
│   ├── gsap-bundle.ts       # GSAP core for page injection
│   ├── d3-bundle.ts         # D3.js for page injection (chart scenes)
│   └── presets.ts           # Reusable animation presets
├── templates/
│   ├── base.html            # Common layout with theme + GSAP + D3 injection
│   └── scenes/              # Per-scene-type HTML templates
├── themes/                  # CSS custom property theme files
├── schema/
│   └── storyboard.ts        # Zod schemas
└── types/
    └── index.ts

Scripts

npm run build    # tsc + copy templates/themes to dist/
npm run dev      # tsc --watch
npm start        # node dist/server.js
npm test         # vitest

Publishing

Packages are published automatically to GitHub Packages via GitHub Actions when you push a version tag.

# 1. Bump version (updates package.json and creates a git tag)
npm version patch   # or minor / major

# 2. Push the commit and tag — CI publishes to GitHub Packages and creates a GitHub Release
git push --follow-tags

No extra secrets needed — the workflow uses the built-in GITHUB_TOKEN.

License

MIT