Production defaults for every AI: Start with PRODUCTION_RULES.md.
The OpenAI, Gemini, DeepSeek and AW360 script paths load one shared policy; real-input graphics renders require a production review. Gameplay can retain original audio without added music. Civic and election explainers use politics mode (python policy_tool.py prompt --mode politics; see PRODUCTION_RULES.md). Export the policy to another assistant with python policy_tool.py prompt, and check a plan with python policy_tool.py check production.json. These checks do not guarantee audience performance or replace final-media review.
A Python toolkit for automated short-form video production. It selects source footage, scores it with licensed music, strips unwanted subjects out of the frame, and renders finished vertical cuts with FFmpeg.
- Automated editing — picks a segment from a source clip, crops to 9:16, applies colour grading and fades, and renders a finished short.
- Music scoring — searches the Epidemic Sound catalogue for a track matching a mood query, caches the download, and mixes it under the footage.
- YouTube b-roll —
youtube_broll.pyfills gaps the stock libraries can't, pulling only the seconds it needs, cutting on the longest uninterrupted shot, and logging credit for everything it caches. - Space media —
space_media_sourcer.pysources spaceflight footage and imagery from NASA and SpaceX for space videos, ahead of the generic stock libraries. - Subject detection — OpenCV-backed passes that scan frames for people or body parts so clips can be filtered down to hardware-only footage.
- Voiceover — narration through a local Voicebox TTS server, Edge TTS, or OpenAI voices.
- Licence checking —
check_licensing.pyverifies the state of your Epidemic Sound account before you publish.
- Python 3.12+
- FFmpeg and
ffprobeon yourPATH - API keys for the services you intend to use (see below)
python -m venv .venv
.venv\Scripts\activate # Windows; source .venv/bin/activate elsewhere
pip install -e . # or: uv sync
cp .env.example .env # then fill in keys and media pathsAll file locations are configured through .env. Nothing is hardcoded — set
MEDIA_ROOT to wherever your source footage lives and the per-category folders
are derived from it, or override each one individually.
python main.py # main pipeline
python create_military_short.py # military-footage short builder
python check_licensing.py # verify Epidemic Sound licensing
python search_music.py # search the music catalogueeditroom_tool.py adds the post-production departments beyond audio
sourcing: transcription with speaker turns, multicam sync, silence/filler
detection, proxies, a JSON timeline with edit actions and FCPXML/EDL export,
transcript-driven assembly, B-roll search, house-styled captions, subject
tracking auto-reframe, dialogue clean-up, music ducking, ADR with the approved
voice, shot matching and LUTs. See EDITING_ROOM.md.
python editroom_tool.py transcribe raw/interview.mp4 --output work/transcript.json
python editroom_tool.py assemble raw/interview.mp4 --transcript work/transcript.json --brief "why the launch was scrubbed" --output work/cut.json
python editroom_tool.py render work/cut.json --output work/clean.mp4 --work work/segmentsBoth video agents — pipeline.py and the AW360 director — fall through to
YouTube when Pexels and Pixabay return nothing usable. The tier is also a
standalone tool:
python youtube_broll.py --query "aerial drone forest fog" --duration 6
python youtube_broll.py --query "storm clouds timelapse" --count 3
python youtube_broll.py --attribution # print the credit ledgerWhat it does per clip:
- Searches YouTube behind its Creative Commons filter, then re-checks the licence each candidate actually reports.
- Rejects live streams, age-gated uploads, anything under
YOUTUBE_BROLL_MIN_HEIGHT, and sources too short to cut from. - Downloads a probe window instead of the whole video — intro and outro trimmed, offset derived from the query so repeated scenes don't reuse the same footage.
- Runs FFmpeg scene detection over that window and cuts from the longest uninterrupted shot, so the clip doesn't straddle an edit.
- Normalises to a muted 1080x1920 clip. B-roll is video-only; narration and music are added by the renderer, so source audio is never downloaded.
Everything is cached under assets/materials/youtube/. A repeat request for the
same query and clip length reuses the clip it already cut — without that, YouTube
reorders its results between runs and the same scene would download something
new each time. --count still returns distinct clips.
Tuning lives in .env (YOUTUBE_BROLL_*) — most usefully
YOUTUBE_BROLL_PRIORITY to move the tier ahead of the stock APIs (first) or
switch it off (off).
Space scenes are sourced from NASA and SpaceX before the generic stock libraries — the footage is public domain and a far better match than whatever "rocket" returns from a stock search. The tier only engages when the scene keywords look like spaceflight or astronomy, so it costs nothing on the gaming and military scenes.
python space_media_sourcer.py --query "saturn v apollo launch" --duration 6
python space_media_sourcer.py --query "deep space nebula" --stills-only
python space_media_sourcer.py --check # which upstream APIs are reachable
python space_media_sourcer.py --attribution # print the credit ledgerSources, tried in order:
- NASA Image and Video Library — real MP4 footage, no API key needed.
- SpaceX via Launch Library 2 — the launch photo on each past SpaceX launch, plus launch webcasts, whose YouTube ids are handed to the b-roll pipeline so the footage gets cut the same way.
- NASA library again, broadened — NASA's search is literal, so
rocket grid fins deployment steeringmatches nothing whilerocketmatches thousands of clips. A miss retries with progressively shorter queries anchored on the space terms before anything else is tried. - NASA APOD — high-resolution astronomy stills. Uses
NASA_API_KEY; without one it falls back to the heavily rate-limitedDEMO_KEY. APOD has no search endpoint — it only serves a date or a random pick — so it is consulted only for astronomy scenes (nebula, eclipse, night sky). A scene about landing legs never gets a random galaxy.
Stills get a slow Ken Burns push rather than being held static, because a frozen frame under narration reads as a broken video.
SpaceX data source.
api.spacexdata.comwas archived in June 2026 and now fails TLS (Cloudflare525), so the tier reads Launch Library 2 directly — the same upstream that API was built on. It is free without a key at 15 requests an hour; the first run pages the SpaceX archive intoassets/materials/space/spacex_launches.json(resuming later if the quota runs out) and after that a refresh is one request a day. SetLL2_API_KEYfor a higher limit. Every call treats absence as normal and falls through to NASA.
Music retrieved through the Epidemic Sound API is licensed to your account.
Downloaded audio lives in assets/ and is deliberately excluded from this
repository — do not redistribute it. Likewise, output/ holds rendered video
and is not tracked.
Source footage is your own responsibility: confirm the rights on anything you publish, particularly third-party or government-released material.
NASA material is public domain, with the caveats NASA itself publishes: its
logos and insignia are restricted, and the media library hosts some third-party
content that only NASA has cleared. SpaceX has released its launch photography
into the public domain. APOD is the exception — it frequently features privately
owned astrophotography, so entries carrying a copyright field are recorded as
permission required rather than public domain. All of it lands in
assets/materials/space/ATTRIBUTION.md.
YouTube b-roll defaults to YOUTUBE_BROLL_LICENSE=cc, keeping only videos
YouTube reports as Creative Commons. Those permit reuse with credit — the
generated assets/materials/youtube/ATTRIBUTION.md lists title, channel, source
URL and licence for every cached clip, and that credit has to travel with the
finished video. Setting the variable to any widens the pool to standard-licence
uploads, which are not cleared for reuse; clearing them is on you.