Communitygithub.com

AI Documentary Production

Produce Chinese character/theme short films with a duration determined by the brief, covering the full workflow from brief to delivery: fact-checking, narration, beats, segments/cuts/keyframes, first frames, H3 production package, review, editing, music, final check, and delivery. 30-second and 3-minute films are just examples, not hard limits.

What is AI Documentary Production?

This AI agent skill is designed for producing Chinese character/theme short documentaries where the runtime is dictated by the client brief rather than a fixed template. It guides an AI agent through a comprehensive 9-stage pipeline (G0-G8): from brief creation, historical fact-checking, and narration writing, to storyboard beat crafting, frame generation via GPT and H3 (a specific video generation model), rough cut, sound design, final QC, and delivery. The workflow enforces strict ‘gates’ between stages, ensuring that no costly video generation occurs until the narrative and visuals are locked. Key features include a ‘narration-first’ approach (multiple shots per narration line, not vice versa), support for static opening cards, model routing that delegates text to DeepSeek and image/video to GPT/H3, and a range of validation scripts to check structural integrity, timing, and costs. The skill is intended for use with AI coding tools like Claude Code or Cursor, providing a structured, repeatable production process that controls costs and maintains clear attribution.

Works with✓Claude Code✓Codex CLI~Cursor
npx skills add https://github.com/yinguozhang/ai-documentary-production/tree/HEAD

Ask in your favorite AI

Open a new chat with this agent skill pre-loaded.

Documentation

What does AI Documentary Production do?

First Use: Environment Setup

  1. Images: By default, the user generates images with GPT; AI does not call image APIs; image_mode=agent requires explicit approval.
  2. Environment: Python 3.10+, ffmpeg, ffprobe; contact_sheet.py additionally requires Pillow; no PyYAML dependency.
  3. H3: If you haven't configured MiniMax H3, first check references/00_setup.md:
    • Register/verify identity/recharge on the open platform;
    • Create an API Key;
    • Set the MINIMAX_API_KEY environment variable or use a key file;
    • Align base_url / model name / resolution;
    • Run a 4-second test first, then batch.
  4. Keys should never be included in code, logs, or git.
  5. If H3 is unavailable, switch providers or create an animatic first; do not pretend to generate.
  6. If H3 is not configured, do not proceed to G5.

When to Use

  • User wants to create a character/theme short film, with duration determined by the brief;
  • 30 seconds, 1 minute, 3 minutes are just examples, not hard limits;
  • Involves real people, historical materials, AI reenactments;
  • Needs to go from zero to a deliverable finished film;
  • Requires cost control, source retention, and credits writing.

Not Applicable

  • Multi-character portraits, interview-style feature films;
  • Commercial advertisements, pure product videos;
  • Full animation, full virtual production;
  • On-site documentaries requiring real filming.

Duration has no hard threshold; extra-long projects require additional asset management, but the workflow remains the same.

Must Ask Before Starting

  1. Finished film duration, aspect ratio, frame rate, language, platform;
  2. Who is the character, which part of the story, which facts cannot be wrong;
  3. Budget ceiling, whether retries are allowed;
  4. Who generates images (image_mode=human/agent), which video model, which editing software;
  5. Whether narration is real voice or TTS; whether music is a separate track;
  6. Whether historical photos/music licenses exist; whether an AI disclaimer is needed;
  7. Delivery format and deadline;
  8. Profile: short (approx. 15–60s) / standard (approx. 2–5min) / custom (as needed);
  9. model_routing: hybrid / gpt_only / codex_deepseek;
  10. Whether H3 is configured (Key/base_url/model/quota); if not, teach configuration first;
  11. Opening card: none / static; how many seconds; whether it counts toward the target duration; title text to be finalized at G2.5.

Without a brief, do not proceed to research.

Duration and Profile

Duration is determined by duration_target_sec in project.yaml, not hardcoded.

profileexample durationshots (example)segments (example)music (example)
short15–60s8–181–21 segment
standard2–5min24–603–53–5 segments
customuser-defineduser-defineduser-defineduser-defined

These are estimates, not gates; 30 seconds and 3 minutes are just two common examples.

G4 Image Handoff

