67 lines
3.9 KiB
Markdown
67 lines
3.9 KiB
Markdown
# 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`](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
|
||
```bash
|
||
cp <video> input/localpoc/highlights/source/<name>.mp4
|
||
```
|
||
|
||
## 2. Analyze + auto-direct (render stays OFF)
|
||
```bash
|
||
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)
|
||
```bash
|
||
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):
|
||
```bash
|
||
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:
|
||
```bash
|
||
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`](cinematic-highlight-acceptance-review.md)).
|