- Python 83.3%
- JavaScript 10.2%
- HTML 5.2%
- CSS 0.9%
- Dockerfile 0.4%
| Filename | Latest commit message | Latest commit date |
|---|---|---|
| .forgejo/workflows | ||
| docs | ||
| examples/prehistoric-jungle | ||
| scripts | ||
| src/interstitial_director | ||
| tests | ||
| .dockerignore | ||
| .gitignore | ||
| Dockerfile | ||
| pyproject.toml | ||
| README.md | ||
Interstitial Director
Interstitial Director builds and reuses channel-branded scene packs for schedule-aware interstitials. It sits between Tunarr schedule context, curated assets, local vision and generation services, and deterministic final rendering.
The project is intentionally separate from Comfy Gallery and homelab:
- Interstitial Director owns scene packs, creative plans, matching, renders, review state, and publication workflows.
- Comfy Gallery curates source media and hands selected assets to Director.
- Homelab owns deployment, secrets, storage mounts, and service configuration.
- ComfyUI and Ollama remain generation and analysis backends.
The first milestone establishes the versioned scene-pack contract, deterministic renderer, and an operator console. See the architecture and Phase 0 scope.
Operator console
Open the service root to run the end-to-end manual workflow:
- Upload a still, animated image, or source video into the Director Inbox.
- Optionally animate a still with a composition-aware ComfyUI Gallery preset. The still is preserved and the finished motion clip becomes a separate source.
- Enter the on-screen message and choose its safe-area position.
- Select one or many target durations and queue the render batch.
- Preview each verified MP4, approve it, and publish it to a channel folder.
Source assets are stored below INTERSTITIAL_DATA_ROOT (default /data), job
records and review state below INTERSTITIAL_STATE_ROOT (default /state), and
approved Tunarr media below INTERSTITIAL_PUBLISHED_ROOT (default /published).
Publication is deliberately gated on approval.
Gallery motion generation is enabled when INTERSTITIAL_GALLERY_URL points to
the writable Gallery curator API and INTERSTITIAL_GALLERY_INBOX_ROOT points to
the same Inbox mounted by Gallery. Director copies a working image into that
shared Inbox, tracks the video-i2v run, and copies its result into the Director
Inbox. It never overwrites or changes the original asset.
Development
Requires Python 3.11 or newer.
python -m venv .venv
. .venv/bin/activate
pip install -e '.[dev]'
pytest
interstitial-director serve --reload
Validate a scene pack:
interstitial-director validate examples/prehistoric-jungle/scene-pack.yml
Render a broadcast-safe review asset using the compatibility CLI:
build-tunarr-interstitial \
--source source.mp4 \
--title "UP NEXT" \
--subtitle "SCI-FI WORLD" \
--pack sci-fi-world \
--duration 15 \
--output review/up-next-15s.mp4
The renderer writes atomically, probes the temporary output before publication, and rejects files that miss the requested duration, H.264/yuv420p video, AAC stereo audio, 48 kHz sample rate, resolution, or frame-rate contract. A JSON provenance sidecar includes the measured verification result.
Application-managed renders are stored as one-shot jobs. Each job receives its
own directory containing request.json, render.mp4, render.json, and
result.json. Requests and results are created exclusively, and SHA-256 hashes
tie the source inputs to the verified output without allowing a job ID to be
reused. Failed jobs retain request.json and an immutable failure.json for
diagnosis.
CI also runs the real FFmpeg renderer against a deterministic fixture and
uploads the complete verified job as the interstitial-director-fixture
workflow artifact. This proves the MP4 and its requested duration rather than
only testing command construction.
The HTTP service exposes:
GET /(operator console)GET /healthzGET /api/v1/schema/scene-packGET /api/v1/schemaGET /api/v1/schema/{contract}POST /api/v1/scene-packs/validateGET|POST /api/v1/operator/assetsGET /api/v1/operator/motion/presetsPOST /api/v1/operator/motion/runsGET /api/v1/operator/motion/runs/{run_id}GET /api/v1/operator/jobsPOST /api/v1/operator/rendersPOST /api/v1/operator/jobs/{job_id}/approvePOST /api/v1/operator/jobs/{job_id}/publish
Print any domain contract locally with interstitial-director schema creative-plan (or channel-profile, program-context, gap-request,
render-spec, render-record, and publication-record).
Initialize a persistent catalog and store a validated contract:
interstitial-director catalog-init /data/catalog.sqlite3
interstitial-director catalog-put /data/catalog.sqlite3 channel-profile channel.json \
--expected-revision 0
interstitial-director catalog-get /data/catalog.sqlite3 channel-profile sci-fi-world
The SQLite catalog runs ordered migrations automatically, keeps every document revision, and supports optimistic revision checks so concurrent work cannot silently overwrite newer decisions.
Container
docker build -t interstitial-director:dev .
docker run --rm -p 8080:8080 interstitial-director:dev
After the full test and real-render suite passes on main, Forgejo publishes:
git.scruffydude.net/scruffydude/interstitial-director:sha-<full-commit>for immutable homelab deployment pins.git.scruffydude.net/scruffydude/interstitial-director:devas the latest successful development build.
Pull-request workflows build the image but never publish it.