Loading...
Loading...
Landing page hero demo video composition. Use when editing scenes, regenerating voiceover, updating captions, or adjusting timing for the hero demo at telecine/services/web/app/components/landing-v5/HeroDemo.tsx.
npx skill4agent add editframe/skills hero-demosequence| File | Purpose |
|---|---|
| Composition: DUR constants, CAPTIONS array, 8 scene functions, HeroDemoContent layout |
| All |
| TTS generation + whisper splitting script |
| Generated WAV/MP3 files, timing.json |
FitScale
Timegroup mode="contain" (960x540, relative)
Audio src={VOICEOVER_SRC} ← single continuous track
Timegroup mode="sequence" overlapMs=495
SceneTitle (3333ms)
SceneAuthor (6333ms)
SceneLayers (7067ms)
SceneTimeline (9767ms)
SceneEditor (8200ms)
SceneTemplate (5500ms)
SceneStream (5700ms)
SceneRender (8833ms)
SceneCaptions groups={CAPTIONS} ← absolute overlay, global timestampsanimationDelay| # | Scene | Text |
|---|---|---|
| 1 | title | Video is a web page that moves. |
| 2 | author | It starts with HTML and CSS. When you need more, it's just React. |
| 3 | layers | Stack layers the way you stack divs. Video, text, shapes, 3D, mix everything. |
| 4 | timeline | Need an editor? Snap together GUI primitives. Timeline, waveforms, captions, into any editing experience you want. |
| 5 | editor | A full NLE. A simple trim tool in a form. It's your UI. These are just the building blocks. |
| 6 | template | Feed in data, and one template becomes ten thousand unique videos. |
| 7 | stream | Preview is instant. Change the code, see the frame. |
| 8 | render | When it's ready, render to the cloud, the browser, or the command line. Same composition, every target. |
SEGMENTStelecine/services/web/scripts/generate-hero-voiceover-local.pykey01-titletextlast_worddiscard"discard": True"Here is the introduction."" ... "cd telecine/services/web
python scripts/generate-hero-voiceover-local.pyqwen_ttsQwen/Qwen3-TTS-12Hz-1.7B-VoiceDesignwhispersoundfilenumpytorchgenerate_custom_voicegenerate_voice_designlanguage="English"telecine/services/web/public/audio/hero/voiceover.wav.mp301-title.wav08-render.wav.mp3timing.jsonffmpeg -y -i public/audio/hero/voiceover.wav -ss <PREAMBLE_END_SEC> public/audio/hero/voiceover-trimmed.wav
ffmpeg -y -i public/audio/hero/voiceover-trimmed.wav -codec:a libmp3lame -b:a 128k public/audio/hero/voiceover-trimmed.mp3import whisper, json
model = whisper.load_model("small")
result = model.transcribe("public/audio/hero/voiceover-trimmed.wav", language="en", word_timestamps=True)
words = []
for seg in result["segments"]:
for w in seg.get("words", []):
words.append({"word": w["word"].strip(), "start": round(w["start"] * 1000), "end": round(w["end"] * 1000)})
with open("/tmp/hero-whisper/global.json", "w") as f:
json.dump(words, f, indent=2)gs://editframe-assets-7ac794b/hero/editframe-assetshttps://assets.editframe.com/hero/HASH=$(md5 -q public/audio/hero/voiceover-trimmed.mp3 | head -c 8)
gsutil -h "Content-Type:audio/mpeg" -h "Cache-Control:public, max-age=31536000" \
cp public/audio/hero/voiceover-trimmed.mp3 "gs://editframe-assets-7ac794b/hero/voiceover-${HASH}.mp3"VOICEOVER_SRCCAPTIONSshowMshideMswords{ w, s, e }DURDUR.scene = voiceDurationMs + buffertiming.jsonSceneTitleSceneAuthorTimegroup mode="fixed"duration={DUR.xxx}mssceneStyle(d)animationDelayCompositionCanvas<Text split="char">landing.csshero-telecine/services/web/app/content/changelogs/{version}.mdxChangelogIntroCardversioncodenametitletitletitletitle.trim()illustration<ChangelogIntroCard
version="0.47.0"
codename="Mocha Relay"
title="Short title for the card display"
durationMs={4000}
/>ReleaseVideo<Timegroup mode="contain"><Timegroup mode="sequence"><ReleaseVideo aspect="16/9">
<Timegroup mode="sequence" overlapMs={600} style={{ width: 1920, height: 1080, position: "relative" }}>
<ChangelogIntroCard ... />
<TextMoment ... />
<ChangelogOutroCard ... />
</Timegroup>
</ReleaseVideo>ChangelogOutroCardversiontaglinedurationMsTextMomentheadlinebodymotifaccentColordurationMsReleaseVideoReleaseVideoisClientTypeErrorgenerate_voice_designflushSyncuseLayoutEffectgl.render()gl.finish()