--- name: video-editing-run-and-operate description: "Operate the video-editing service safely: choose and start exactly one of its REST clipping, folder segmentation, multi-clip cinematic edit, or single-source highlight workflows; perform preflight, ingest and approve work, locate artifacts, inspect health and queue state, quarantine failures, and stop or resume jobs. Load this skill for runtime commands, operator incidents, local-model readiness, output locations, scheduler behavior, or deployment-readiness questions." --- # Run and Operate Video Editing Use this runbook from the repository root. It describes code verified on **2026-07-21**. ## Scope and safety boundary Operate only an explicitly approved workflow. The checked-in `application.yml` still enables folder ingestion, editing, both editing schedulers, local worker auto-start, and heuristic fallback, while highlight rendering now defaults off and director approval defaults on. A plain `mvn spring-boot:run` or packaged-JAR start can therefore claim input and invoke the network-capable local-CV bootstrap path. The `cinematic-editing-local` profile explicitly enables the separate local-director auto-render path behind its approval flag. `video-editing-change-control` is authoritative for the seven no-waiver prohibitions. Their operating consequences are: - automatic dependency or model downloads; - no network use for model/media inference or acquisition, including loopback RPC, and no external AI; use in-process or approved non-network IPC with pre-provisioned artifacts; - unlicensed music, SFX, fonts, LUTs, models, or footage; - silence, generated tones, or heuristic analysis presented as production assets or evidence; - rendering without a reviewed plan and approval artifact; - a production-facing default change outside change control. **Current implementation warning:** strict asset readiness now fails startup and the Java/Python asset workers no longer accept silence, tones, or host speech as successful fallbacks. The repository still lacks resident Piper, MusicGen, and AudioGen model artifacts, and the standalone bootstrap script remains prohibited. Do not start the production profile until approved local paths are provisioned. ### When not to use this skill | Need | Use instead | |---|---| | Change a flag or add a profile | `video-editing-config-and-flags` | | Install tools or reconstruct the build | `video-editing-build-and-env` | | Diagnose a failure after locating its state | `video-editing-debugging-playbook` | | Decide whether an output passes | `video-editing-validation-and-qa` | | Change runtime behavior or promote it | `video-editing-change-control` | | Measure FFmpeg, queue, storage, or media behavior | `video-editing-diagnostics-and-tooling` | ## Definitions | Term | Meaning here | |---|---| | Claim | An atomic move from a source directory to a working directory. The source name is not available for a second worker after the move. | | Publish | Copy or upload a completed artifact to its externally consumed location. | | Approval artifact | The current plain `approved.flag` scheduler signal. Its contents are not validated, so it is not production authorization. | | Quarantine | Move failed input to `rejected`, or leave/rename it in `working` when that move fails. | | Local model | Model weights provisioned before startup on the same runtime host; no request may fetch weights or call an external inference service. | | Project store | A filesystem tree below `output/edit-projects` or `output/highlight-projects`; it is not PostgreSQL-backed. | ## Current system versus production target | Concern | Current, verified | Required production target | |---|---|---| | Runtime packaging | Spring Boot JAR; no container or deployment manifest | One immutable platform-neutral application artifact plus signed platform-specific runtime/model/image bundles, each promoted without rebuild for the same target | | REST metadata | Memory by default; `jpa` profile uses H2 in-memory | PostgreSQL with validated migrations, backup/restore, credentials, TLS, readiness, and persistent queue | | REST media | Memory adapter emits example URLs and stub bytes; S3 adapter exists | Approved object storage with real multipart lifecycle, least privilege, encryption, retention, and integration evidence | | Edit/highlight state | Local filesystem | Durable shared storage or an explicitly justified single-writer volume with recovery evidence | | Highlight intelligence | Noncompliant loopback CV endpoint plus manual/external director-plan creation | All required director, vision, voice, music, and SFX models pre-provisioned; inference uses in-process or non-network IPC and fails closed | | Asset failure | Non-strict readiness can log and continue, but synthesis now rejects missing/unlicensed models and inaudible output; requested render assets require license sidecars | Production startup must fail closed; add checksum, origin, allowed-use, and creative-quality gates beyond the current sidecar/audibility checks | | Security | No Spring Security; Actuator exposes health, info, metrics, Prometheus | Authentication (AuthN), authorization (AuthZ), secured Actuator, restrictive network policy, audit trail, redaction, and threat-model gates | There is no production profile, Open Container Initiative (OCI) image, Compose file, Kubernetes/Helm definition, or cloud deployment contract in this repository. Do not invent a deployment command. A Linux/VPS/cloud run is a **target**, not a certified procedure. | Profile | Verified effect and operational status | |---|---| | no profile | Unsafe all-on file schedulers/editing defaults from `application.yml`; API uses memory/stub adapters. | | `cinematic-editing-local` | Disables folder segmentation but enables local director auto-render with an approval gate; it does not disable the highlight scheduler inherited from base configuration. Do not use as a safe baseline. | | `folder-scheduler-local` | Enables folder segmentation but does not disable inherited editing/highlight defaults. Do not use as an isolated folder lane. | | `jpa` | Selects JPA and DB queue with H2 in PostgreSQL compatibility mode and stub processing. It is not a PostgreSQL production profile. | ## Preflight every run Run read-only checks before approval. These commands neither start the service nor modify repository files: ```bash java -version mvn -version ffmpeg -version ffprobe -version test -f pom.xml test -f target/video-editing-1.0-SNAPSHOT.jar ``` The project requires Java 21. An offline Maven command fails instead of downloading missing dependencies: ```bash mvn -o -DskipTests package ``` Do not replace `-o` with an online build. Provision Maven artifacts through an approved, audited build process. Do not run either `tools/run_local_cv_worker.sh` or `tools/run_local_asset_worker.sh`: their `auto` modes can create virtual environments, install packages, and load/download a YOLO model. Before enabling any media workflow, check directories and binaries without starting it: ```bash test -x "$(command -v ffmpeg)" test -x "$(command -v ffprobe)" find input -maxdepth 4 -type f -print 2>/dev/null find output -maxdepth 4 -type f -print 2>/dev/null ``` Treat every listed input as work that a scheduler may claim. Confirm ownership, license, retention, and approval before continuing. ## Disabled-first baseline Use this exact baseline for inspection-only startup. It binds to loopback, disables all file schedulers, editing, local worker bootstrap, rendering, fallbacks, and cleanup. `-o` prevents Maven dependency downloads. ```bash env \ SERVER_ADDRESS=127.0.0.1 \ FOLDER_SCHEDULER_ENABLED=false \ VIDEO_EDITING_ENABLED=false \ VIDEO_EDITING_LOCAL_DIRECTOR_ENABLED=false \ VIDEO_EDITING_HIGHLIGHT_SCHEDULER_ENABLED=false \ VIDEO_EDITING_HIGHLIGHT_SCHEDULER_RENDER_ENABLED=false \ VIDEO_EDITING_LOCAL_DIRECTOR_AUTO_RENDER=false \ VIDEO_EDITING_LOCAL_DIRECTOR_REQUIRE_APPROVAL=true \ VIDEO_EDITING_HIGHLIGHT_SCHEDULER_REQUIRE_DIRECTOR_APPROVAL=true \ VIDEO_EDITING_LOCAL_CV_WORKER_AUTO_START=false \ VIDEO_EDITING_LOCAL_ASSET_WORKER_AUTO_START=false \ VIDEO_EDITING_VISUAL_ANALYSIS_FALLBACK_TO_HEURISTIC=false \ VIDEO_CLIPPING_CLEANUP_ENABLED=false \ mvn -o spring-boot:run ``` For a prebuilt artifact, replace the last line with: ```bash java -jar target/video-editing-1.0-SNAPSHOT.jar ``` Environment variables precede the command and override packaged values. Do not add `cinematic-editing-local` or `folder-scheduler-local`; those profiles enable work. Startup success only proves Spring context creation, not dependency connectivity: the repository, queue, and object-storage health indicators always report `UP` with adapter names and do not perform a real probe. ## Workflow 1: REST clipping API ### Current behavior The API implements multipart-session metadata, clip jobs, cancellation, events, and signed URL responses. It is not a production upload service with default adapters: memory storage returns `storage.example` URLs, materializes stub content, and memory/stub state disappears on restart. | Object | States | |---|---| | Asset | `PENDING_UPLOAD`, `UPLOADED`, `PROCESSING`, `READY`, `DELETED` | | Upload | `OPEN`, `COMPLETED`, `ABORTED`, `EXPIRED` | | Clip job | `QUEUED`, `RUNNING`, `SUCCEEDED`, `FAILED`, `CANCEL_REQUESTED`, `CANCELLED` | | DB queue message | `PENDING`, `PROCESSING`, `COMPLETED`, `DLQ` | ### Start and exercise safely Use the disabled-first baseline. It leaves API defaults at memory repository, memory storage, and stub processing. These are contract-demonstration adapters only; label all results non-production. Send `X-Tenant-Id` and stable `Idempotency-Key` values on create calls. Relevant routes are: ```text POST /v1/video-assets POST /v1/video-assets/{assetId}/uploads:complete GET /v1/video-assets/{assetId} GET /v1/video-assets/{assetId}/upload-session POST /v1/video-assets/{assetId}/clip-jobs GET /v1/video-assets/{assetId}/clip-jobs GET /v1/video-assets/{assetId}/events DELETE /v1/video-assets/{assetId} GET /v1/clip-jobs/{jobId} GET /v1/clip-jobs/{jobId}/clips GET /v1/clip-jobs/{jobId}/events POST /v1/clip-jobs/{jobId}:cancel POST /v1/clips/{clipId}/download-url ``` A job publish on the memory queue invokes processing asynchronously in the same JVM. The database queue polls, claims with a visibility timeout, retries, and moves exhausted messages to `DLQ`. Cancellation is cooperative only before clip generation; do not claim that it interrupts FFmpeg. ### PostgreSQL and S3 gate `application-jpa.properties` selects JPA plus the DB queue but configures H2, not PostgreSQL. PostgreSQL migrations `V1` through `V6` exist, but there is no production datasource profile or Testcontainer certification. The S3 adapter is present, but no approved environment, credentials contract, or end-to-end multipart validation is checked in. Treat both as candidates. Do not set `video-clipping.storage=s3`, `video-clipping.repository=jpa`, or `video-clipping.queue=db` in production until change control approves integration, recovery, security, and fault-injection evidence. Scratch files appear under `tmp/ffmpeg-input`, `tmp/ffmpeg-output`, `tmp/in-memory-storage`, and `tmp/stub-output`. Successful processing deletes staged/generated worker files when `cleanup-local-files=true`; the scheduled cleanup also removes aged files when global cleanup is enabled. ## Workflow 2: folder segmentation This scheduler turns one source video into numbered fixed-duration clips. It is independent of the REST API and edit project stores. ### Approved start Obtain explicit approval for the exact source and output directories. Start only with all editing lanes off: ```bash env \ SERVER_ADDRESS=127.0.0.1 \ FOLDER_SCHEDULER_ENABLED=true \ VIDEO_EDITING_ENABLED=false \ VIDEO_EDITING_LOCAL_CV_WORKER_AUTO_START=false \ VIDEO_EDITING_LOCAL_ASSET_WORKER_AUTO_START=false \ VIDEO_CLIPPING_CLEANUP_ENABLED=false \ mvn -o spring-boot:run ``` Defaults are `input/source`, `input/working`, `input/processed`, `input/rejected`, and `output/clips`, polled every five seconds with eight-second segments. Override paths through the documented `FOLDER_SCHEDULER_*` variables before approval when isolation is required. ### Ingest, claim, publish, quarantine 1. Copy a complete source as `name.mp4.part` in `input/source`. 2. Verify size and checksum outside the service. 3. Atomically rename it to a supported final extension only after approval. Accepted extensions are `mp4`, `mov`, `m4v`, `mkv`, `webm`, and `avi`; hidden files and `.tmp`, `.part`, `.download`, `.failed` are ignored. 4. Expect an atomic move to `input/working`. 5. Expect clips in `output/clips/[-N]/` and then the source in `input/processed`. The first output uses ``; if that output directory already exists, the clipper chooses `-1`, `-2`, and so on. 6. On validation/FFmpeg failure, expect the source in `input/rejected`. If quarantine movement fails, expect a `.failed` name in working. The scheduler handles one naturally sorted candidate per poll. Output-directory collisions cause suffixing as described above. Source lifecycle collisions are different: moving a source to `working`, `processed`, or `rejected` refuses to overwrite an existing same-name file and fails/quarantines the attempt. `preserve-input-quality=true` uses stream copy where possible; false transcodes with the configured preset. Neither mode alone proves cinematic or delivery quality. Restart resumes only files still visible as new candidates. A file stranded in `working` is not automatically reclaimed. Diagnose it, preserve evidence, and move it back to source only after proving that no process is active and that output collision handling is understood. ## Workflow 3: multi-clip cinematic edit This lane accepts a folder of source clips, analyzes them, creates a filesystem project, imports a director plan, and can render `final.mp4`. ### Approved analysis start Keep automatic rendering and asset/CV bootstrap disabled: ```bash env \ SERVER_ADDRESS=127.0.0.1 \ FOLDER_SCHEDULER_ENABLED=false \ VIDEO_EDITING_ENABLED=true \ VIDEO_EDITING_LOCAL_DIRECTOR_ENABLED=true \ VIDEO_EDITING_HIGHLIGHT_SCHEDULER_ENABLED=false \ VIDEO_EDITING_LOCAL_DIRECTOR_AUTO_RENDER=false \ VIDEO_EDITING_LOCAL_DIRECTOR_REQUIRE_APPROVAL=true \ VIDEO_EDITING_LOCAL_CV_WORKER_AUTO_START=false \ VIDEO_EDITING_LOCAL_ASSET_WORKER_AUTO_START=false \ VIDEO_EDITING_VISUAL_ANALYSIS_FALLBACK_TO_HEURISTIC=false \ VIDEO_CLIPPING_CLEANUP_ENABLED=false \ mvn -o spring-boot:run ``` Stage a complete project folder as `input/editing/source/.tmp`, then atomically rename it to ``. The scanner also groups loose root clips into `source-clips`, so do not leave unrelated media there. Temporary suffixes `.tmp`, `.part`, `.download`, and `.processing` are ignored. Expected movement is `source/` to `working/` to `processed/`. Failure moves it to `rejected/` or creates a `.failed` marker/name when possible. The project tree is: ```text output/edit-projects// project.json analysis.json ai-director-prompt.md director-readme.md thumbnails/ contact-sheets/ proxies/ audio/ assets/requests/ inbox/ rendered-clips/ render-work/ edit-plan.json render-manifest.json qa-report.json final.mp4 ``` Project states are `CREATED`, `ANALYZING`, `ANALYZED`, `WAITING_FOR_DIRECTOR`, `PLANNING`, `PLANNED`, `RENDERING`, `RENDERED`, and `FAILED`. Inspect state without modifying files: ```bash curl --fail-with-body --show-error --silent --connect-timeout 2 --max-time 10 \ http://127.0.0.1:8080/v1/edit-projects/PROJECT_ID ``` Expected: HTTP 200 with the requested project. Exit 22 means an HTTP error such as unknown project; exit 7 means connection failure; exit 28 means a bound timeout. Preserve the response and branch to `video-editing-debugging-playbook`; do not retry without classifying it. Place strict JSON at `inbox/edit-plan.json`. The inbox scanner validates and archives imports; rejected plans receive a rejected name and do not authorize render. Review source bounds, timeline, transitions, asset provenance, license, voice audibility, and all generated requests. **Do not call the unauthenticated `POST /v1/edit-projects/{projectId}:render` endpoint.** It has no approval check. It remains prohibited until authenticated authorization and auditable approval bound to source, plan, configuration, model, and asset digests are implemented and tested. Automatic render is also non-production until the same binding exists; a bare `inbox/approved.flag` is insufficient. Do not render when any required asset is missing or was created by a placeholder path. A render writes segment files, `final.mp4`, `render-manifest.json`, and `qa-report.json`; the QA report is evidence to validate, not automatic acceptance. ## Workflow 4: single-source cinematic highlights This is the strategically primary lane, but it is **not production-ready**. Current analysis calls a loopback local-CV HTTP endpoint, while director-plan authorship remains manual/external. No in-service local director model exists. Strict asset readiness now fails startup when the pre-provisioned Piper, MusicGen, and AudioGen runtime is incomplete, and placeholder success paths have been removed. No complete three-model bundle is checked in, so no current start command satisfies the production requirement of fully local, runtime-resident intelligence with fail-closed cinematic assets. ### No approved operation yet Do not start this workflow as a certified or approved path. Its visual analysis requires the current loopback HTTP worker, and loopback RPC violates the no-network model/media rule. First replace that boundary with an in-process call or approved non-network IPC through `video-editing-change-control`; then validate the replacement through `video-editing-cinematic-highlights-campaign`. Use the read-only artifact inspection below for existing projects. Stage one complete file as `.part`, then atomically rename it in `input/highlights/source`. Claim and quarantine rules match folder ingestion: source to working, then processed on success or rejected on failure. The source is also copied into its project. ```text output/highlight-projects// project.json manifest.json source/ analysis/ director/director-brief.md director/director-prompt.md director/edit-plan.json director/approved.flag assets/ highlights// render-manifest.json final.mp4 ``` Analysis writes `analysis/source-analysis.json`, `ffprobe.json`, `scene-segments.json`, `audio-analysis.json`, `visual-analysis.json`, plus frames, a contact sheet, proxy, and waveform. The scheduler then calls `HighlightCandidateGenerator`, which writes `analysis/category.json` and `analysis/highlight-candidates.json` before prompt generation. Its scores are deterministic ranking hints from coarse source/shot/audio evidence, not proof of semantic importance. States are `CREATED`, `ANALYZING`, `WAITING_FOR_DIRECTOR`, `PLANNED`, `RENDERING`, `RENDERED`, and `FAILED`; a validated plan remains `PLANNED` while required local assets are pending. Do not enable rendering until a change-controlled local director implementation, immutable local model inventory, license manifest, and fail-closed asset generation are verified. If running a non-production experiment after explicit approval, require `director/approved.flag`; the scanner selects only `WAITING_FOR_DIRECTOR` or `PLANNED` projects with `director/edit-plan.json` and no project-root `final.mp4`. It writes each `highlights//final.mp4`, then concatenates/copies them to project-root `final.mp4` and writes the root manifest. Plan rejection or render failure marks the project `FAILED`, which the scanner skips; investigate and repair through an explicit recovery procedure rather than changing the status by hand. ## Health, metrics, and logs For a deliberately started inspection-only service, the following bounded API diagnostics use the service's loopback operator boundary; they do not call model workers: ```bash for path in health info metrics prometheus; do curl --fail-with-body --show-error --silent --connect-timeout 2 --max-time 10 \ "http://127.0.0.1:8080/actuator/$path" || exit $? done ``` Expected: all four requests return HTTP 200. Exit 22 means an endpoint is unavailable/denied, exit 7 means no listener, and exit 28 means a timeout. Stop and route the symptom to `video-editing-debugging-playbook`; do not broaden Actuator exposure to make the probe pass. The DB queue exports `video.clipping.queue.pending`, `.processing`, `.dlq`, and `.oldest.pending.age.seconds` only when `video-clipping.queue=db`. Editing observability is primarily structured-looking `event=...` log text, not metrics or traces. Search for workflow-specific events: ```bash rg 'event=(folder_|candidate_|processing_|local_director_|edit_|highlight_|local_asset_|local_cv_)' SERVICE_LOG ``` Do not expose Actuator beyond loopback in the current service. Health `UP` is not proof that storage, repository, queue, models, or FFmpeg work. ## Stop, restart, resume, and cleanup 1. Stop ingestion first by terminating the single application process; flags are not dynamically reloadable. 2. Allow active FFmpeg work to finish when possible. The application has no verified drain/readiness protocol. 3. Record process logs, `project.json`, plans, manifests, QA reports, and working/rejected listings before changing files. 4. Classify every `working` item as active, safely resumable, or quarantined. The file schedulers do not generally reclaim working input after restart. 5. For REST memory adapters, expect all metadata/queue state to disappear. For DB queue, expired `PROCESSING` claims become claimable after the visibility timeout. 6. Never delete outputs, caches, or failed inputs during incident analysis. Shared edit caches are `input/highlights/assets/{music,sfx,fonts,luts}` and `output/highlight-projects/_voiceover-cache`. Treat them as controlled artifact repositories: verify hash, provenance, license, model/version, and owner before use. The scheduled cleanup does not clean these project trees or shared caches. Global cleanup can delete REST source/clip records and scratch files; keep it disabled until retention and recovery are approved. Use a new project ID or source filename for a clean retry. Reusing names can collide with processed, rejected, project, or output paths. Never resolve a collision by deleting evidence or enabling overwrite without change control. ## Production promotion checklist - [ ] One workflow is selected; every other scheduler and renderer is explicitly disabled. - [ ] Artifact was built offline/reproducibly and traced to a reviewed commit. - [ ] All local models and dependencies are immutable, pre-provisioned, hashed, licensed, and network-independent. - [ ] Missing/unhealthy models fail startup or the use case; no heuristic, silence, or tone fallback can publish. - [ ] Director plan and render approval are authenticated, authorized, auditable, and tested. - [ ] PostgreSQL/S3 or replacement adapters pass real integration, retry, concurrency, backup, restore, and retention tests. - [ ] Filesystem state is durable and single-writer/shared-storage semantics are explicit. - [ ] Health probes test real dependencies; logs, metrics, traces, SLOs, dashboards, and alerts have runbooks. - [ ] Graceful shutdown, restart, duplicate claim, stuck working item, and DLQ recovery are exercised. - [ ] Security, vulnerability, secret, image, and license gates pass with no unresolved critical/high findings. - [ ] `video-editing-validation-and-qa` accepts objective media and human-review evidence. - [ ] `video-editing-change-control` approves promotion. No checklist item may be waived silently. ## Provenance and maintenance Ground truth: `application.yml`, application profiles, `VideoClippingProperties`, controllers, schedulers, project stores, queue/storage adapters, cleanup jobs, local worker scripts, renderers, health indicators, and Maven configuration, inspected 2026-07-21. Re-verify drift with one-line commands: ```bash rg -n 'enabled:|auto-start:|auto-render|require-.*approval|fallback-to-heuristic|directory:' src/main/resources/application*.yml rg -n '@(Get|Post|Put|Delete|Patch)Mapping|@RequestMapping' src/main/java/org/example/videoclips/api rg -n 'ConditionalOn(Property|Expression)|@Scheduled' src/main/java/org/example/videoclips rg -n 'Files\.(move|copy)|StandardCopyOption|\.failed|rejected|processed|working' src/main/java/org/example/videoclips/{folder,editing} rg -n 'pip install|download|from_pretrained|YOLO|silence|fallbackTone|write_fallback_tone' tools src/main/java/org/example/videoclips/editing rg -n 'video\.clipping\.queue|Health\.up|management\.endpoints' src/main src/main/resources rg -n '|spring-boot-starter-parent||' pom.xml ```