Loading...
Loading...
Main workflow for SRT subtitle-driven video generation. Convert SRT subtitle files into Remotion video projects, automatically generate storyboard scripts, create scene components, and synthesize the final video. Used when users need to generate Remotion videos from SRT subtitle files.
npx skill4agent add yangagent/remotion-video-skill srt-remotion-video┌──────────┐ ┌──────────┐ ┌──────────┐ ┌──────────┐ ┌──────────────────────┐ ┌──────────┐
│ Get SRT │ → │ Dependency │ → │ Project │ → │ Generate │ → │ Parallel Creator │ → │ Synthesize│
│ File Path│ │ Precheck/ │ │ Initialization │ │ Storyboard │ │ Planning & Implementation │ │ Video │
│ │ │ First-time │ │ │ │ │ │ scene-plan + code │ │ │
│ │ │ Installation │ │ │ │ │ │ │ │ │
└──────────┘ └──────────┘ └──────────┘ └──────────┘ └──────────────────────┘ └──────────┘<skillRoot>/
├── SKILL.md
├── template/
├── references/
│ ├── storyboard-parser.md
│ └── scene-component-creator.md
└── scripts/
├── ensure-template-deps.js
├── init-project.js
├── generate-storyboard.js
├── generate-creator-scenes.js
├── generate-scenes-registry.js
├── scene-registry-utils.js
├── validate-project.js
└── validate-scene-plan.js
<srtDir>/
├── your-file.srt
└── remotion-video-projects/
└── {yyyy-mm-dd-hh-mm-ss}/skillRootsrt-remotion-videotemplateRoot{skillRoot}/templatereferencesRoot{skillRoot}/referencesscriptsRoot{skillRoot}/scriptssrtPathprojectBaseDir{dirname(srtPath)}/remotion-video-projectsprojectRoot{projectBaseDir}/{projectName}/referencesRootscriptsRootsrtPathsrtPathKey: Templates are always copied from inside the skill, and all work is performed in an independent project directory under the subtitle directory.
node "{skillRoot}/scripts/ensure-template-deps.js" "{templateRoot}"{templateRoot}/package.json{templateRoot}/package-lock.jsonnpm install{templateRoot}node "{skillRoot}/scripts/init-project.js" --srt-path "{srtPath}"{dirname(srtPath)}/remotion-video-projects/remotion-video-projects/{yyyy-mm-dd-hh-mm-ss}/{skillRoot}/template/projectRootprojectRootskillRoottemplateRootreferencesRootscriptsRootsrtPathstoryboardReference = {referencesRoot}/storyboard-parser.mdstoryboardScript = {scriptsRoot}/generate-storyboard.jsYou are executing the "Storyboard Generation Phase" of the srt-remotion-video workflow.
First read the following reference protocol and strictly follow its steps:
- {storyboardReference}
Input parameters:
- skillRoot: {skillRoot}
- projectRoot: {projectRoot}
- srtPath: {srtPath}
Important:
1. All paths have been expanded to absolute paths, do not guess on your own
2. The script to execute is located at {storyboardScript}
3. After completion, you must return structured results in accordance with the "Return After Completion" contract in the reference protocolstoryboard.jsonstoryboard.jsonconst SCENES_PER_CREATOR = 5;
const sceneCount = storyboard.scenes.length;
const creatorCount = Math.ceil(sceneCount / SCENES_PER_CREATOR);creatorIdconst creatorId = `creator-${String(index + 1).padStart(2, '0')}`;creator-01creator-02creator-10scenesDataPath = {projectRoot}/scene-plans/{creatorId}.scenes.jsoncreatorIdplanPath = {projectRoot}/scene-plans/{creatorId}.jsonvalidateScript = {scriptsRoot}/validate-scene-plan.jsnode "{scriptsRoot}/generate-creator-scenes.js" \
"{projectRoot}/storyboard.json" \
"{creatorId}" \
"{SCENES_PER_CREATOR}" \
"{scenesDataPath}"{scenesDataPath}You are executing the "Scene Planning and Implementation Phase" of the srt-remotion-video workflow.
First read the following reference protocol and strictly follow its steps:
- {referencesRoot}/scene-component-creator.md
Input parameters:
- skillRoot: {skillRoot}
- projectRoot: {projectRoot}
- creatorId: {creatorId}
- planPath: {planPath}
- scenesDataPath: {scenesDataPath}
- validateScript: {validateScript}
Important:
1. All paths have been expanded to absolute paths, do not guess on your own
2. The scene data source for the current creator is only allowed to come from {scenesDataPath}
3. During the planning phase, only use {scenesDataPath}, {projectRoot}/cartoon-ui-style-guide.css, {projectRoot}/cartoon-ui-style-guide-reference.md and {skillRoot}/../remotion-best-practices/SKILL.md
4. First generate the scene-plan JSON, then perform validation, and only write scene components after validation passes
5. By default, one subtitle segment corresponds to one beat in `beatPlan`; if adjacent segments clearly belong to the same continuous expression, they can be merged
6. Merging is only allowed between adjacent segments, skip merging is prohibited
7. `beatPlan` only declares `segments` and `action`; actual timing must be derived from `relativeStart / relativeDuration` of scenesData[].segments
8. The main scene rhythm must be bound to scenesData[].segments[].relativeStart / relativeDuration
9. By default, retain the host background, organize the main visual around the middle or upper-middle area of the screen on a transparent root layer; do not rebuild the full-screen background
10. The component interface is fixed as React.FC<{ segments: Segment[] }> and uses default export
11. Only responsible for producing {projectRoot}/src/scenes/SceneXXX.tsx; create the file if it does not exist, only modify the scene files you are responsible for if it already exists
12. Do not manually modify {projectRoot}/src/compositions/Main.tsx or generated-scenes.ts
13. After completion, you must return structured results in accordance with the "Return After Completion" contract in the reference protocol
14. `remotion-best-practices` is at the same level as the current skill, with a fixed entry at {skillRoot}/../remotion-best-practices/SKILL.mdis only used for task completion feedback, not as the real source for final registry file assembly or total duration calculation.componentResults
{projectRoot}/src/compositions/Main.tsx1920x1080 / 30fpstotalDurationInFramesgenerated-scenes.tsgenerate-scenes-registry.jsmsToFramesMain.tsxuseVideoConfig().fpsFPSnode "{scriptsRoot}/generate-scenes-registry.js" \
"{projectRoot}" \
"{projectRoot}/storyboard.json"SceneXXX.tsxgenerated-scenes.tsstartdurationsegmentsComponentMain.tsx<Component segments={scene.segments} />Root.tsxRoot.tsxtotalDurationInFramesgenerated-scenes.tsnode "{scriptsRoot}/validate-project.js" \
"{projectRoot}" \
"{projectRoot}/storyboard.json"cd "{projectRoot}"
npx remotion render Main out/output.mp4{projectRoot}/out/output.mp4Both operations assume thatexists and scene components have been generated.projectRoot
audioPath{projectRoot}/public/{projectRoot}/public/audio.mp3mkdir -p "{projectRoot}/public"
cp "{audioPath}" "{projectRoot}/public/audio.mp3"{projectRoot}/src/compositions/Main.tsxAudiostaticFileimport { AbsoluteFill, Audio, Sequence, staticFile, useCurrentFrame } from "remotion";<AbsoluteFill style={{ backgroundColor: ... }}><Audio src={staticFile("audio.mp3")} />cd "{projectRoot}"
npx remotion studioMain.tsx{projectRoot}/src/compositions/Main.tsx<Audio<Audio src={staticFile("audio.mp3")} />AudiostaticFilecd "{projectRoot}"
npx remotion render Main out/output.mp4{projectRoot}/out/output.mp4This operation assumes thatexists and scene components have been generated.projectRoot
--scale| Wrong Practice | Consequence |
|---|---|
| Change Root.tsx to width=3840 height=2160 | All scene elements shrink by half |
Use | Same as above |
| Only change fps without modifying totalDurationInFrames | Only the first half of the video has content, the second half is blank |
Hardcode | Scene timing is messed up after changing Root.tsx fps |
| User Requirement | Root.tsx Modification | generated-scenes.ts Modification | Render Command |
|---|---|---|---|
| 4K / Ultra HD | No change | No change | |
| 60fps | | Convert | No scale needed |
| 4K 60fps | | Convert | |
fps{projectRoot}/src/Root.tsxfps={60} // Changed from 30 to 60totalDurationInFrames{projectRoot}/src/compositions/generated-scenes.ts// Frame count = original frame count × (new fps / original fps)
// Example: 30→60fps: 1572 × 2 = 3144
export const totalDurationInFrames = {original frame count × new fps / original fps};widthheight<Composition>{projectRoot}/src/Root.tsx19201080--scaleinmsToFramesmust dynamically obtain the frame rate usingMain.tsx. If a hardcodeduseVideoConfig().fpsconstant is found inFPS, it must be fixed toMain.tsxfirst, otherwise scene timing will be completely messed up after fps changes.useVideoConfig().fps
node "{scriptsRoot}/validate-project.js" \
"{projectRoot}" \
"{projectRoot}/storyboard.json"cd "{projectRoot}"
npx remotion render Main out/output-4k.mp4 --scale 2--scale 2--scale 2{projectRoot}/out/output-4k.mp4interface Storyboard {
totalDuration: number;
sceneCount: number;
scenes: {
id: string;
startTime: number;
duration: number;
segments: {
text: string;
relativeStart: number;
relativeDuration: number;
}[];
semanticTags?: string[];
visualHint?: string;
}[];
}interface ScenePlanCard {
sceneId: string;
goal: string;
layout: string;
visualCore: string;
surface: string;
emphasis: string;
screenShouldShow: string[];
beatPlan: {
segments: number[];
action: string;
}[];
}interface SceneComponentResult {
sceneId: string;
componentPath: string;
componentName?: string;
planPath?: string;
}storyboard-parser.mdscene-component-creator.mdtheme-template-switching.mdensure-template-deps.jsinit-project.jssrtPathgenerate-storyboard.jsgenerate-creator-scenes.jsgenerate-scenes-registry.jsgenerated-scenes.tsscene-registry-utils.jsvalidate-project.jsvalidate-scene-plan.jsensure-template-deps.jsinit-project.js --srt-pathprojectRootskillRoottemplateRootreferencesRootscriptsRootstoryboard.jsonreferences/storyboard-parser.mdstoryboard.jsonreferences/scene-component-creator.mdgenerate-scenes-registry.jsvalidate-project.js{projectRoot}/public/audio.mp3Main.tsx<Audio>Main.tsx<Audio><Audio>msToFramesMain.tsxuseVideoConfig().fpsfpsRoot.tsxtotalDurationInFramesgenerated-scenes.tswidthheightRoot.tsxvalidate-project.js--scale 2{skillRoot}/templatetemplate/{dirname(srtPath)}/remotion-video-projectsMain.tsxRoot.tsxsegmentsvalidate-project.jsreferences/theme-template-switching.md