feat(demo): lay the generated music bed under the demo video - #60
Merged
Conversation
added 2 commits
August 3, 2026 23:14
The demo video has no music because an unlicensed track is a problem we will not hand a judge. Generating it removes the licensing question entirely: the bed is as clearly ours as the footage. minimax-music-2.5 is reachable through the same Genblaze/GMI Cloud path every other asset uses. It answers the SDK's empty-payload liveness probe with 400 'lyrics (Required parameter is missing)' where a made-up slug answers 404 'does not exist'. The SDK's own gmi-audio-music surface does not allow 'lyrics', which the model requires, so the slug gets an explicit ModelSpec through the documented per-instance registry override - the same shape the seedance FLF2V bridge already uses. Direction comes from the occasion the reel in the video actually uses (anniversary: warm romantic strings, 96 bpm), which is what Occasion.music_style has always documented itself as being for.
The film had no music because an unlicensed track is a copyright problem we will not hand a judge. Generating it removes the question instead of dodging it: the bed is as clearly ours as the footage. Two things had to be solved. minimax-music-2.5 gives no duration control, so the bed came back 90.26s against a 169.74s film; mix-music.py loops it by crossfading it into a second copy of itself with a constant-power (qsin) seam, which on a sustained strings pad is not something you can point at. And the narration stays dominant: both tracks are measured with EBU R128 and the bed is attenuated to sit exactly 20.1 LU under the voice, with amix normalize=0 so the mixer cannot quietly undo the measurement. Integrated loudness is -25.9 LUFS before and after, so the voice is not one decibel quieter than the approved cut. The picture is stream copied, never re-encoded, so every footage beat, caption window and cut survives byte for byte. check_video.py gains a music section. The mix is one AAC track, so "exactly one audio stream" still guards a stray stream but can no longer tell narration-only from narration-plus-music. Two new two-sided bounds do: a floor (narration-only leaves 44 windows of true dead air between padded lines, the mix leaves 1, so a rebuild that skips the music step fails) and a ceiling (the mixed film must measure within 1.0 LU of the narration it was built from, so a bed mixed near the voice fails). The bed is pinned by content hash and recorded in the beat script with its provider, model and prompt like every other generated asset.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
The demo film had no music because an unlicensed track is a copyright problem we will not hand a judge. Generating it removes the question instead of dodging it: the bed is as clearly ours as the footage.
minimax-music-2.5through the same Genblaze path every other asset uses, prompted from the occasion the reel in the video actually picks (anniversary: warm romantic strings, 96 bpm), which is exactly whatOccasion.music_stylehas always documented itself as being for.Two problems worth naming
No duration control. The bed came back 90.26s against a 169.74s film.
demo/mix-music.pyloops it by crossfading it into a second copy of itself with a constant-power (qsin) seam, then trims to the film and eases in and out. On a sustained strings pad the seam is not something you can point at.Narration stays dominant. Both tracks are measured with EBU R128 integrated loudness and the bed is attenuated to sit exactly 20.1 LU under the voice, with
amix normalize=0so the mixer cannot quietly halve both inputs and undo the measurement. The script fails hard if the measured separation drifts more than 0.5 LU.Integrated loudness is -25.9 LUFS before and after, so the voice is not one decibel quieter than the cut that was already approved.
The picture is untouched
The video stream is copied, not re-encoded, so every footage beat, caption window and cut survives byte for byte. 169.74s, under the 180s cap, ten beats and ten cues.
The gate
The mix is one AAC track, so
exactly one audio streamstill guards against a stray stream but can no longer tell narration-only from narration-plus-music.check_musicadds two bounds, two-sided on purpose (a one-sided "not silent" check would pass a mix that drowns the voice):The bed is pinned by content hash and recorded in
demo/cinemory-demo.beats.jsonwith its provider, model and prompt like every other generated artifact.Docs
The "no music, deliberately" claims in
demo/SUBMISSION.mdanddemo/video-script.mdbecome false on merge and are updated.demo/STATE.mdgets a new top entry rather than a rewrite, per its own append-log contract.README.mdhad no false claim; one clause was added to the demo-video bullet. Badge row, YouTube URL and test-count floors untouched.Owner action after merge: re-upload
demo/cinemory-demo.mp4to YouTube and repoint the Devpost video link.