Turn an SRT subtitle file into a HyperFrames + GSAP Editorial-style video. Only SRT input is supported.
When invoking this skill, the user must provide the SRT subtitle file path. Without srtPath , the main Agent must first pause and
ask the user to provide the .srt file path.
Before production, a theme must first be selected:
- Dark style (
dark-editorial) - Kraft paper style (
kraft-editorial) - Klein blue style (
klein-blue) - Sage green style (
sage-green)
SubAgent usage authorization and hard requirements
When the user requests "use HyperFrames to generate a video based on SRT subtitles" or otherwise triggers this skill, the user is deemed to have explicitly requested using SubAgents according to this skill's workflow. The main Agent must not skip the SubAgent stages specified by this skill because of the general tool instructions' restriction that "sub-agents should only be used when the user explicitly requests them".
Steps 3 and 4 are mandatory SubAgent stages. If the current runtime environment has no available SubAgent tool, the main Agent must immediately pause and explain the blocking reason to the user, and must not downgrade to completing these stages by itself as the main Agent.
Core principles
- SRT time is the sole source of time truth.
- AI is only responsible for semantic grouping, visual translation, and local scene design.
- Scripts are responsible for SRT parsing, continuity validation, relative time calculation, creator sharding, scene-plan validation, and final composition assembly.
- The creator does not directly modify the final
index.html, and only writes independent scene fragments.
Path Contract
The main Agent and all SubAgents uniformly use absolute paths:
skillRoot: the currentsrt-hyperframes-editorial-videodirectory absolute pathreferencesRoot:{skillRoot}/referencesscriptsRoot:{skillRoot}/scriptsthemesRoot:{skillRoot}/themessrtPath: the absolute path of the SRT file provided by the userprojectBaseDir:{dirname(srtPath)}/hyperframes-editorial-video-projectsprojectRoot:{projectBaseDir}/{yyyy-mm-dd-hh-mm-ss}
Mandatory requirements:
- The expanded absolute paths must be written into the SubAgent prompt; do not pass only variable names.
- Stage protocol documents can only be read from
referencesRoot. - Scripts can only be executed from
scriptsRoot. - All runtime state must be explicitly passed by the main Agent.
Workflow
0. Environment pre-check
Before entering formal production, the main Agent must first complete the environment pre-check. If the pre-check fails, immediately pause and report the missing items.
Pre-check commands:
node --version
npm --version
npx hyperframes --version
ffmpeg -version
Decision rules:
node --versionmust bev22.0.0or higher.npm --versionmust successfully output the version number.npx hyperframes --versionmust successfully output the version number; if the first execution requires downloading the CLI over the network, it should be completed before formal production.ffmpeg -versionmust successfully output version information.- If any pre-check fails, you must clearly tell the user which environment item does not meet the requirements, and attach the failed command, actual output, or reason for the missing item.
1. Determine the theme and SRT path
The SRT subtitle file path is a required input condition. If the user does not provide an SRT path, pause first and ask the user to provide it.
The user must explicitly select a theme. When showing themes to the user, preferentially use theme.json in nameZh, and also indicate
the corresponding themeId:
- Dark style (
dark-editorial) - Kraft paper style (
kraft-editorial) - Klein blue style (
klein-blue) - Sage green style (
sage-green)
If the user has not specified a theme, pause first and ask the user to choose from the above Chinese style names; do not choose a default on their behalf. When actually executing the script
use the one in parentheses themeId。
If the user provides a relative SRT path, the main Agent must first resolve it to an absolute path and confirm that the file exists. All subsequent
steps uniformly use the finally confirmed srtPath。
2. Initialize the project
Execute:
node "{scriptsRoot}/init-project.mjs" --srt-path "{srtPath}" --theme "{themeId}"
The script will create {dirname(srtPath)}/hyperframes-editorial-video-projects/{timestamp}/, copy the template styles,
copy the theme token, write .theme, and create src/scenes/ and scene-plans/。
3. Generate groups.json and storyboard.json
This stage must be executed using the storyboard SubAgent; when the user triggers this skill, it is deemed as explicitly authorizing the use of a
SubAgent for this stage. The main Agent is prohibited from generating groups.json or directly generating storyboard.json itself to replace the
storyboard SubAgent. The main Agent is only responsible for computing and expanding:
storyboardReference = {referencesRoot}/storyboard-parser.mdstoryboardScript = {scriptsRoot}/generate-storyboard.mjs
The SubAgent first reads storyboard-parser.md, then reads the SRT, and generates by semantics and time
{projectRoot}/groups.json. Then run:
node "{storyboardScript}" "{srtPath}" "{projectRoot}/groups.json" "{projectRoot}/storyboard.json"
The script is responsible for parsing the SRT, validating the continuity of groups, and generating storyboard.json。
4. Shard by creator and implement scenes in parallel
After the main Agent reads {projectRoot}/storyboard.json , it must assign one
creator for every 10 storyboard scenes. Creator shards are parallel SubAgent work units, not local implementation tasks for the main Agent.
The creator naming rule is fixed:
const creatorId = `creator-${String(index + 1).padStart(2, "0")}`;
For each creator, execute:
node "{scriptsRoot}/generate-creator-scenes.mjs" \
"{projectRoot}/storyboard.json" \
"{creatorId}" \
"10" \
"{projectRoot}/scene-plans/{creatorId}.scenes.json"
An independent creator SubAgent must be started for each creator shard; if the number of creators is greater than 1, all creator SubAgents must be started in parallel in the same round as much as possible, not serially. Each creator only receives its own .scenes.json source of truth and
references/scene-creator.md protocol. The global skill and creator stage reference documents are to be read by
scene-creator.md according to responsibilities and the selection result, and are not listed repeatedly in the main flow.
The main Agent is prohibited from directly writing any SceneXXX.html、SceneXXX.css or SceneXXX.js file to replace the
creator SubAgent. The main Agent's responsibilities are sharding, starting creator SubAgents, waiting for all creators to finish, reviewing
results, assembling the composition, and running the final validation.
- Generate
{projectRoot}/scene-plans/{creatorId}.json - Run
validate-scene-plan.mjs - Write
{projectRoot}/src/scenes/SceneXXX.html - Write
{projectRoot}/src/scenes/SceneXXX.css - Write
{projectRoot}/src/scenes/SceneXXX.js - Run
validate-scene-js.mjs
The creator must not modify the final index.html。
The prompt given to the creator SubAgent must remain low-noise.creatorId is only used by the main Agent for sharding and naming files,
do not pass it to the SubAgent, and do not inline the scene JSON into the prompt. The main Agent first expands:
scenesDataPath = "{projectRoot}/scene-plans/{creatorId}.scenes.json"
planPath = "{projectRoot}/scene-plans/{creatorId}.json"
tokensPath = "{projectRoot}/styles/tokens.css"
validateScript = "{scriptsRoot}/validate-scene-plan.mjs"
validateJsScript = "{scriptsRoot}/validate-scene-js.mjs"
Then use the recommended template:
你是 HyperFrames Editorial scene creator,负责 scenesDataPath 中列出的所有 scenes。
## 路径
- projectRoot: "{projectRoot}"
- scenesDataPath: "{scenesDataPath}"
- planPath: "{planPath}"
- referencesRoot: "{referencesRoot}"
- tokensPath: "{tokensPath}"
- validateScript: "{validateScript}"
- validateJsScript: "{validateJsScript}"
## 任务
读取 "{referencesRoot}/scene-creator.md",按其中协议完成 scene-plan、校验和
SceneXXX.html/css/js 片段实现。全局 skill 和二级参考文档的读取顺序以 scene-creator.md 为准。
scene-plan 校验命令:
node "{validateScript}" "{planPath}" "{scenesDataPath}"
写完 SceneXXX.html/css/js 后的 JS timing 校验命令:
node "{validateJsScript}" "{projectRoot}" "{scenesDataPath}"
不要修改最终 index.html。完成后按 scene-creator.md 的返回格式报告结果。
5. Assemble the HyperFrames composition
After all creators are finished, execute:
node "{scriptsRoot}/generate-composition.mjs" \
"{projectRoot}" \
"{projectRoot}/storyboard.json"
The script will generate the final {projectRoot}/index.html, create a unique paused GSAP timeline, hard-cut scenes,
and call the builder registered by each scene fragment.
The final HTML must serve both sets of HyperFrames sources of truth:
- GSAP main timeline: each scene must use
tl.addLabel(scene.id, scene.startTime / 1000)to register a label, and hard-cut display according to SRT time. - Studio/debug timeline: each
<section id="scene_xxx" class="ed-scene">must be automatically filled in bygenerate-composition.mjswithclass="clip"、data-start、data-durationanddata-track-index="0"。data-startcomes fromstoryScene.startTime / 1000;data-durationFor non-last scenes use "the interval to the next scene minus 0.001 seconds", to avoid the floating-point boundary beingnpx hyperframes lintjudged asoverlapping_clips_same_track。
creator fragments do not need to, and must not, hand-write these clip metadata; they are the responsibility of the final assembly script.
6. Pre-delivery validation
At minimum run:
node "{scriptsRoot}/validate-ed.mjs" "{projectRoot}/index.html" "{projectRoot}/storyboard.json"
npx hyperframes lint "{projectRoot}"
storyboardDerivedTimes=$(node "{scriptsRoot}/generate-inspect-times.mjs" "{projectRoot}/storyboard.json")
npx hyperframes inspect "{projectRoot}" --at "$storyboardDerivedTimes" --json
generate-inspect-times.mjs will compute from {projectRoot}/storyboard.json compute storyboardDerivedTimes, in comma-separated seconds format. The time points cover the key frames of each scene:
- about 0.2s after the scene starts.
- the stable point after the skeleton is established, usually about 1.0s after the scene starts; for short scenes it may be moved earlier appropriately.
- Near the
scene.startTime + segment.relativeStartof each segment. - about 0.2s before the scene ends.
inspect does not use --strict; errors must be fixed, and warnings are judged by the main Agent based on semantics as to whether they need fixing.
npx hyperframes lint must reach errorCount: 0. In particular, none of the following may appear:
timed_element_missing_clip_classoverlapping_clips_same_track
If the scene count,data-start、data-duration or class="clip"have been regenerated, and the user is using
Studio/debug mode, the main Agent should back up or clean {projectRoot}/.thumbnailsto let the debug timeline re-read the latest
scene clip index. Prefer a non-destructive backup directory, such as .thumbnails.bak-<timestamp>。
Exception: ghost text is allowed to intentionally overflow the frame. If inspect reports text_box_overflow occurs only on ghost
-class decorative large text, such as .ed-ghost-type、.sh-ghost、.es-ghost or semantically equivalent
ghost heading/text, and the main content, subtitles, charts, labels and key visuals are not obscured or truncated, then it is considered a design-allowed
overflow; do not adjust the ghost's position, font size,bottom、overflow or clipping method in order to eliminate this error.
The main Agent only needs to note in the validation summary that these text_box_overflow are ghost design overflow and continue rendering.
7. Render the final video
After pre-delivery validation passes, execute:
npx hyperframes render "{projectRoot}" --quality high --output "{projectRoot}/output.mp4" > "{projectRoot}/render.log" 2>&1
node "{scriptsRoot}/validate-render-log.mjs" "{projectRoot}/render.log"
The final video is output fixed to {projectRoot}/output.mp4. If the file already exists, the main Agent must first confirm whether the current render
should overwrite the old file; do not output the final video to the default renders/ timestamp directory.
After rendering completes, must check {projectRoot}/render.log. If the logs contain timeline not registered, JS exception,
q(...) used as a DOM element, or GSAP target not found, the main Agent must first return to the corresponding
src/scenes/SceneXXX.js to fix it, then re-run generate-composition.mjs, pre-delivery validation and render.
Do not only modify the final index.html。
data structure
storyboard.json
interface Storyboard {
totalDuration: number;
sceneCount: number;
scenes: {
id: string;
startTime: number;
duration: number;
displayDuration?: number;
segments: {
text: string;
relativeStart: number;
relativeDuration: number;
}[];
}[];
}
Resource navigation
assets/template/: HyperFrames composition style templates.themes/: built-in themes, each theme containstheme.jsonandtokens.css。references/storyboard-parser.md: SRT to groups/storyboard protocol.references/scene-creator.md: creator planning and fragment implementation protocol.references/TIMING-CANON.md: SRT relative time and focus cue rules.references/VISUAL-SYSTEM.md: token, primitive class and theme rules.references/BEAT-ARCHETYPES.md: layout index, graphical selection rules and layout common contract.references/layout-patterns/: progressively read perlayout_idfor single layout detailed constraints.references/MOTION-CANON.md: GSAP and HyperFrames common animation rules.scripts/init-project.mjs: create a project from SRT and theme.scripts/generate-storyboard.mjs: generate storyboard from SRT and groups.scripts/generate-creator-scenes.mjs: split local scenesData for creator.scripts/validate-scene-plan.mjs: validate creator scene-plan.scripts/validate-scene-js.mjs: validate SceneXXX.js timing during the creator stage.scripts/generate-composition.mjs: assemble the finalindex.html。scripts/generate-inspect-times.mjs: fromstoryboard.jsongenerateinspect --attime point.scripts/validate-ed.mjs: add static checks.scripts/validate-render-log.mjs: check for black-screen-level runtime errors in the final render log.
User shortcut commands
Generate a 4K 60 fps version
When the user says semantically equivalent commands such as "generate a 4K 60 fps version of a certain video", "generate 4K60", "export 4k 60fps", etc., the main Agent automatically executes this process and does not need to go through the SRT grouping, scene creator, or composition generation process again.
First determine projectRoot:
- If the user gives a HyperFrames project directory, use that directory directly.
- If the user gives
{projectRoot}/output.mp4、output.mp4or another video file located in the project root directory, and the same directory containsindex.html, use the directory where that video file is located asprojectRoot。 - If only an isolated video file can be obtained and the HyperFrames project directory cannot be inferred from the same directory, first ask the user to provide the corresponding
HyperFrames project directory;
npx hyperframes renderis re-rendered from the composition, not ordinary video transcoding.
Before execution, if {projectRoot}/output-4k.mp4 already exists, you must first ask the user whether to overwrite it. Do not overwrite without explicit consent.
Execute:
npx hyperframes render "{projectRoot}" \
--resolution landscape-4k \
--fps 60 \
--quality high \
--output "{projectRoot}/output-4k.mp4" \
> "{projectRoot}/render-4k.log" 2>&1
node "{scriptsRoot}/validate-render-log.mjs" "{projectRoot}/render-4k.log"
Description:
landscape-4koutputs 3840x2160, suitable for this skill's default 1920x1080 landscape composition.--fps 60outputs 60fps;--quality highis used for final delivery.- The output file is fixedly named
{projectRoot}/output-4k.mp4。 - After rendering is complete, you must check
render-4k.log. If the log contains timeline not registered, JS exception,q(...)used as a DOM element, or GSAP target not found, first fix the correspondingsrc/scenes/SceneXXX.js, rerungenerate-composition.mjs, then re-render the 4K 60 fps version.
Turn on debug mode
When the user says semantically equivalent commands such as "turn on debug mode", "enter debug mode", "preview debug", etc., the main Agent automatically executes this process. Debug mode uses HyperFrames Studio preview.
First determine projectRoot. If the current conversation does not have a clear project directory, first ask the user to provide the HyperFrames project directory; that directory
must contain index.html。
Then ask the user to provide the debug audio file path. After obtaining the audio:
- Confirm that the audio file exists.
- If the audio is not in
{projectRoot}, copy it to{projectRoot}/assets/debug-audio{ext}; ifassets/does not exist, create it first. - In
{projectRoot}/index.html, find the fixed debug audio slot and only replace the content inside the slot. Normally generatedindex.htmlalready has this slot preset; when there is no audio, the slot is empty and does not affect preview or render:
<!-- ED_DEBUG_AUDIO_SLOT_START -->
<!-- Debug audio is inserted here during preview-only debug mode. Keep empty for normal renders. -->
<!-- ED_DEBUG_AUDIO_SLOT_END -->
After inserting audio, it should become:
<!-- ED_DEBUG_AUDIO_SLOT_START -->
<audio
id="ed-debug-audio"
data-start="0"
data-track-index="99"
src="assets/debug-audio.mp3"
data-volume="1"
></audio>
<!-- ED_DEBUG_AUDIO_SLOT_END -->
Rules:
- Only between
ED_DEBUG_AUDIO_SLOT_STARTandED_DEBUG_AUDIO_SLOT_END, write or remove debug audio. Do not search<div id="main">or scene positions to decide the insertion point yourself. - If the slot already contains old debug
<audio>, directly replace the content inside the slot; do not repeatedly insert multiple<audio>。 - Audio is only used as a debugging aid. Do not write it into
src/scenes/SceneXXX.*, do not modifystoryboard.json, and do not regroup. - If rerunning
generate-composition.mjsoverwritesindex.html, it will preserve the empty slot; you need to write the debug audio into that slot again before preview. - Do not call
audio.play(); HyperFrames is responsible for media playback and timeline sync.
Start preview:
npx hyperframes preview "{projectRoot}" --port "{port}"
Choose an unoccupied port, preferably starting from 3002 ; if it is occupied, increment. Record the preview process PID / session,
for stopping debug mode. After successful startup, tell the user the Studio URL:
http://localhost:{port}/#project/{project-directory-name}
If preview does not automatically open the browser, use the system open command to open the above Studio URL.
During debug mode, when the user gives specific feedback such as "what's wrong with scene N", "there's a problem with scene_00N", "some visual element is occluded, misaligned, not appearing, or the pacing is off":
- Locate the storyboard scene based on the user's description: preferentially match
scene_00N; if the user says "scene N", map it toSceneNNN.html/css/jsandscene_00N。 - Read the corresponding
src/scenes/SceneNNN.html、SceneNNN.css、SceneNNN.js, the related scene-plan, andstoryboard.jsonfragments. - Only modify the corresponding scene source file; do not directly modify the final
index.htmlassembled fragments. - Reassemble the composition so preview hot-reloads:
node "{scriptsRoot}/generate-composition.mjs" "{projectRoot}" "{projectRoot}/storyboard.json"
- Write the debug audio back into the fixed slot, because
generate-composition.mjswill restore the slot to empty. - Keep preview running so the user can continue viewing in Studio. Do not automatically run validation scripts in debug mode; only run them when the user explicitly requests checking, acceptance, or pre-render confirmation, then run
validate-scene-js.mjs、validate-ed.mjsornpx hyperframes inspect。
Stop debug mode
When the user says semantically equivalent commands such as "stop debug mode", "close debug mode", "exit debug":
- Clear
{projectRoot}/index.htmlinED_DEBUG_AUDIO_SLOT_STARTtoED_DEBUG_AUDIO_SLOT_ENDthe temporary audio in between, keeping the slot comments themselves. - Stop the previously recorded
npx hyperframes previewprocess / session. - Do not delete the user's original audio files.
{projectRoot}/assets/debug-audio{ext}is a debug copy and can be kept; only delete it when the user explicitly requests cleanup. - Report that debug mode has been stopped, and explain that the debug audio has been removed from the timeline.