Zhati Relationship Video Essay
This is a reusable workflow distilled from the final film "Why Do Some Good People End Up with the Wrong Partners?" The goal is not to replicate the same script, but to maintain the same production method for each new episode:
A relationship story centered on a concrete object + Song Ti large characters + cinematic/real-shot/photo texture + restrained narration + 3:4 cover.
What's Fixed Is the Method, Not the Assets
Fixed: 16-beat narrative grammar, font/palette/motion/sound standards, 3:4 cover, source and ethics hard gates, QA.
Variable: Script, narration, music, film/client footage/product/photo/licensed stock, portraits, cover background, publishing copy.
AI can search for background video itself: When the client has no footage, use scripts/stock_search.py to search Mixkit/Coverr/Pexels/Pixabay, select 3 candidates, then use scripts/fetch_stock.py to download, remove audio tracks, standardize, and write a manifest. See references/stock-sources.md for details.
The master's "Seventh Heaven," Freud, Aristotle, and Kant are only reference implementations, not required materials for every episode. If the client has real store footage, use the client's materials; if the client wants historical film examples, switch to 2–3 public domain films; if the client has no footage, create a pure text/graphic episode. Do not force a specific film or face just for "series consistency."
See references/client-brief.md and references/asset-strategy.md for detailed selection.
First, Determine Applicability
Applicable:
- Chinese emotional topics about male-female relationships, love, intimacy, boundaries, self-worth, giving and receiving, breakups and reconciliation, etc.
- Brand/organization client stories about "relationships, boundaries, respect, companionship" suitable for essay-style expression.
- Users want a 2:40–3:40 horizontal video essay with narration, subtitles, and cinematic feel.
- Users explicitly say "in the style of 'Good People and Wrong People'" or "use that previous template" or "make it a series."
Not Applicable:
- Pure product launches/sales/fast-paced montages/feature explanations; those are better suited to other formats.
- Users request clips from films still under copyright (e.g., Casablanca, In the Mood for Love) without authorization. First explain the risk; switch to public domain films or ask the user to provide authorized footage.
- Users want a 9:16 vertical final film. This template is 16:9 final film + 3:4 cover; vertical requires a complete layout redo, not just cropping.
Final Film Specifications (Default)
| Item | Default |
|---|---|
| Final Film | 1920×1080 / 30fps / 2:40–3:40 |
| Aspect Ratio | 16:9 |
| Language | Simplified Chinese narration + burned-in subtitles + SRT |
| Cover | 1080×1440 (3:4), PNG + JPG |
| Audio | Narration + original score + rain sounds, approx −15 LUFS, true peak ≤ −1.5 dBFS |
| Subtitles | Burned into the frame, plus separate .srt file |
| Deliverables | MP4, SRT, 3:4 cover, publishing copy, asset sources, editable project |
| Client Approval | Brief → First still → Final, three approval points |
Master Location (Reference Implementation)
Reference master (not distributed with this repository; only for asset/structure reference):
- On local dev machine:
~/Desktop/自媒体/good-people-wrong-person - On other machines: use
--refto point to your own master project
Do not default to the master's assets for a new episode. Using --ref is only for accessing vendor/, fonts, textures, and a placeholder audio track; films, portraits, stills, scripts, and audio must all be swapped per the client brief.
The master contains:
index.html: Complete huashu-motion composition of the 201.37-second final film.cover/cover.html: 1080×1440 3:4 cover source file.assets/movies/: Verified, de-audio-tracked, integer-frame-padded clips from Seventh Heaven (1927).assets/portraits/: Public domain portraits of Freud, Aristotle, Kant.assets/stills/,assets/textures/,assets/fonts/,vendor/.assets/score.wav: Mixed final audio (narration + score + rain) from the previous episode. Must be replaced for a new episode; do not reuse directly.output/: Previous episode deliverables, for reference only, do not copy verbatim.
If the master is unavailable: restore code from templates/index.template.html and templates/cover-3x4.template.html; re-acquire and verify film clips and portraits per references/rights-and-ethics.md.
How to Start a New Episode
SKILL="$HOME/.agents/skills/zhati-relationship-film"
$SKILL/scripts/new_episode.sh my-episode-slug --base "$HOME/relationship-films"
The script will:
- Create a new project in
$BASE_DIR/my-episode-slug(default$HOME/relationship-films, can be changed with--base); - Copy the skill's latest template code (
index.html,cover/cover.html), then copyvendor/, fonts, textures, and a set of initial assets from the master; - Copy the master's
assets/score.wavas a placeholder audio track (so the page can run initially); - Generate
BRIEF.md,文稿.txt,字幕.srt,treatment.md,素材来源.md,发布文案.md, andassets.manifest.jsontemplates; - Create
assets/imported/and print next steps and text/asset slots that need replacement.
Then follow the pipeline below. Do not skip writing new narration and new subtitles.
Pipeline
0. Read Client Brief, Lock Content + Assets
First, read references/client-brief.md and compress client requirements into a 10-line content plan:
Audience / Platform / Duration / One-sentence Theme / Hook Question / Two Concepts / Philosophical or Psychological Perspective / Ethical Turn / One Small Sentence / Asset Mode & Source
Then read references/beat-sheet.md and place the theme into the 16 narrative beats. Decide on the asset mode before writing narration: client footage / public domain film / licensed stock / photos / pure text / hybrid. Do not write 3 minutes of narration first and then ask the client for assets.
Default structure:
- Hook (a question)
- Specific story (rain/umbrella; can be replaced with another concrete object, but there must be one object running through)
- "This is a fictional story" type disclaimer
- Distinction between two concepts (goodness vs. suitability, or the episode's pair of concepts)
- Philosophical perspective A (friendship/reciprocity/respect, etc.)
- One person's limitation ("One person's effort cannot complete a relationship alone" type)
- Emotional turning point question (why hope for a next time despite sadness)
- Psychological perspective (repetition/patterns; use "one way to understand," not a diagnosis)
- Pattern recognition (effort for approval)
- Coldness and self-doubt
- Ethical turn (the harm is not your fault; responsibility lies with the perpetrator)
- Limits and exceptions (deception, change, seeing after being together)
- Self-reflection (two questions; mirror/reflection)
- Philosophical perspective B (self-respect)
- One very small sentence (an actionable statement)
- Practice and conclusion (keep gentleness, but also leave space for yourself)
- End credits/sources
If the new topic doesn't require two philosophers, keep only one; if a psychological perspective is not needed, compress beats 8–9 into one paragraph. Do not fabricate quotes or diagnoses just to fill the structure.
1. Write New Narration
- Target 950–1150 Chinese characters, roughly 3 minutes at normal speaking speed; if the user provides a script, first edit it down to a "breathable" length, but do not change their stance.
- Keep qualifying statements: "one way to understand" / "not an explanation for everyone" / "the responsibility for harm cannot be excused for the other person."
- End with a memorable "small action" or "small sentence," e.g., "I'm also cold, I also need this umbrella."
- Write into
文稿.txt, one paragraph per line, for easy subtitle generation.
2. Generate New Voiceover and New Timeline
Prioritize using the user's own local voice clone (see the macos-local-voice skill); do not upload reference recordings. If no voice is available, explicitly ask the user: personal recording / local clone / system voice / silent.
Output:
- One complete voiceover file
assets/voice.wav(48kHz, ideally 24-bit); - Start and end times for each sentence (JSON or CSV), accurate to 0.01s;
- A new
CUESarray ([start, end, text]).
Do not reuse the master's 194-second voiceover. The master's timeline is only for understanding rhythm, not as the audio for a new episode.
3. Music & Mixing
- Stick to a "piano/strings/soft ambient + rain" direction; do not use copyrighted songs.
- Mixing targets: narration clear, music at approximately −28 to −32 LUFS, overall approximately −15 LUFS, true peak ≤ −1.5 dBFS.
- Output
assets/score.wav, replacing the placeholder audio track; keep the<audio id="score" ...>tag in the page but update its duration. - This template uses
id="score"instead ofom-sound, so add--silentduring rendering; otherwiseom renderwill try to rebuild the audio track. See the "Audio" section ofreferences/visual-system.mdfor details.
4. Re-timing
This is the most underestimated step. All timings in the master are hardcoded; once the new voiceover is swapped, every scene must be re-timed.
Assign new durations to the 16 scenes according to the proportions in references/beat-sheet.md, then:
- First modify the
CUESarray, root nodedata-duration, the JS variableDUR, and<audio data-duration>. - Anchor each scene at the start of the first voiceover sentence in that segment; the scene boundary is the start of the next sentence.
- Scale animation times within each scene proportionally (new duration / old duration); do not just shift the start, or the latter half will drift.
- Recalculate video window
data-start/data-duration/data-media-start/data-playback-rate; ensure the clip doesn't finish playing before it fades out. Master clips are already padded to integer frames, but new sources need re-padding. - After each scene edit, use
om stillto checkstart+0.5s,start+2s, andend-0.5sfor residual old text, text collisions, or empty frames.
For the specific replacement checklist, see references/text-slots.md; for re-timing methods, see references/retiming.md.
5. Replace Text, Not Visual DNA
Must replace all text slots in index.html one by one (see references/text-slots.md), including:
- Film title variable
filmTitle, two-line hook; - Four paragraphs of umbrella story large text;
- "Fictional story" disclaimer;
- Labels for the two frames (goodness/suitability);
- Aristotle/Freud/Kant paragraphs and attributions;
- Cold scene, turning point, responsibility, mirror, self-reflection, action, ending, end credits;
- Every subtitle in
CUES.
Preserve:
- The color palette, Song Ti/苹方/EB Garamond combination;
- Film grain, rain, umbrella, particles, vignette, white flashes, wine-red underline;
- 16:9 left-right margin and lower subtitle band;
- The "one image, one event" rhythm; do not cram all text into one screen.
Do not keep the master's old copy. If a new episode includes a thinker other than Aristotle/Freud/Kant, re-verify the source and mark it in the frame as "paraphrase/application," not a fake direct quote.
6. Asset Replacement (Required per Client Requirement)
The master uses Seventh Heaven (1927), but this is just a reference implementation. Select a mode per references/asset-strategy.md:
- Client footage/photos/products/storefront: Prioritize; obtain clear authorization/portrait consent; keep faces real, do not over-smooth; products only appear as "objects in a relationship," not as hard ads.
- Public domain films: Can continue using Seventh Heaven or switch to 1–3 public domain films; remove audio tracks, pad frames, extract stills, annotate each source.
- AI-searched free stock: When the client has no footage, first search 3 candidates and show to the client; after confirmation, download/standardize with
scripts/fetch_stock.py. Do not scrape from YouTube/streaming services/copyrighted content; do not bypass watermarks/paywalls. Include source, license, and credit in the manifest. - Licensed stock: Retain license/order records; do not use watermarked previews.
- Photos/archives/portraits: Label as photo/statute/painting; must be public domain or client-authorized; do not use AI-generated images impersonating historical figures.
- Pure text/graphics: When there's no footage, let text and white space create the image; do not force film clips.
- Hybrid: Maximum 2–3 sources; one grade, one font set, credits per source.
After replacement, you must:
- Update the
srcfor correspondingdata-asset-slot; - Recalculate video windows with
ffprobe; - Re-extract stills;
- Update
#credit,#credits .cols, and素材来源.md; - Run
python3 scripts/asset_report.py --manifest assets.manifest.json --project ..
Do not use clips from films still under copyright (e.g., Casablanca, Roman Holiday, In the Mood for Love) unless the client provides explicit written authorization.
7. Check, Render, Review
cd "$HOME/relationship-films/my-episode-slug"
om check . --samples 6
om render . --silent --fps 30 --workers 4 --video extract
om qa out/<new-file>.mp4
Rendering takes approximately 25–35 minutes (1080p/30fps/4 workers, ~201 seconds). Do not use 720p as a substitute for 1080p.
If the local om is a wrapper script (e.g., Node/Chrome environment), point OM to it; scripts/ will try $OM, om, then ~/.agents/skills/huashu-motion/bin/om in order.
Checklist:
om checkwith 0 errors;om qawith no single-frame jumps;- Frame-by-frame check: hook, each scene boundary, turning point, Freud, ending, end credits;
- Independent cold review (ask an agent who didn't participate in production to watch the final film only); fix at least all MUST-FIX items;
ffprobeconfirms 1920×1080/30fps/correct duration/AAC 48kHz stereo;- Full video decode with no errors; loudness/peaks within spec.
8. Cover and Publishing Copy
- Cover: Copy
cover/cover.html, replace title, duration, bottom hook, source; render to 1080×1440 PNG + JPG. Template layout: small label at top + large title ("Wrong Person" in amber) + central umbrella/two people + a golden sentence at bottom + source. - Publishing copy: Per
references/publishing.md, produce long version/short version/Bilibili version/pinned comment/tags; do not reuse the previous episode's copy directly. - End credits and corner labels must retain necessary disclaimers: "Film images, not real cases" and "Interpretive perspective, not a diagnosis."
9. Delivery
my-episode-slug/output/
<slug>_1080p_30fps.mp4
<slug>_字幕.srt
<slug>_封面_3x4.png
<slug>_封面_3x4.jpg
<slug>_发布文案.md
素材来源.md
项目说明.md
Hard Gates (No Delivery Until Passed)
- New Voiceover: A new episode must have a newly recorded/generated voiceover; do not reuse the master's 194-second audio with new subtitles.
- New Text: No residual sentences from the master's copy in
index.html; go throughreferences/text-slots.mditem by item. - Copyright/Assets: Films, client materials, stock, portraits, music, and sounds all have source/authorization records; each source is credited; film title/year/"not a real case" indicators are in the frame.
- Ethics: No diagnosis, no victim-blaming, no fabricated philosopher quotes, no treating film characters as real cases.
- Visuals: No cropped text, no single-character orphans, no text overlapping subtitles; if the umbrella metaphor is still used this episode, both characters are under the umbrella in the ending.
- Audio: Narration clear, no clipping, no unexpected silence;
--silentrendering preserves the custom audio track. - Review: All MUST-FIX items from independent cold review are fixed, or explicitly documented why they were kept.
Don't
- Don't directly reuse the master's old text, old subtitles, or old voiceover.
- Don't treat Seventh Heaven/Freud/Aristotle/Kant as fixed assets; don't force them in if the client doesn't need them.
- Don't change all scenes to the same image plus the same block of text; the master has varied scene grammar.
- Don't use blue-purple gradients, neon, or AI-style starry backgrounds.
- Don't simply crop the 16:9 final film for a 3:4 cover; re-layout using
cover/cover.html. - Don't present philosopher/expert statements as "famous quotes" with quotation marks; use "he discussed/one way to understand."
- Don't use copyrighted clips, client faces, chat logs, or unreleased products without client authorization.
- Don't download backgrounds directly from YouTube/Bilibili/streaming services/copyrighted content; don't bypass watermarks, paywalls, or regional restrictions; only use clearly permitted free/licensed stock.
- Don't use diagnostic labels like "good-person-picker" or "love-obsessed" in titles; use questions, not verdicts.
File Map
references/client-brief.md: Client brief, content matrix, approval points.references/asset-strategy.md: Client footage/public domain/stock/photo/pure text/hybrid, multi-source unification, asset slots, manifest.references/stock-sources.md: Search, licensing, download, and credit for Mixkit/Coverr/Pexels/Pixabay/Commons.references/beat-sheet.md: 16-beat structure, proportions, visual events, narrative functions.references/visual-system.md: Color palette, fonts, shots, umbrella/rain, audio, cover.references/text-slots.md: Item-by-item replacement checklist.references/retiming.md: Timeline re-timing method for new voiceover.references/rights-and-ethics.md: Source/portrait/audio/ethics.references/publishing.md: Titles, long copy, short copy, Bilibili description, pinned comment, tags.templates/index.template.html: Master composition.templates/cover-3x4.template.html: 3:4 cover.templates/assets.manifest.example.json: Assets manifest template.scripts/new_episode.sh: Create new project.scripts/prepare_media.sh: Pad frames, extract stills, verify sources.scripts/render.sh: Render wrapper with--silent.scripts/render_cover.sh: Rendercover/cover.htmlto 1080×1440 PNG/JPG.scripts/verify.sh: check/qa/ffprobe/decode/loudness.scripts/asset_report.py: Check asset manifest for files/rights/credits/scenes.scripts/stock_search.py: Search free stock online, output candidates/pages/licenses.scripts/fetch_stock.py: Download, remove audio tracks, standardize to 1920×1080/30fps, and update manifest.