After prompts are completed, first remind the user to generate images, then work in parallel:

  1. Send image_batch_request.md: shot number, filename, prompt location, quantity, priority; if opening card is enabled, 0-1_card.png goes into the first batch;
  2. State clearly: "You can start generating images now";
  3. Once the user starts, the agent does work that does not depend on images/video: subtitles, cue sheet, cost table, sources/credits, editing skeleton, QA for next batch of prompts;
  4. Do not review images, generate video, or do final compositing;
  5. After the user returns images, review them first; do not re-discuss already locked narration/shots;
  6. Opening card is a static card, do not use H3; verify text character by character; if Chinese is unstable, switch to post-production overlay.

Do not silently work on other things and keep the user waiting; the image generation task must be handed off first. See references/13_parallel_work.md for details.

Model Routing

Default is hybrid:

StageModelTask
G0–G3Codex + DeepSeekbrief, research, narration, storyboard, prompts
G4GPTgenerate/review images; image_mode determines who generates
G5–G8Codex + DeepSeektasks, costs, editing files, QC; temporarily switch to GPT when reviewing images
  • Use DeepSeek for text and files, GPT for pixels and visuals;
  • image_mode=human: user generates with GPT; image_mode=agent: Codex + image tools generates (requires explicit approval);
  • Write image_handoff.md before switching; project files serve as handoff credentials;
  • See references/10_model_routing.md for details.

9 Stages and G0–G8 Gates

StageDeliverableGate
G0 Briefproject_brief.mdDuration, budget, rights, platform locked
Research/Fact Checkfact_check.csv, research.mdG1 Facts locked
Script/Narrationscript.md, vo.csv, vo_text_review.md, voice_audition.md, vo_lock.md, vo_review.mdG2 Narration locked (copy + voice + version)
Storyboard/Timelinebeats.csv, shots.csv, segments.csv, timeline.csv, animatic.mp4, v0_review.mdG3 Beats claimed + shot table + v0 confirmed
First Frames (per image_mode)first_frames/, image_review.md, image_handoff.md, image_batch_request.mdG4 First frames locked
Video Generationh3_package/, clips/, tasks.json, cost.csvG5 Video locked
Rough Cut/Subtitlescut/, subtitles.srtG6 Picture locked
Music/Soundmusic/, cue_sheet.csvG7 Sound locked
Final QC/Deliveryfinal.mp4, final_qc.md, credits.mdG8 Delivery

Rule: Do not proceed to the next gate until the current one is passed; do not spend money.

Opening Card

Only ask at G0: "Do you want one, how many seconds, does it count toward the target duration"; title text is finalized at G2.5.

  • G0: opening_card: none|static; opening_seconds; opening_in_target;
  • G2.5: Main title/subtitle/font style; opening_card.md character-by-character confirmation;
  • G3: Written as a 0-1 static shot in shots.csv (static=yes, no narration), a CARD row in segments.csv (static=yes);
  • G4: Goes into the first image batch, filename first_frames/0-1_card.png; verify text character by character when images come out;
  • G5: Do not use H3; export_h3.py skips static=yes; do not include it in the H3 task table;
  • G6: Static hold in editing; can apply a slow 1–2% push-in;
  • Opening card duration is deducted from the target duration or explicitly added to the total length, decided at G0.

The opening card is a "duration decision during project initiation", not a "decoration option when generating images".

Narration Review Order

  1. Copy Review: Show the user the full vo.csv, timecodes, and fact notes; get user confirmation before doing voice;
  2. Voice Audition: Generate 2–3 candidates for the same sentence, let the user choose A/B/C or record their own;
  3. Full Scratch: Generate the complete narration with the chosen voice;
  4. v0 Animatic: Only then create static frames + narration;
  5. Do not proceed to the next step without confirmation at any step.

Narration First

