Repository navigation
Releases: abm-dungtq/opus-video
Release list
v1.1.0: tiếng khớp hình, chữ đủ lâu để đọc, sửa theo vòng
Why: three faults slipped past every existing gate. A sound effect could ring after the moment it belongs to (a click heard after the button is pressed), because many SFX files start with silence and data-start only marks where the file begins. On-screen text could leave before a viewer can read it. And each fix meant re-rendering the whole video, with no record of what had changed.
New script
scripts/sfx-sync.mjs: reads the## Sự kiệntable in PLAN.md (Thời điểm | Sự kiện | Âm thanh, seconds on the root timeline), finds each sound inindex.html(or--html), measures the file's leading silence with ffmpeg at the file's own peak − 20 dB (so a quiet file is not read as all silence) and compares the moment the sound is heard with the event. OneLEVEL SYNCline per event.--fixprints thedata-startthat would put the sound on the event and never edits the HTML;--write-qaappends toQA.md;--jsonprints an array. Measurements are cached per file sha256 inassets/sfx-onsets.json. Exit 0 no FAIL, 1 a FAIL, 2 bad usage or missing PLAN.md / HTML. Sounds inside a sub-composition are reported, not measured.
New rules in check-preflight
- Creative projects (
direction:): the plan stage requires a## Sự kiệnsection, either a table with at least one row or the linekhông có SFX gắn sự kiện(WARN only, and only when the table has no rows). An empty section, aTODOor a header-only table fails like a missing one. The final stage runssfx-sync: FAIL lines block, WARN lines warn, a missing section only warns so a delivered project can still re-render. - Readable hold, both stages, every project, WARN only: quoted on-screen text in the picture column of
## Cảnhmust stay up at leastmax(1 s, words / 2.5 + 0.5 s). A cell may state(giữ đến <t>s)or(giữ đến hết)when the text stays past its beat; the hold is then measured to that mark. REVISIONS.md, final stage, every project, WARN only: a round with more than 5 fixes, or a fix missing one ofVị trí,Lỗi thấy,Đổi,Giữ nguyên.
Thresholds and sources
- Sync windows from ITU-R BT.1359-1 (sound minus picture): PASS from −45 to +125 ms, WARN from −90 to +185 ms, FAIL beyond.
- Reading speed 2.5 words/s from viet-pro
references/publishing/video-script.md. The 0.5 s eye-landing time is an assumption, marked as such in the code. The hold rule stays a WARN until more projects are measured: on the Gemini 4 Argon project the closing title and tagline (9 new words) stay about 2.2–2.8 s against a 4.1 s threshold, and read fine in the frames. - Calibration on a copy of that project: all five SFX PASS when the event times are their
data-start;keys.mp3measured 30 ms of leading silence, the quietsend.mp3(peak −32 dB) 0 ms.
Docs
references/revisions.md: the revision-round template (four fields, at most five fixes per round, check each fix withhyperframes snapshot --at, one animatic per round; HyperFrames 0.8.144 has no--range).references/plan-demo.md(event table, hold marks, measured vs proposed marks),references/edit-method.md(times are on the root timeline),references/pattern-library.md(card 10, Launch Clip),references/audio-pipeline.md,references/qa-checklist.md, SKILL.md steps 6 and 6b, README and chapter 13 ofdocs/huong-dan-chuyen-sau.md.- README test command is now the quoted glob
node --test "…/scripts/tests/*.test.mjs"; the directory form exits 1 on Node 24 even when no test fails.
Compatibility
- Legacy projects (no
direction:and nobrief_version: 2) are not blocked by anything new:sfx-syncturns every FAIL into a WARN for them andcheck-preflightdoes not run it.bds-ban-do-pip-9x16andabm-introgive the same output and exit code before and after this change.
v1.0.0: chọn hình trước, brand kit, dữ liệu thật
Why: a one-line brief ("15s, công nghệ cao cấp") produced four title cards sliding up and fading. Causes found: step 1 told the agent to fill the style itself; the script was written before any visual idea (one sentence = one card); the general-video path built without HyperFrames recipes; the demo gate showed stills, which cannot reveal a slide swap; no gate looked at motion. Property and news videos also needed real numbers (nearby amenities, source text) instead of typed-in ones.
Workflow
- New SKILL.md step 1b: the user picks one of three styleframes built from their own topic, before the script. The chosen styleframe becomes the opening scene. Step 1 asks only for the minimal brief; step 2 writes the script after the direction (picture leads, words follow) within
word_budget; steps 4b, 6, 6b, 8 and the reference table follow the new gates. SKILL.md suggests writing the three styleframes with parallel agents when the runtime allows (about 15 minutes when written one after another). - Step 6 builds from
build/RECIPES.md; step 6b approves a motion draft (animatic) instead of stills. data/directions.json: 8 creative directions (A1 to A8: one-shape morph, prompt to live artifact, kinetic type with beat invert, continuous camera with cursor, 3D flythrough, live data, editorial marker, map/PiP), two knobs (energy, palette) and 5 swappable keyword groups (style, visual, effect, transition, sfx) with Vietnamese labels. Every token is a real HyperFrames blueprint, rule, preset, visual style or seam.references/creative-directions.mdis generated from it.references/styleframe-examples/holds one finished styleframe per direction (A2, A3, A4) from a real pitch;STYLEFRAME.mdpoints to the example of its direction when one exists.references/pattern-library.md: vertical news and niche explainer cards (9:16), with every on-screen number traced toSOURCES.md.references/brand.example.json: template for a shared brand kit (shared-assets/brand.json).- Docs:
brief-template.md,plan-demo.md(7-column scene table),edit-method.md(all 22 blueprints, anti-slideshow rules, the 4 cut-catalog seams), README, chapter 12 ofdocs/huong-dan-chuyen-sau.mdand the prompt library pagedocs/thu-vien-prompt/07-chon-huong-sang-tao.md.
New scripts
scripts/directions.mjs:check(token existence against the installed HyperFrames),pick(deterministic, one direction per tier: fit / continuous / bold; topic keywords match whole words),show,compat(clash warnings, exit 3),doc --write.scripts/make-pitch.mjs:initscaffolds 3 HyperFrames styleframe projects withSTYLEFRAME.mdandRECIPES.md;rendermakes 3 draft clips,sheet.jpgandPITCH.md(numbered menu, works on every agent) and measures their motion;choosewritesdirection,direction_swaps,energy,palette,word_budget,music_only_s,creative_selection,styleframeand## creative_directionintoBRIEF.md.renderrefuses an unwritten scaffold, checks ffmpeg and ffprobe first (exit 1), never reuses a stale poster, and exits 4 when a styleframe fails MOTION. Smoke run: 3 × 3 s styleframes rendered in 26 s.scripts/recipe-pack.mjs: inlines the blueprint/rule/seam recipes named in PLAN.md (or a direction) intobuild/RECIPES.md, build rules first.scripts/brand.mjs check: validates the brand kit (#rrggbbcolours, banned directions that exist; missing logo or font files are WARN).make-pitchreads it: banned directions leave the pick,STYLEFRAME.mdgets the colours, logo and fonts,choosedefaults to palettethuong-hieuand fillsvoice_id/tts_modelwhen BRIEF has none or only the template default. An explicit brand path that does not exist fails; a brand file inPICK.jsonthat is gone is a WARN.scripts/poi-fetch.mjs: real nearby amenities (school, market, supermarket, transit, hospital, park, mall) around an address or a point, from OpenStreetMap (Nominatim, Overpass), with straight-line distance and walking time (estimate, or the FOSSGIS OSRM foot router with--route). Writessources/poi.json(cache keyed by centre, radius, kinds and--route), the POI section ofSOURCES.mdand the ODbL credit inassets/CREDITS.md, and prints the geocoded place so a wrong match is caught.scripts/source-ingest.mjs: fetches article URLs, PDFs and arXiv abstract pages (passhttps://arxiv.org/pdf/<id>for the full text) intosources/<slug>.txtand indexes each inSOURCES.mdwith candidate sentences holding numbers or quotes. No AI summary. A missingpdftotextexits 2 after indexing the sources already fetched.make-demo.mjs --animatic: full draft render scaled to 540 px on the short side, kept asdemo/animatic.mp4, frames cut from it,contact-sheet.jpg,animatic:in DEMO.md.
New gates
check-preflight.mjscreative gate when BRIEF hasdirection:orbrief_version: 2:## Ý đồ sáng tạo, a Blueprint/Rule column with real tokens (at least 2 distinct), a seam into every next beat (fade/crossfade/cut banned, soft seams only forallow_softdirections), music-only beats of at leastmusic_only_s.brief_version: 2withoutdirection:fails. The final stage adds an animatic newer than PLAN.md,index.htmlandcompositions/*.html(a build edited after the approved animatic blocks), whose motion passes MOTION, andbuild/RECIPES.mdnewer than PLAN.md.check-viet-pro.mjs: voice words above BRIEFword_budgetfail the gate (VOICE_OVER_BUDGET). When the field is missing butdirection:is set, the budget comes from the direction's energy and the BRIEF duration.qc-mp4.mjsMOTION: share of near-still frames (YDIF < 0.5 at 360 px, 30 fps) and 90th-percentile YDIF. Creative projects FAIL at 60 % still or more with a peak under 1.5, with separate thresholds for energyem. Calibration: the real slideshow render 70 % / 1.12 (FAIL), the creative 10 s reference 25 % / 7.0 (PASS).video-lint.mjs:SLIDESHOW_MOTIONearly WARN. It stays a WARN on purpose: the real slideshow fixture usesscale(),rotate()and a background canvas, so static code analysis cannot tell it apart; the blocking check is MOTION on the render.setup-check.mjsrunsdirections.mjs checkwhenhyperframes-animationis installed.find-cases.mjsexits 2 on a bare word; search with--keyword,--categoryor--tag.- Tests:
creative.test.mjswith fixturesslideshow/(the real Gemini 4 Argon TikTok project, must be blocked) andcreative-good/(must pass);brand.test.mjs,poi-fetch.test.mjsandsource-ingest.test.mjsrun offline on fixtures.
Compatibility
-
Legacy projects (no
direction:and nobrief_version: 2) get one WARN,creative gate skipped, and keep the old gates. For them MOTION is a WARN, and a composition edited after the demo stays a WARN. -
creative_override: <reason ≥10 chars>in BRIEF skips the creative gate for footage-only projects and is printed as a WARN.make-pitch chooseclears it. Existing test fixtures set it, since they predate the creative gate. -
The seam check no longer flags ordinary prose that contains "hiện".
-
On Windows,
make-pitchandrender-finalquote thenpxarguments. -
eleven.mjstts/audio-metanow take the voice and TTS model fromBRIEF.md(voice_id,tts_model) beforeOPUS_VIDEO_VOICE_ID/OPUS_VIDEO_TTS_MODEL;--voice/--modelstill win. A BRIEF value equal to the default is the template's and does not hide the env. The chosen source is printed.
Video demo
Video demo do opus-video dựng, dùng cho phần Video demo trong README. Không phải bản phát hành mã nguồn.