video_editing_poc/docs/RUNBOOK-highlight-e2e.md

3.9 KiB
Raw Blame History

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.json by 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 permitted on 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: ffprobe geometry + 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 (see cinematic-highlight-acceptance-review.md).