This is the core sequence of the skill:

  1. Finalize narration first, then shots, first frames, video;
  2. One narration line matches 2–3 shots as the norm;
  3. One shot per line is a special case (short reaction, slogan, single-shot montage), not the default;
  4. Narration stands independently as vo.csv, do not fragment by shot;
  5. Do not generate TTS per shot; generate per sentence/paragraph, place the entire segment on one audio track;
  6. Each sentence carries one piece of information; every 1–2 sentences contains at least one hard fact (year/person/number/action/cause-effect);
  7. Poetic imagery must have a concrete anchor, a chain, and be grounded; "door/seed" can be a motif, not an automatic error; anchorless slogans are empty words; explain cause and effect first, then poetic language;
  8. After writing, run narration_lint.py, then read once to finalize;
  9. When editing, use J-cut/L-cut: picture cuts, narration continues;
  10. Leave 0.3–1.0 seconds of breathing room between sentences; do not force a 5-second narration onto a 5-second shot; it is best to bear the breathing room with a short shot without narration, not inside a shot with narration;
  11. Breathing room should only be placed between narration sentences; cut points must fall within the breathing room, not inside a sentence with narration;
  12. After narration is locked, do not directly modify the old version; first run vo_diff.py, only change affected files;
  13. One narration segment can span multiple shots; a normal shot should have at most one narration segment; a long_take=yes shot can contain multiple narration segments, but each must be completely within the shot;
  14. The breathing room window between adjacent narrations must contain at least one shot cut point; sentence start/end can fall inside the shot, not required to align with the cut point; when there is a range, use the larger breathing room;
  15. After finishing shots.csv / timeline.csv, first produce a v0 animatic (static/black frames + narration), explicitly remind the user to listen for breathing room between sentences; confirm before proceeding to first frames/video;
  16. Show the copy first, then determine the voice, then make v0: without user confirmation of copy and voice, do not generate TTS/animatic.

First the narration, then the visuals; not 40 shots first, then cram a sentence into each one.

File Contracts

shots.csv

id,story_segment,scene_id,duration,shot_size,camera,scene,action,expression,vo_ids,anchor,first_frame,video,status,cost,notes,long_take,static
  • story_segment is the narrative segment number, not the H3 generation segment; generation segments are in segments.csv under generation_id;
  • scene_id is the scene number, must match segments.csv;
  • duration in seconds, supports decimals;
  • status only uses todo/image_ready/video_running/video_ok/conditional/retake/final;
  • vo_ids can be empty; a normal shot should have at most one vo_id; a long_take=yes shot can write V01|V02;
  • long_take=yes: one continuous long take, allows 2+ narration segments, but each must be completely within the shot;
  • static=yes: static opening card/insert card, do not use H3; must have a first_frame, use a static=yes segment in segments.csv;
  • This is the source of truth for visuals; narration is in vo.csv, linked via vo_ids.

vo.csv

vo_id,start,end,text,shot_ids,notes
V01,0.0,4.2,"A complete narration line","1-1|1-2","4.2s; 0.8s breathing room after"
V02,5.0,6.2,"Next line","1-3","1.2s; 0.8s at the end"
  • start/end are absolute seconds;
  • One narration line can span 2–3 shots;
  • One shot per line is only used in special cases;
  • Leave 0.3–1.0 seconds of breathing room between sentences;
  • One shot_id can belong to only one cue; one cue can cover multiple shots;
  • Subtitles are generated from vo.csv, not bound to shots.

beats.csv

beat_id,story_segment,kind,shot_id,vo_id,text,notes
B01,1,action,1-1,V01,Calculating behind the counter,
B02,1,action,2-1,V02,Putting the paper into an envelope,
  • A beat is the smallest unit of story, not a musical beat;
  • Each beat is exactly claimed by one shot_id;
  • Each non-static shot has at least one beat; static=yes opening cards can have no beat; each narration segment has at least one beat;
  • One narration can span multiple beats, repeating the same vo_id on each row;
  • Beat order must be consistent with shot order; missing, duplicate, or out-of-order beats are caught by validate.py.

segments.csv

generation_id,scene_id,cut_order,shot_id,start,end,duration,keyframe,static,notes
S01,1,1,1-1,0,5,5,first_frames/1-1_first.png,no,single-cut segment
S02,1,1,1-2,5,9,4,first_frames/1-2_first.png,no,cut 1 within segment
S02,1,2,1-3,9,15,6,first_frames/1-3_first.png,no,cut 2 within segment
  • generation_id = one H3 generation; a segment ≤15 seconds, does not cross scenes;
  • scene_id must equal the scene_id of the same shot in shots.csv; scene change requires a new segment;
  • cut_order = the cut order within the segment, starting from 1 sequentially;
  • keyframe = composition anchor image for this cut; cut 1 pins at 0.00 seconds, subsequent cuts pin at the cut point;
  • static=yes = static card, not for H3; must be a single cut; export_h3.py will skip;
  • Each shot can only appear in one generation;
  • Each cut's start/end/duration must equal the cumulative start and end in shots.csv; the entire film must have no gaps and no overlaps;
  • validate.py catches overruns, misalignments, gaps, and duplicates.

