Skip to main content

Turn raw screen recordings + narration text into polished narrated screencasts

Project description

screencast-narrator

Turn raw screen recordings + narration text into polished narrated screencasts.

screencast-narrator is a Python library and CLI that takes a browser screen recording together with a narration timeline and produces a final video with:

  • Text-to-speech narration synced to on-screen actions
  • QR-code-based frame-accurate synchronization
  • Automatic freeze-frame insertion when narration overflows action duration
  • Dead-air gap detection and cutting
  • Interactive HTML timeline visualization

Installation

pip install screencast-narrator

For TTS support (Kokoro):

pip install screencast-narrator[tts]

For TTS support (Gemini, requires GEMINI_API_KEY or GOOGLE_API_KEY):

pip install screencast-narrator[gemini]

System dependencies:

# macOS
brew install ffmpeg zbar

# Ubuntu/Debian
apt-get install ffmpeg libzbar0

# Windows
winget install GyanDev.FFmpeg
# The pyzbar Python package ships its own libzbar DLL but needs the Visual C++ 2013 runtime:
winget install Microsoft.VCRedist.2013.x64

Quick Start

As a library with Playwright

from pathlib import Path
from playwright.sync_api import sync_playwright
from screencast_narrator.storyboard import Storyboard
from screencast_narrator.sync_frames import inject_sync_frame
from screencast_narrator.merge import process

output_dir = Path("my-screencast")
storyboard = Storyboard(output_dir)

with sync_playwright() as p:
    browser = p.chromium.launch()
    context = browser.new_context(
        record_video_dir=str(output_dir / "videos"),
        record_video_size={"width": 1280, "height": 720},
    )
    page = context.new_page()

    # Narration bracket with sync frames
    nid = storyboard.begin_narration("We open the example website.")
    inject_sync_frame(page, nid, "START")
    storyboard.add_screen_action("Navigate to example.com")
    page.goto("https://example.com")
    inject_sync_frame(page, nid, "END")
    storyboard.end_narration()

    context.close()
    browser.close()

# Produce the final narrated video
process(output_dir)

As a CLI

screencast-narrator /path/to/recording-output/

# Options:
#   --offline                          use the offline Kokoro TTS backend
#   --tts-backend kokoro|edge|gemini   select the TTS backend explicitly
#                                      (gemini reads GEMINI_API_KEY or GOOGLE_API_KEY)
#   --debug-overlay                    burn narration timing overlay into the video
#   --font-size N                      debug overlay font size

The directory must contain:

  • A storyboard.json file (produced by Storyboard or hand-written)
  • A video file (.webm) in a videos/ subdirectory with sync frames embedded

API

The screencast-narrator API is JSON-based and language-agnostic. Any browser automation framework that can record video and execute JavaScript can produce the inputs.

See docs/api.md for:

  • Timeline JSON schema
  • Sync frame protocol specification
  • Sample code in Python, Java, and TypeScript
  • Pipeline processing details

Architecture

The pipeline has these stages:

  1. Storyboard (storyboard.py) — Declares narration text and screen actions. No timestamps — timing comes from sync frames.

  2. Sync frame injection (sync_frames.py) — Inject green QR-code overlay frames into the browser at narration bracket boundaries for frame-accurate sync.

  3. TTS generation (tts.py) — Convert narration text to speech audio files. Pluggable backend; ships with Kokoro TTS.

  4. Sync detection (sync_detect.py) — Extract frames from the recorded video, detect green sync frames, decode QR codes to map video frames to narration events.

  5. Freeze frame calculation (freeze_frames.py) — When narration audio is longer than the on-screen action, calculate where to insert freeze frames so audio and video stay in sync.

  6. Video merge (merge.py) — Orchestrate FFmpeg to build the final video: strip sync frames, insert freeze frames, overlay audio, cut dead air gaps.

  7. Timeline visualization (timeline_html.py) — Generate an interactive HTML timeline showing bracket positions, freeze frames, gap cuts, and audio durations.

Custom TTS Backend

Subclass TTSBackend:

from pathlib import Path

from screencast_narrator.tts import TTSBackend

class MyTTS(TTSBackend):
    def resolve_voice(self, voice: str) -> str:
        # Map a logical voice name (female-1..4, male-1..4) to a backend voice ID
        ...

    def _generate_raw(self, text: str, output_path: Path, voice: str) -> None:
        # Generate a WAV file at output_path
        ...

# Use it — the factory receives the storyboard language
from screencast_narrator.merge import process
process(target_dir, tts_backend_factory=lambda language: MyTTS(language=language))

Development

git clone https://github.com/mmarinschek/screencast-narrator.git
cd screencast-narrator
pip install -e ".[dev,tts]"

# Run tests
pytest tests/ -v

# On macOS, if pyzbar can't find libzbar:
DYLD_LIBRARY_PATH=/opt/homebrew/lib pytest tests/ -v

License

Apache License 2.0 — see LICENSE.

Project details


Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

screencast_narrator-0.6.0.tar.gz (39.4 kB view details)

Uploaded Source

Built Distribution

If you're not sure about the file name format, learn more about wheel file names.

screencast_narrator-0.6.0-py3-none-any.whl (23.8 kB view details)

Uploaded Python 3

File details

Details for the file screencast_narrator-0.6.0.tar.gz.

File metadata

  • Download URL: screencast_narrator-0.6.0.tar.gz
  • Upload date:
  • Size: 39.4 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: twine/6.1.0 CPython/3.13.14

File hashes

Hashes for screencast_narrator-0.6.0.tar.gz
Algorithm Hash digest
SHA256 f4ac07e6aab89dfb1360143d81d26f4cc2bda2914ddc945ce2ea814568b7dd0d
MD5 7be94012337df1dde22715e79a269552
BLAKE2b-256 86c67d88cb54a0984d071292126242788c9151c3a795feddaa9e1dbb7193c11b

See more details on using hashes here.

Provenance

The following attestation bundles were made for screencast_narrator-0.6.0.tar.gz:

Publisher: publish.yml on mmarinschek/screencast-narrator

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

File details

Details for the file screencast_narrator-0.6.0-py3-none-any.whl.

File metadata

File hashes

Hashes for screencast_narrator-0.6.0-py3-none-any.whl
Algorithm Hash digest
SHA256 371e7e840dd6ec379a39ee776e8a33b0bbef6f0fcd5262887faca80dd6bb362c
MD5 bc984c07bce18049818f37e44ff0b1c8
BLAKE2b-256 e80d9f8b0363760178fa0c10ce661f7fcc4048422506caa2a3939a4ff0e19916

See more details on using hashes here.

Provenance

The following attestation bundles were made for screencast_narrator-0.6.0-py3-none-any.whl:

Publisher: publish.yml on mmarinschek/screencast-narrator

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

Supported by

AWS Cloud computing and Security Sponsor Datadog Monitoring Depot Continuous Integration Fastly CDN Google Download Analytics Pingdom Monitoring Sentry Error logging StatusPage Status page