Movie Narrator: a Python pipeline that turns one prompt into a narrated recap video
🎬 Generate narrated movie recap videos from a single prompt.
At a glance
- What is it?
- Movie Narrator is an AGPL-3.0 Python toolkit that chains an OpenAI-compatible LLM, Edge-TTS and moviepy into a single `mn create` command. It is built for people who want a repeatable recap pipeline rather than a hosted editor, and it assumes you can run a local model or bring your own API key.
- Who is it for?
- Adopt Movie Narrator if you already run an OpenAI-compatible endpoint, are comfortable on Python 3.10 to 3.13, and want the pipeline to live in your own repo rather than a vendor's dashboard: `pip install movie-narrator` then `mn create --movie "飞驰人生" --duration 60` is the whole onboarding.
- Can I use it commercially?
- Yes, with strict conditions. AGPL-3.0 is a network copyleft licence: if people use a modified version over a network, for example as a hosted service, you must offer them its source code under the same licence.
- Is it still maintained?
- Yes. The repository last received commits 2 days ago.
- What is it written in?
- Mainly Python, according to GitHub's language statistics.
Answers come from the project's GitHub data, last synced on September 17, 2026, and from our analysis. They are not legal advice.
DEEP OPEN-SOURCE ANALYSIS
The problem: recap videos are a pipeline, not a prompt
A movie recap video is four or five jobs glued together. You need a script that summarizes a plot without inventing scenes, a voice track timed to that script, subtitles that match the voice track, and a render that cuts source footage to the narration. Doing this by hand means moving between a chat window, a TTS tool, a subtitle editor and a video editor, and redoing all of it when you change the duration or the language.
Movie Narrator targets that repetition. The README describes it as a toolkit that "automatically generates movie recap videos with narration, subtitles, and rendered output from a simple command", and the CLI is organised around that: `mn create` for the standard run, `mn race` for several candidate scripts, `mn imitate` to copy the style of a reference video, and `mn submit` plus `mn tasks` for asynchronous jobs. The intended user is someone who wants the whole chain reproducible from a config file, not someone looking for a browser-based editor.
The project also assumes you have opinions about models. The default configuration points at a local Ollama server, and the README lists five providers with free tiers (Ollama, Zhipu GLM, Alibaba Bailian, Xiaomi MiMo, SiliconFlow). That is a deliberate choice: the script generation, the translation and the plot research all go through an OpenAI-compatible endpoint you supply.
How the pipeline moves from prompt to final.mp4
The flow is visible in the output table. A run produces `narration.mp3`, `subtitle.srt`, `script.md`, `metadata.json` and `final.mp4`, plus `mixed.mp3` when background music is enabled and `matches.json` plus a `clips/` directory when source video is supplied. So the stages are script, speech, subtitles, optional clip matching, render.
The LLM does more than write prose. The feature list includes TMDB fact verification "with source attribution", which writes `research.json` when `--research` is set, and multi-language subtitle translation, which produces `subtitle.<lang>.srt` and `subtitle.bilingual.srt`. There is also an optional VLM scene captioning step through a cloud VLM API, and a final-video QA pass that the README describes as black-frame and slideshow-risk detection. That QA step matters more than it sounds: a slideshow of still frames with narration over it is the most common way an automated recap looks broken.
Scene detection is optional and comes from PySceneDetect through the `[media]` extra. The heavier alignment and semantic-matching steps come from the `[ml]` extra (WhisperX, faster-whisper, sentence-transformers, FunASR). The README is explicit that these are soft steps: on Python 3.14 or newer the `[ml]` extra "is silently skipped and the align/match steps automatically soft-degrade". Silent is the operative word. A run on 3.14 will not fail, it will just do less, and you have to know that going in.
Installing Movie Narrator and running a first recap
The package needs Python 3.10 or newer and installs from PyPI. The base install pulls in typer, httpx, openai, pydantic, edge-tts, moviepy 2.x, pydub and pyyaml, which is enough for a script, a voice track and a render.
pip install movie-narratorBefore the first run you need an LLM. The default is a local Ollama server, so start it and confirm the model name in your configuration matches what you have pulled.
ollama serveOn first run the tool creates `~/.movie-narrator/.env` with default values. The README notes that this file lives outside the package, so pip install, upgrade and uninstall never touch it. The defaults assume Ollama on port 11434:
MN_LLM_BASE_URL=http://localhost:11434/v1
MN_LLM_API_KEY=ollama
MN_LLM_MODEL=qwen2.5:7b
MN_DEFAULT_VOICE=zh-CN-YunxiNeuralWith that in place, one command produces the video. The README's own example uses a Chinese title and style string, which is a fair signal of where the project's testing effort sits.
mn create --movie "飞驰人生" --style "热血搞笑" --duration 60Expect a working directory containing narration.mp3, subtitle.srt, script.md, metadata.json and final.mp4. If you want a vertical cut, add `--format "9:16"`; if you want translated subtitles, add `--subtitle-lang en --subtitle-mode bilingual`. The README points at `examples/cli-usage.sh` for the full flag list and `examples/job.example.yaml` for pipeline behaviour, and that split is worth internalising early: credentials and endpoints live in `.env`, everything about how the pipeline behaves lives in job.yaml.
Where Movie Narrator breaks or is the wrong tool
Python 3.14 is the clearest boundary. The `[ml]` extra is pinned to `python_version < "3.14"` in pyproject.toml, and the README explains why: PyTorch itself is 3.14-ready at 2.10+, but WhisperX and FunASR have not shipped 3.14 wheels. The consequence is not an error message but a quieter pipeline. If alignment and semantic matching are the reason you picked this tool, stay on 3.12 or 3.13.
The dependency set also constrains you. pillow is pinned to the 11.x line because moviepy 2.x requires `pillow<12.0`, and the pyproject comment states that known pillow 11.x advisories are ignored in the CI security job's pip-audit call until moviepy supports pillow 12.x. That is a real, documented gap rather than a hypothetical one, and anyone running an internal vulnerability scan will see it.
Scaling out is the third limit, and the docker-compose file is unusually candid about it. The project has no database and no external broker; task state is a `tasks.json` index held in memory and rewritten on every save. The compose comments warn that two processes pointing at the same `--storage-dir` would clobber each other, so worker replicas get a private anonymous volume for `/app/.mn_tasks` and act as independent inference endpoints reached via `--remote http://worker:8765` rather than as consumers of the API's queue. If you were hoping for a horizontally scalable job system, this is not one.
Finally, the tool needs source footage for anything beyond a narrated slideshow. `matches.json` and `clips/` only appear when a video is provided, and `mn create` as documented takes a movie title, not a file. The README's output table lists `clips/` as appearing "when `--no-clips` not set", which implies a video input path exists, but the quick-start examples do not show one.
Movie Narrator compared with a general video-generation API
The obvious alternative is a hosted text-to-video or avatar API: you send a prompt and a script, and the vendor returns a rendered file. The difference in approach is where the work happens. A hosted API owns the script model, the voice, the render farm and the retry logic, and you get a URL back. Movie Narrator owns none of that. It is a local orchestrator that calls out to an LLM you configure, uses Edge-TTS for the default voice, and renders with moviepy on your machine.
That trade is concrete. You get the multi-candidate horse race, reference-video imitation, narrator perspective selection (omniscient, character, detective), the render template system and the plugin architecture for custom TTS and LLM backends, all of which you can modify because the source is in front of you. You also get the failure modes: a local render is bounded by your CPU or GPU, the `[ml]` stack carries PyTorch, and the AGPL-3.0-or-later licence applies to the whole thing.
If your goal is one video a month and you do not want to run a model, a hosted API is less work. If your goal is a repeatable format you tune over time, with a config file you can diff, the local pipeline is the better shape.
Maintenance, upgrades and what AGPL-3.0-or-later means here
The repository is not archived and the last push was on 2026-09-16, the same day as the v1.7.0 release. The release cadence visible in the notes is roughly weekly: v1.5.2 on 2026-08-30, v1.6.0 on 2026-09-08, v1.7.0 on 2026-09-16. v1.6.0's title mentions a megafile split, CLI option aliasing and a settings ops view, which suggests ongoing internal restructuring rather than feature-only work.
Upgrade cost is mostly dependency cost. The pyproject pins are tight (moviepy `>=2.0,<3.0`, pillow `>=11.3.0,<12.0`, httpx `>=0.23,<1`), so a moviepy 3.0 or pillow 12 release will require a coordinated bump rather than a passive `pip install --upgrade`. The `[ml]` extra drags in PyTorch, WhisperX, faster-whisper, sentence-transformers and FunASR, which is the part most likely to break on a Python version change.
The licence is AGPL-3.0-or-later, and pyproject.toml declares it as `AGPL-3.0-or-later`. The practical consequence for a network service is that users interacting with a modified version over a network are entitled to the corresponding source. This is not legal advice, and the obligations depend on how you deploy it, but it is the reason some teams will not touch the project regardless of its technical merits.
Editorial conclusion
Adopt Movie Narrator if you already run an OpenAI-compatible endpoint, are comfortable on Python 3.10 to 3.13, and want the pipeline to live in your own repo rather than a vendor's dashboard: `pip install movie-narrator` then `mn create --movie "飞驰人生" --duration 60` is the whole onboarding. Do not adopt it if you need a supported SaaS with an SLA, if your runtime is Python 3.14 or newer (the `[ml]` extra is skipped there and the align and match steps soft-degrade), or if you cannot accept AGPL-3.0-or-later on a network service. Verify two things before committing: that your LLM endpoint answers the OpenAI chat-completions shape the defaults assume, and that your output directory is writable, because the pipeline writes narration.mp3, subtitle.srt, metadata.json and final.mp4 there.
Frequently asked questions
Who is considered the best movie narrator?
The README does not discuss human narrators or rank them. Movie Narrator generates narration with Edge-TTS by default, and its voice references are TTS names such as zh-CN-XiaoxiaoNeural and zh-CN-YunxiNeural.
What is a narrator in a movie?
The README does not define the general film term. It treats narration as the audio track written by the LLM and spoken by Edge-TTS, with the perspective selectable between omniscient, character and detective.
Who is a famous narrator?
The README does not name any narrators. The project is a Python toolkit for generating narration, and the only named voices in the documentation are TTS voice identifiers.
Who was the famous movie announcer?
The README does not cover announcers or film history. Its narration output comes from Edge-TTS, with the default voice set through MN_DEFAULT_VOICE in the .env file.
What is a movie narrator?
In this project it is the generated voice track rather than a person. The README describes the tool as generating movie recap videos with narration, subtitles and rendered output from a single command.
Community notes