h3_prompts.csv

shot_id,prompt,soundscape,notes
1-1,"Maintain the first frame; the pen tip moves slowly, the lamp flame sways gently.","Sound of paper and pen, distant wind.",
  • export_h3.py groups by segments.csv and stitches each cut's prompt into a multi-image alignment prompt;
  • Outputs h3_package/<generation_id>/prompt.md + manifest.json;
  • Does not call APIs; generation is still executed by the H3 task table.

Narration Versions

vo_versions/vo_v1.csv
vo_v1_scratch.wav
vo_lock.md
  • Before locking, do a read-through/TTS, measure actual duration;
  • After locking, only add new versions, do not directly modify the old version;
  • To change narration, first run vo_diff.py, then modify affected files;
  • See references/12_change_control.md for details.

project.json

Machine configuration generated by init_project.py: profile/model_routing/image_mode/duration_target_sec/shot_target/fps/resolution/providers. project.yaml is the human-readable version; scripts read project.json.

tasks.json

[{"generation_id":"S01","provider":"minimax_h3","model":"MiniMax-H3","resolution":"768P","duration":9,"status":"todo","prompt":"h3_package/S01/prompt.md","first_frames":["first_frames_h3/1-1_first.png"],"cost_cny":0.0}]
  • generation_id corresponds to the generation segment in segments.csv;
  • duration must be an integer between 4 and 15;
  • prompt / first_frames are paths to the production package;
  • Failed tasks are not billed; retries are listed separately;
  • Old per-shot tasks can use id, but h3_tasks.json always uses generation_id.

Delivery Package

final.mp4
subtitles.srt
vo.wav
vo.csv
music/A-E.wav + cue_sheet.csv
credits.md
source_list.csv
fact_check.csv
final_qc.md

Hard Rules

  1. Images are default generated by the user via GPT; AI does not call image APIs; image tools are only allowed when image_mode=agent and the user explicitly approves;
  2. Video defaults to a single version; only add a second version if the first is unusable;
  3. Generated video is only for ambient sound/dialogue, not for music/BGM;
  4. 768P source material may be 1344×768 (7:4), final delivery at 1920×1080;
  5. First frames must be 16:9, otherwise image-to-video aspect ratio will drift;
  6. Historical photos must cite sources; AI visuals must be labeled "reenactment";
  7. Subtitles: 16–20 characters per line, max 2 lines, ≥100px left/right margins;
  8. Each music segment should have 1.5–2 seconds of handle; low point is not silence;
  9. Costs are calculated based on task logs, not from memory;
  10. Before delivery, use ffprobe to verify resolution/frame rate/audio;
  11. First finalize narration, then shots; default is one narration line spanning 2–3 shots; one shot per line is a special case;
  12. Narration should not fill the entire shot; a 5-second narration paired with a 5-second shot will feel rushed; leave 0.3–1.0 seconds of breathing room between sentences;
  13. Narration can be poetic, but poetry must have physical/action anchors; only the explanatory section requires one hard fact per sentence; do not mix the two standards;
  14. After narration is locked, do not rewrite the entire project because of one changed line; first run vo_diff.py, then only modify affected files;
  15. After G4 prompts are completed, first remind the user to generate images; only after the user starts generating should you work on parallel tasks that do not depend on images/video;
  16. One narration segment can span multiple shots; a normal shot should have at most one narration segment; a long_take=yes long shot can contain multiple narration segments, but all must be within the shot;
  17. The breathing room window must contain the shot cut point; do not require sentence start/end to align with the cut point; when there is a range, use the larger breathing room;
  18. After the v0 animatic is produced, first remind the user to check the breathing room between sentences; do not produce first frames or generate video before confirmation;
  19. The voice must be auditioned with 2–3 candidates and selected by the user; do not default to a specific TTS;
  20. Narration defaults to "clear but not plain": first explain the character/event/cause-effect, then use concrete imagery and short sentences to create space; allow adding 1–2 sentences, but each must bring new information or a new image; do not pad with adjectives;
  21. Each beat in beats.csv must be claimed by exactly one shot; each shot and each narration segment must have beats covering them; missing, duplicate, or out-of-order beats are caught by validate.py;
  22. segments.csv: one segment ≤15 seconds; cut order within the segment is sequential, each cut has a keyframe, each shot appears only once; the start/end of each cut must equal the cumulative time in shots.csv; use export_h3.py to produce the H3 multi-image alignment production package;
  23. Opening card: G0 sets duration, G2.5 sets text, G3 writes 0-1 static=yes, G4 generates image, G5 does not use H3.

