🎬 Movie Narrator
One Prompt → One Narrated Movie Video
Movie Narrator is an open-source toolkit that automatically generates movie recap videos with narration, subtitles, and rendered output from a simple command.
Features
- 🎬 LLM-powered movie recap script generation
- 🔊 Text-to-Speech narration (Edge-TTS by default)
- 💬 Automatic SRT subtitle generation
- 🌐 Multi-language subtitles with LLM translation
- 🏁 Multi-candidate horse race — run N variations, auto-pick the best
- 🎯 Reference video imitation — extract style from viral narration
- 👁️ VLM scene captioning via cloud VLM API
- 🎭 Narrator perspective (omniscient / character / detective)
- 🎨 Render template system (title cards, watermarks, slogans)
- 🔍 TMDB fact verification with source attribution
- 🖥️ Web UI (separate
movie-narrator-webpackage) - 🎞️ Video rendering (1080p/4K output)
- 📝 Script markdown export
- 🎵 Background music integration
- 🔌 Extensible plugin architecture (custom TTS / LLM backends)
- ☁️ Async task processing (submit and go, notified on completion)
- 🌐 Remote inference via REST API
- ✅ Final-video QA — black-frame / slideshow-risk detection
- 🗣️ Optional Chinese ASR (automatic multi-backend fallback)
Installation
Requirements
- Python 3.10+
Install Movie Narrator
From PyPI
pip install movie-narrator
From Source
git clone https://github.com/zcbacxc/movie-narrator.git
cd movie-narrator
pip install -e .
Optional extras
# Scene detection (PySceneDetect)
pip install "movie-narrator[media]"
# WhisperX + faster-whisper + FunASR + semantic search (requires PyTorch; Python < 3.14)
pip install "movie-narrator[ml]"
# Web UI (FastAPI + React) — separate package
pip install movie-narrator-web
# Everything
pip install "movie-narrator[full]"
Note on Python 3.14+: The
[ml]extra is limited to Python < 3.14 — PyTorch itself is now 3.14-ready (2.10+), but downstream ML dependencies (WhisperX, FunASR) have not yet shipped Python 3.14 wheels; on 3.14+ it is silently skipped and the align/match steps automatically soft-degrade (see Soft steps).
For development:
pip install -e ".[dev]"
Quick Start
Prerequisites
- LLM: Default uses local Ollama (
ollama serveto start). Or configure remote LLM via.envfile.
Basic Usage
# Generate a narrated movie video
mn create --movie "飞驰人生" --style "热血搞笑" --duration 60
# With custom voice and format
mn create --movie "飞驰人生" --voice "zh-CN-XiaoxiaoNeural" --format "9:16"
More Commands
mn create --config examples/job.example.yaml # Drive from YAML config
mn create --subtitle-lang en --subtitle-mode bilingual # Multi-language subtitles
mn race --movie "飞驰人生" --video movie.mp4 --candidates 3 # Multi-candidate horse race
mn imitate --reference viral_ref.mp4 --movie "飞驰人生" # Reference video imitation
mn serve # Start remote inference API server (v0.6.1+)
mn submit -m # Submit async task
mn tasks # List recent tasks
mn version # Show version
mn --help # Show full CLI help
All CLI flags and usage examples are documented in examples/cli-usage.sh.
Configuration
All settings use the MN_ prefix to avoid conflicts with other tools.
Via .env file (recommended)
~/.movie-narrator/.env is auto-created with default values on first run — edit it to configure LLM, TTS, and other settings. This file lives outside the package, so pip install/upgrade/uninstall never touches it. You can also create a project-level .env in your working directory for per-project overrides.
MN_LLM_BASE_URL=http://localhost:11434/v1
MN_LLM_API_KEY=ollama
MN_LLM_MODEL=qwen2.5:7b
MN_DEFAULT_VOICE=zh-CN-YunxiNeural
Via environment variables
# PowerShell
$env:MN_LLM_BASE_URL="http://localhost:11434/v1"
$env:MN_LLM_MODEL="qwen2.5:7b"
mn create --movie "飞驰人生" --duration 60
# Linux / macOS
export MN_LLM_BASE_URL=http://localhost:11434/v1
export MN_LLM_MODEL=qwen2.5:7b
mn create --movie "飞驰人生" --duration 60
Config lookup order
| Priority | Location | Notes |
|---|---|---|
| 1 | Environment variables (MN_*) |
Highest |
| 2 | cwd/.env |
Project-level |
| 3 | ~/.movie-narrator/.env |
User-level, never lost on pip install/upgrade/uninstall |
| 4 | Built-in defaults | Local Ollama |
Full reference
See .env.example for the complete list of all environment variables (LLM + TTS infrastructure only). All pipeline behavior is configured via examples/job.example.yaml — params keys covering scene detection, match, render, translate, BGM, WhisperX/FunASR align, async, and video sizes.
LLM Provider Guides
Movie Narrator works with any OpenAI-compatible LLM. New user? Check out the LLM Provider Guides for step-by-step registration and free-tier setup:
| Provider | Free Tier | Best For |
|---|---|---|
| Ollama | Completely free (local) | Privacy, offline use |
| Zhipu (GLM) | glm-4-flash unlimited free | Zero-cost, no GPU |
| Alibaba Bailian | 1M tokens per model | Qwen flagship models |
| Xiaomi MiMo | Limited-time free + ¥10 invite bonus | LLM + TTS in one platform |
| SiliconFlow | Free models + voucher credits | Multi-model switching |
Output
| File | Description |
|---|---|
narration.mp3 |
AI-generated narration audio |
mixed.mp3 |
Narration + BGM overlay (when BGM enabled; otherwise narration.mp3 used directly) |
subtitle.srt |
Synchronized subtitle file (original narration) |
subtitle..srt |
Translated subtitle (when --subtitle-lang set) |
subtitle.bilingual.srt |
Bilingual subtitle (when --subtitle-lang set) |
script.md |
Human-readable script |
research.json |
Movie research data (when --research) |
metadata.json |
Segment timings, pipeline status, config |
final.mp4 |
Rendered video (16:9 or 9:16) |
matches.json |
Scene-to-segment clip matching (when video provided) |
clips/ |
Per-segment clip .mp4 files (when --no-clips not set) |
clips/holds a standalone clip per segment, ready for secondary editing or reuse.
Pipeline
16-step sequential pipeline (see Architecture):
resolve_video → prepare_assets → research_plot → generate_script →
export_script_md → generate_voice → align_audio → detect_scenes →
match_clips → mix_bgm → translate_subtitles → generate_subtitle →
run_qa_gate → render_video → validate_deliverable → export_clips
Soft steps (research, align, scene detect, scene match, BGM, translate, QA gate, clip export) gracefully skip or soft-degrade when optional dependencies are missing or upstream data is unavailable. Use --strict to abort instead.
Project Structure
For contributors — most users only need
mn create. See Architecture for details.
movie-narrator/
├── src/movie_narrator/
│ ├── cli.py # Typer CLI entry point
│ ├── config.py # Pydantic settings
│ ├── models.py # Data models (Context, Status, etc.)
│ ├── contract.py # Stable API contract surface
│ ├── pipeline/ # 16-step pipeline (runner, steps, errors)
│ ├── cloud/ # Task queue, remote inference, batch, scheduling, DLQ, distributed (v0.9.x)
│ ├── reliability/ # Circuit breaker + retry policy (v0.9.1)
│ ├── workflow/ # YAML job config (schema, loader, merge)
│ ├── tts/ # TTS provider abstraction layer
│ └── utils/ # Shared utilities (console, log, font, etc.)
├── tests/ # Unit + integration tests
├── docs/ # Architecture, guides, roadmap
├── examples/ # Job YAML, CLI usage, plugins
└── .github/workflows/ # CI/CD
Documentation
Compliance Notices
- Edge-TTS: the default TTS channel (
edge) is built on a reverse-engineered, unofficial interface. It is provided for personal / non-commercial free testing only. For commercial deployment, switchMN_TTS_PROVIDERtoopenaiormimo(both built-in). - TMDB: movie research data is sourced from TMDB (The Movie Database). When TMDB data is used, the source attribution is recorded in
research.jsonas required, as a courtesy.
License
Licensed under the AGPL-3.0-or-later License.