Commit Graph

13 Commits

Author SHA1 Message Date
Calesthio
1188e1bee9 Merge pull request #199 from An-idd/fix/video-compose-vertical-resolution
fix(video_compose): honor target resolution in FFmpeg compose (vertical/9:16)
2026-06-30 20:45:49 -07:00
Calesthio
7b8d59186d Merge pull request #223 from 0xDevNinja/feat/issue-168-music-library-preflight
feat(audio): add music_library tool so user tracks surface at preflight
2026-06-30 20:40:14 -07:00
calesthio
5e4943a41b Add expressive TTS governance 2026-06-29 12:16:07 -07:00
0xDevNinja
add955696d feat(audio): add music_library tool so user tracks surface at preflight
AGENT_GUIDE.md requires the music decision to be made at the proposal stage,
but the only check for the user's music_library/ folder lived in the
asset-director skills, which run later. A user could approve a creative
direction without ever being told a free, intentional music option was sitting
on disk (issue #168).

music_library/ was already referenced as a source_tool in asset artifacts but
had no backing tool. Add a small read-only tool that scans the library folder
(default <project root>/music_library, override via MUSIC_LIBRARY_DIR or a
library_dir input) and lists the audio tracks it finds, with best-effort
durations via ffprobe when present.

Because it inherits BaseTool, the registry auto-discovers it and it appears in
the preflight provider menu alongside music_gen and the stock music sources:
- AVAILABLE when the folder holds at least one audio track
- UNAVAILABLE otherwise, with install_instructions telling the user how to add
  tracks

So the user sees their music options before approving creative direction, with
no orchestration code changes. Read-only: no side effects, no cost.

Closes #168
2026-06-29 13:24:48 +05:30
An-idd
035df52b26 fix(video_compose): honor target resolution in FFmpeg compose (vertical/9:16)
The compose target resolution was resolved from `profile` (and documented as
overridable via edit_decisions.metadata.compose_target) but the per-segment
scale/pad filter hardcoded 1920x1080. As a result, vertical profiles such as
`tiktok` / `youtube_shorts` / `instagram_reels` silently produced landscape
1920x1080 output instead of 1080x1920 — a silent dimension bug, no error raised.

- Use the resolved target width/height in the per-segment scale/pad filter.
- Implement the previously-stubbed `metadata.compose_target` extension point:
  {"width", "height", "fit"} where fit="pad" (letterbox, default, unchanged
  behavior) or fit="cover" (scale-to-fill + centre-crop, ideal for vertical).
- Default with no profile/target stays 1920x1080 (backward compatible).

Adds tests/tools/test_video_compose_vertical.py covering default landscape,
profile=tiktok vertical, and compose_target cover override.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-27 11:56:49 +08:00
Calesthio
49a1e56825 Merge pull request #136 from vizionik25/feat/apple-silicon-mps-support
feat(gpu): Apple Silicon MPS (Metal) GPU Support
2026-06-26 14:29:55 -07:00
An-idd
93d96de8f1 fix(video): runway/higgsfield model defaults diverge from schema
runway (estimate_cost/estimate_runtime/execute) defaulted to gen4_turbo and
higgsfield (execute) defaulted to kling_3.0, while both schemas advertise
seedance_2.0 as model.default. Omitting model under-quoted cost (runway 6x:
$0.25 vs $1.50) and silently generated a different model than advertised,
violating the Decision-Communication / cost-accuracy contract.

Root cause was a default duplicated across schema + 3 methods that drifted.
Collapse it to a single _DEFAULT_MODEL constant referenced everywhere.

Add tests/tools/test_provider_model_defaults.py to lock each tool's
estimate default to its schema default and guard the execute path.
2026-06-26 15:30:22 +08:00
Nik Nichols
576bb2f6f2 test(gpu): add tests for Apple Silicon MPS device resolution and fallback 2026-06-24 16:30:29 -05:00
calesthio
0efed7427c video-compose: catch TTS punctuation leaks in final review
Adds a transcript_comparison check to VideoCompose._run_final_review
that word-diffs the whisper/whisperx transcript against script.txt and
fails loudly when the TTS engine literally voiced punctuation tokens
(dot, dots, ellipsis, comma, dash, hyphen, period). Chirp3-HD did this
to ellipses in a production run and it slipped past review; now it
cannot.

Also corrects the "tiny background video" gotcha in
skills/core/hyperframes.md. After six renders of blaming HyperFrames
CSS, the real root cause was 640x360 Pexels sources combined with a
fit-and-pad pre-transform — HyperFrames was rendering the letterboxed
input faithfully. Gotcha now walks through the ffprobe diagnostic and
the scale-to-cover fix, and keeps the wrapper-div pattern for the
right reasons (aspect mismatch handling, not framework bug workaround).

Four regression tests cover the new check: punctuation-leak detection,
clean-audio false-positive guard, graceful skip when inputs missing,
and always-present transcript_comparison section.
2026-04-18 22:16:27 -07:00
calesthio
b4f7ec4eee hyperframes: add HTML/CSS/GSAP as a parallel composition runtime
Separates creative grammar (renderer_family) from technical engine
(render_runtime) so HyperFrames can stand alongside Remotion as a
first-class runtime instead of masquerading as a Remotion sub-case.
Locks runtime choice at proposal stage and enforces it end-to-end: the
schemas require it, video_compose routes by it, the reviewer fails
closed on silent swaps, and a parametrized contract test walks every
pipeline manifest to ensure each planning-stage skill explains the
conversation to the user. Adds hyperframes_compose (scaffold/lint/
validate/render/doctor/add_block), a playbook -> CSS style bridge, and
vendored HyperFrames Layer 3 skills from commit d291358, pinned via
PROVENANCE.md for future re-sync. Final_review now records
render_runtime_used and runtime_swap_detected so compose lies are
catchable after the fact.
2026-04-18 18:37:00 -07:00
calesthio
a8d1ebdf6f docmontage: corpus builder hardening from P1 + P2 audit observations
All of these changes came out of running the P1 and P2 documentary-montage
audits end-to-end and watching specific things break. Grouping them into
one commit because they share a theme: making the corpus builder and its
stock source adapters robust enough that a real brief can produce a
real corpus without special-casing.

corpus_builder.py + new clip_cache.py + test_clip_cache.py
  Phase 1 of the shared-corpus architecture. Adds
  ~/.openmontage/clips_cache/ — a process-safe, LRU-evicted cache of
  downloaded clip files keyed by clip_id. Before each candidate download,
  corpus_builder asks the cache whether the bytes already exist on disk
  from a previous run; on a hit it hard-links (or copies on cross-drive)
  the blob into the caller's corpus dir and skips the network fetch. On
  a miss it downloads as usual and ingests the fresh file. Motivation:
  re-running the P1 audit after every tool fix was re-downloading gigs
  of archive.org footage that had already been fetched in the prior run.
  Cache faults never block the pipeline — they degrade gracefully to
  normal downloads. The cache bubbles counters into the corpus_builder
  return payload so the production report can show hit/miss/bytes-saved.
  Default 20 GB cap, overridable via OPENMONTAGE_CACHE_MAX_GB.
  Full test coverage: try_link, ingest, stats, LRU eviction, manifest
  persistence, lock behavior. 23 tests, tmp_path-scoped.

stock_sources/archive_org.py
  1. Three-strategy query cascade (phrase_prox_10 → distinctive_and →
     distinctive_or). Motivation: natural-language documentary queries
     against archive.org Solr were zeroing out — "1950s family watching
     television" returned 0 hits because Solr's default multi-term AND
     over-intersects. Walks strict to loose and returns the first
     non-empty strategy. Stop words, source hints ("prelinger",
     "archive", "footage"), and year tokens ("1950s") are excluded from
     the distinctive-token picks since they don't correlate with
     Prelinger title tokens.
  2. 150 MB per-rendition size cap. archive.org routinely hosts
     multi-hundred-megabyte h.264 masters and one 2 GB Prelinger item
     poisons corpus build wall-time and disk. Within a format bucket
     we now pick the largest rendition under the cap; if nothing fits
     we fall through to the next format rather than dropping the item.
  3. 180 s default max-duration ceiling when the caller hasn't set one
     — archive.org is the only source that routinely hosts feature-
     length material and a naive fan-out pulls them into corpora that
     only ever want a few seconds per clip.

stock_sources/wikimedia.py
  Parallel 3-strategy cascade (full → top2_or → single_best). Motivation:
  Commons CirrusSearch also defaults to AND across multi-word queries;
  our first P2 diagnostic pass returned 0 video results for 10/10
  queries. Same stop-word / source-hint / year-token stripping as
  archive_org so the two adapters stay symmetric.

test_stock_source_adapters.py
  Rewrote the wikimedia query-builder tests against the new cascade
  API. Added coverage for multi-word fallback + source-hint/year
  stripping.

video_compose.py
  Two small fixes for the Remotion renderer on Windows:
  1. Resolve output_path to absolute before invoking the CLI so the
     binary can write wherever the caller asked regardless of cwd.
  2. Pass cwd=composer_dir to run_command so npx can find the local
     Remotion binary under node_modules/.bin. Without this, Windows
     npx returns "could not determine executable to run" because it
     resolves .bin relative to the process cwd rather than the
     script's parent.
2026-04-11 00:46:06 -07:00
calesthio
de94d4dba3 Documentary Montage hardening plus governance fixes 2026-04-10 16:42:39 -07:00
calesthio
a3e735cc7a Initial release — OpenMontage: the first open-source agentic video production system
11 production pipelines, 47 tools, 124 agent skills.
Supports cloud APIs (fal.ai, OpenAI, ElevenLabs, Suno, HeyGen, Runway) and
free local providers (diffusers, Piper TTS, WAN 2.1, Hunyuan, CogVideo).

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-29 08:25:17 -07:00