Provider

config/providers.yaml is documentation; the machine configuration is providers.json (generated by init_project.py, validated by timeline.py).

Defaults: images=user_gpt, video=minimax_h3, narration=capcut_tts, music=local_midi_fluidsynth, editing=capcut, QC=ffmpeg.

The image provider is always human; this does not change with configuration.

Commands

python scripts/init_project.py --root my-film --profile short --duration 30 --shots 10 --segments 2
python scripts/timeline.py --shots shots.csv --vo vo.csv --vo-out vo_report.csv --project project.json --min-gap 0.4
python scripts/timeline.py --shots shots.csv --vo vo.csv --max-density 0.85 --allow-single
python scripts/narration_lint.py --text vo.csv --style lyrical --max-chars 28
python scripts/validate.py --shots shots.csv --vo vo.csv --beats beats.csv --segments segments.csv --project project.json
python scripts/validate.py --shots shots.csv --vo vo.csv --beats beats.csv --segments segments.csv --project project.json --strict-files
python scripts/validate_tasks.py --tasks h3_tasks.json --segments segments.csv
python scripts/selftest.py
python scripts/export_h3.py --shots shots.csv --segments segments.csv --prompts h3_prompts.csv --out h3_package
python scripts/timeline.py --shots shots.csv --vo vo.csv --animatic animatic.mp4
python scripts/vo_gap_report.py --vo vo.csv --audio vo_scratch.wav --out vo_gap.md
python scripts/vo_diff.py --old vo_versions/vo_v1.csv --new vo.csv --out vo_diff.md
python scripts/vo2srt.py --vo vo.csv --out subtitles.srt --max-chars 18
python scripts/contact_sheet.py --clips clips --out review --frames 6
python scripts/cost_report.py --tasks tasks.json --out cost.csv --default-model MiniMax-H3

Scripts: init_project.py, validate.py, selftest.py, export_h3.py, timeline.py, narration_lint.py, vo2srt.py, vo_gap_report.py, vo_diff.py, contact_sheet.py, cost_report.py. --animatic defaults to black frames if first frames are missing; --animatic-missing error can change this to error out.

validate.py handles structural contracts (schema / beats / segment cuts / coverage); G3 does not check keyframe files by default, G5 checks with --strict-files. timeline.py --vo handles timing (breathing room / density / long takes). Run both; they are not interchangeable.

Error Handling

  • Video failure: Check task status; failed tasks are not billed; switch to H3-Max or modify the first frame, do not blindly re-run;
  • Face changes/multiple hands: Regenerate or switch to profile/back view;
  • Action did not occur: Regenerate, do not fix in editing;
  • Subtitle overflow: Change style/break lines, do not shrink to unreadable;
  • Music jarring: Add pickup, expression ramp, handle; do not hard cut;
  • Export proportion wrong: Go back to project and set 1920×1080, do not stretch.

References

  • SOP.md: Human-readable workflow and checklist
  • references/: Stage details (including 00_setup.md, 09_vo_spans.md, 10_model_routing.md, 11_narration.md, 12_change_control.md, 13_parallel_work.md, 14_v0_animatic.md, 15_beats_segments.md)
  • providers/: Replaceable tools
  • templates/: Project card, shot table, prompts, review forms, cue sheet, credits, final QC

Related Skills