3.9 KiB
Runbook — source video → rendered cinematic highlight (local)
Exact steps to run one source clip end-to-end with the localpoc profile. Everything is local/offline.
Run from the repo root. Models must be provisioned first — see LOCAL-MODELS.md.
The plan is now generated automatically by the two-tier director (Tier-1 measured + Tier-2 vision), so you no longer author
montage.jsonby hand — but you can override it (see "Manual override").
1. Stage the source
cp <video> input/localpoc/highlights/source/<name>.mp4
2. Analyze + auto-direct (render stays OFF)
SERVER_ADDRESS=127.0.0.1 mvn -o spring-boot:run -Dspring-boot.run.profiles=localpoc > /tmp/app.log 2>&1 &
The scheduler ingests the file, analyzes it, and (localpoc has auto-director-enabled + vision-director-enabled)
writes director/montage.json + a minimal director/edit-plan.json automatically. Wait for
event=highlight_auto_director_completed, then pkill -f VideoClippingApplication. The Tier-2 vision pass
(moondream captioning several frames, ~25 s/frame CPU) makes this take a few minutes. Artifacts land in
output/localpoc/highlight-projects/<projectId>/.
3. Approve (rendering is gated)
echo approved > output/localpoc/highlight-projects/<projectId>/director/approved.flag
4. Render — render-enabled MUST be a command-line arg
The localpoc profile hard-codes render-enabled: false, so the VIDEO_EDITING_* env var is ignored;
override with a Spring program arg (highest precedence):
SERVER_ADDRESS=127.0.0.1 mvn -o spring-boot:run -Dspring-boot.run.profiles=localpoc \
-Dspring-boot.run.arguments="--video-clipping.editing.highlight-scheduler.render-enabled=true" \
> /tmp/render.log 2>&1 &
MusicGen generates the score (~95 s CPU) → FFmpeg render. Wait for final.mp4 at the project root, then
pkill -f VideoClippingApplication. Output: output/localpoc/highlight-projects/<projectId>/final.mp4.
5. Re-render after editing the plan/code
The render scanner skips projects with a root final.mp4 / status RENDERED. Reset:
BP=output/localpoc/highlight-projects/<projectId>
rm -f $BP/final.mp4 $BP/final-preview.mp4 $BP/render-manifest.json; rm -rf $BP/highlights/* $BP/project-render-work
python3 -c "import json;p='$BP/project.json';d=json.load(open(p));d['status']='WAITING_FOR_DIRECTOR';json.dump(d,open(p,'w'),indent=2)"
Then repeat step 4.
Manual override (optional)
To hand-author the cut instead of the auto-director, write director/montage.json yourself (it takes
precedence over edit-plan.json at render — HighlightDirectorFlowService; the render scanner still needs
edit-plan.json to exist — HighlightDirectorPlanScanner). Schema:
{projectId, sourceVideoFileName, grade("hero"), musicDirection, voiceover[], overlays[{text,timelineStartSeconds,timelineEndSeconds,placement}], shots[{sourceStartSeconds, durationSeconds, zoom, speed}]}. Shot durationSeconds = TIMELINE seconds;
source consumed = durationSeconds * speed (speed < 1 = slow-mo).
Gotchas
- HF downloads: export
HF_HUB_DISABLE_XET=1(the xet CDN times out on some networks; classic HTTPS works). - Sandbox / temp dir: if the app dies with
Operation not permittedon a socket bind or/var/folders/.../T(Tomcat/@TempDir), the environment restricted the default$TMPDIR/network. Run the app JVM with-Dspring-boot.run.jvmArguments="-Djava.io.tmpdir=<writable dir>"and Maven tests with-DargLine="-Djava.io.tmpdir=<writable dir>"(JaCoCo still attaches). - Measure output:
ffprobegeometry +ffmpeg -i final.mp4 -filter_complex ebur128=peak=true -f null -(target ≈ −16 LUFS, TP ≤ −1.5) +blackdetect/silencedetect. A valid MP4 is not proof of cinematic quality — that needs a human creative review (seecinematic-highlight-acceptance-review.md).