Complete workflow for converting SRT subtitle files into Remotion videos.
Workflow Overview
┌──────────┐ ┌──────────┐ ┌──────────┐ ┌──────────┐ ┌──────────────────────┐ ┌──────────┐
│ 获取 SRT │ → │ 依赖预检 │ → │ 项目初始化│ → │ 生成分镜 │ → │ 并行 Creator 规划实现 │ → │ 合成视频 │
│ 文件路径 │ │ / 首次安装│ │ │ │ │ │ scene-plan + code │ │ │
└──────────┘ └──────────┘ └──────────┘ └──────────┘ └──────────────────────┘ └──────────┘
Project Directory Structure
<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}/
Path Contract
The main workflow and all SubAgents uniformly use the following absolute path conventions:
skillRoot: currentsrt-remotion-videoabsolute path of the skill directorytemplateRoot:{skillRoot}/templatereferencesRoot:{skillRoot}/referencesscriptsRoot:{skillRoot}/scriptssrtPath: absolute path of the SRT file provided by the userprojectBaseDir:{dirname(srtPath)}/remotion-video-projectsprojectRoot: current project instance directory, in the format{projectBaseDir}/{projectName}/
Mandatory Requirements:
- The expanded absolute paths must be written into the SubAgent prompt; do not just pass variable names
- Phase protocol documents can only be read from
referencesRootRead - Scripts can only be executed from
scriptsRootExecute - All runtime state must be explicitly passed by the main Agent
Execution Flow
Step 0: Obtain the SRT File
- Ask the user for the SRT file path
- If the user provides a relative path, the main Agent must first determine on its own whether the file exists
- If it exists, the main Agent must first resolve it to an absolute path, then use the resolved absolute path as the
srtPath - If it does not exist, it must clearly inform the user that the path is invalid and require a correct path
- All subsequent steps uniformly use the finally confirmed absolute path
srtPath
Step 1: Dependency Pre-check and Project Initialization
Key: the template is always copied from inside the skill, and all work is performed in an independent project directory under the subtitle directory.
1.0 Dependency Pre-check (automatically installed on first use)
Execute:
node "{skillRoot}/scripts/ensure-template-deps.js" "{templateRoot}"
The script will:
- Check
{templateRoot}/package.jsonand{templateRoot}/package-lock.json - Check whether the template's key dependencies are installed
- If not installed, then under
{templateRoot}execute oncenpm install - If already installed, skip installation directly
- If installation or validation fails, return a clear error and stop the main workflow
1.1 Default Behavior: Create a New Project
Execute:
node "{skillRoot}/scripts/init-project.js" --srt-path "{srtPath}"
The script will:
- Ensure
{dirname(srtPath)}/remotion-video-projects/exists - Create a new project directory
remotion-video-projects/{yyyy-mm-dd-hh-mm-ss}/ - From
{skillRoot}/template/copy the template files; if the template dependencies are installed, also copy the installed dependencies - Output project information JSON
1.2 User-specified Project Path (only when the user explicitly specifies it)
If the user explicitly specifies a project path, use that path directly as projectRoot, skipping the default directory derivation.
1.3 Record Key Paths
Obtain from the script output or the user-specified path:
projectRootskillRoottemplateRootreferencesRootscriptsRootsrtPath
All subsequent steps use these absolute paths.
Step 2: Generate the Storyboard Script
This step must be executed using a SubAgent.
The main Agent is responsible for:
- Calculate and expand the absolute paths:
storyboardReference = {referencesRoot}/storyboard-parser.mdstoryboardScript = {scriptsRoot}/generate-storyboard.js
- Launch a SubAgent
- Write the actual absolute path values into the prompt
SubAgent prompt template:
你正在执行 srt-remotion-video 工作流的“分镜生成阶段”。
首先读取以下参考协议并严格按其步骤执行:
- {storyboardReference}
输入参数:
- skillRoot: {skillRoot}
- projectRoot: {projectRoot}
- srtPath: {srtPath}
重要:
1. 所有路径都已展开为绝对路径,不要自行猜测
2. 需要执行的脚本位于 {storyboardScript}
3. 完成后必须按参考协议中的“完成后返回”契约,返回结构化结果
The main workflow must wait for the returned result and read storyboard.json to verify the structure is correct.
Step 3: Use SubAgent to plan and implement scene components
Read storyboard.json, to obtain all scene data.
3.0 Pre-preparation: Compute grouping
const SCENES_PER_CREATOR = 5;
const sceneCount = storyboard.scenes.length;
const creatorCount = Math.ceil(sceneCount / SCENES_PER_CREATOR);
creatorId Generation rule is fixed as:
const creatorId = `creator-${String(index + 1).padStart(2, '0')}`;
Example:
- 1st creator:
creator-01 - 2nd creator:
creator-02 - 10th creator:
creator-10
The main flow must always use this format, do not omit leading zeros, do not change to another naming method.
3.1 Plan Creator tasks
The main flow is responsible for scheduling:
- Generate for each creator
scenesDataPath = {projectRoot}/scene-plans/{creatorId}.scenes.json - Compute for each creator:
creatorIdplanPath = {projectRoot}/scene-plans/{creatorId}.jsonvalidateScript = {scriptsRoot}/validate-scene-plan.js
- Execute for each creator:
node "{scriptsRoot}/generate-creator-scenes.js" \
"{projectRoot}/storyboard.json" \
"{creatorId}" \
"{SCENES_PER_CREATOR}" \
"{scenesDataPath}"
- The main Agent writes the
{scenesDataPath}absolute path into the SubAgent prompt - Start all creator SubAgents in parallel
3.2 Start all Scene Creators in parallel
SubAgent prompt template for each Creator:
你正在执行 srt-remotion-video 工作流的“场景规划与实现阶段”。
首先读取以下参考协议并严格按其步骤执行:
- {referencesRoot}/scene-component-creator.md
输入参数:
- skillRoot: {skillRoot}
- projectRoot: {projectRoot}
- creatorId: {creatorId}
- planPath: {planPath}
- scenesDataPath: {scenesDataPath}
- validateScript: {validateScript}
重要:
1. 所有路径都已展开为绝对路径,不要自行猜测
2. 当前 creator 的场景事实源只允许来自 {scenesDataPath}
3. 规划阶段只使用 {scenesDataPath}、{projectRoot}/cartoon-ui-style-guide.css、{projectRoot}/cartoon-ui-style-guide-reference.md 和 {skillRoot}/../remotion-best-practices/SKILL.md
4. 先生成 scene-plan JSON,再执行校验,校验通过后再编写场景组件
5. `beatPlan` 默认一段字幕对应一个 beat;如果相邻 segments 明显属于同一句连续表达,可以合并
6. 合并仅允许发生在相邻 segments 之间,禁止跳跃式组合
7. `beatPlan` 只声明 `segments` 和 `action`;实际时间必须从 scenesData[].segments 的 `relativeStart / relativeDuration` 推导
8. 场景主节奏必须绑定 scenesData[].segments[].relativeStart / relativeDuration
9. 默认保留宿主背景,在透明根层上围绕画面中部或中上区域组织主视觉;不要重建整屏背景
10. 组件接口固定为 React.FC<{ segments: Segment[] }> 且使用默认导出
11. 只负责产出 {projectRoot}/src/scenes/SceneXXX.tsx;若文件不存在则创建,若已存在则仅修改自己负责的场景文件
12. 不要手改 {projectRoot}/src/compositions/Main.tsx 或 generated-scenes.ts
13. 完成后必须按参考协议中的“完成后返回”契约,返回结构化结果
14. `remotion-best-practices` 与当前 skill 同级,固定入口为 {skillRoot}/../remotion-best-practices/SKILL.md
3.3 Wait for all Creators to finish
Confirm that all target scene component files have been generated.
componentResultsis only used for task completion feedback, and is not the true source for final registration file assembly or total duration calculation.
Step 4: Synthesize video
4.1 Generate scene registration file
The normal video generation flow must not rewrite {projectRoot}/src/compositions/Main.tsx。
Template default output specifications:1920x1080 / 30fps。
generated-scenes.tsoftotalDurationInFramesis generated bygenerate-scenes-registry.js, do not modify manuallyMain.tsxinmsToFramesmust useuseVideoConfig().fpsto dynamically obtain the frame rate, cannot hardcodeFPSconstant
Execute:
node "{scriptsRoot}/generate-scenes-registry.js" \
"{projectRoot}" \
"{projectRoot}/storyboard.json"
Runtime contract is fixed:
- Each
SceneXXX.tsxexposes the component through a default export generated-scenes.tsis responsible for savingstart、duration、segments、ComponentMain.tsxis responsible for using<Component segments={scene.segments} />to pass segment data to the scene component
4.2 Root.tsx total duration synchronization
Root.tsx is a read-only template file, and does not need to and must not be rewritten in the normal flow.
Requirements:
Root.tsxmust keep reading fromgenerated-scenes.tsreadtotalDurationInFrames- Do not repeatedly manually calculate or manually fill in the total frame count in the flow
4.3 Validate project artifact completeness
Must execute before rendering:
node "{scriptsRoot}/validate-project.js" \
"{projectRoot}" \
"{projectRoot}/storyboard.json"
If validation fails, the flow must stop and rendering must not continue.
4.4 Execute rendering
cd "{projectRoot}"
npx remotion render Main out/output.mp4
Step 5: Complete
Notify the user:
- Video has been generated
- Output path:
{projectRoot}/out/output.mp4 - Number of scenes: N
- Video duration: X seconds
Debug mode and re-rendering
After the main video generation flow (steps 0–5) is complete, the user can request "debug mode" or "re-render".
Both of these operations assume that
projectRootalready exists and the scene components have been fully generated.
Debug mode
Execute when the user says "debug mode", "preview mode" or similar expressions and requests to add audio.
TM.0 Obtain audio file
- If the user has provided an audio file path, verify that the file exists and resolve it to the absolute path
audioPath - If the user has not provided an audio file path, must ask the user
- Verify that the file exists; if it does not exist, report back to the user and stop
TM.1 Add audio to timeline
- Ensure the
{projectRoot}/public/directory exists - Copy the audio file as
{projectRoot}/public/audio.mp3
mkdir -p "{projectRoot}/public"
cp "{audioPath}" "{projectRoot}/public/audio.mp3"
-
Modify
{projectRoot}/src/compositions/Main.tsx:- Add to the import line
AudioandstaticFile:import { AbsoluteFill, Audio, Sequence, staticFile, useCurrentFrame } from "remotion"; - In
<AbsoluteFill style={{ backgroundColor: ... }}>add at the very beginning of the direct children:<Audio src={staticFile("audio.mp3")} />
- Add to the import line
-
Start Remotion Studio for the user to preview:
cd "{projectRoot}"
npx remotion studio
TM.2 Completion notification
Inform the user that Remotion Studio has started, the audio has been added to the timeline, and it can be previewed in the browser.
Re-render
Execute when the user says "re-render", "render again", or similar expressions.
RR.0 Remove audio from the timeline
Before rendering the final video, you must ensure that Main.tsx there is no audio component in:
- Read
{projectRoot}/src/compositions/Main.tsx - Check whether it contains the
<Audiotag - If it exists:
- Remove
<Audio src={staticFile("audio.mp3")} />this line - Remove from the import statement
AudioandstaticFile(if they are no longer used by other code)
- Remove
- If it does not exist, skip this step
RR.1 Execute rendering
cd "{projectRoot}"
npx remotion render Main out/output.mp4
RR.2 Completion notification
Notify the user that the video has been re-rendered, and the output path is {projectRoot}/out/output.mp4。
High-resolution / high-frame-rate rendering
Execute when the main video generation process has already been completed and the user requests generating a 4K, 60fps, or other version higher than the default configuration (1080p 30fps).
This operation assumes that
projectRootalready exists and the scene components have been fully generated.
Key principle: separate design resolution from output resolution
All elements in the scene components (cards, icons, text, etc.) useabsolute pixel values, based on a 1920x1080 design.Directly changing Root.tsx's width/height to 3840x2160 will cause all elements to shrink in proportion within the frame. The correct approach is tokeep the design resolution at 1920x1080 unchanged, and use Remotion's --scale parameter to scale up the output resolution.
Common mistakes (prohibited)
| Incorrect approach | Consequence |
|---|---|
| Change Root.tsx's width=3840 height=2160 | All scene elements shrink to half their proportion |
Use the --width 3840 --height 2160 CLI parameter |
Same as above |
| Change only fps without changing totalDurationInFrames | The video only has content in the first half, and the second half is blank |
Hardcode in Main.tsx const FPS = 30 |
After changing Root.tsx fps, the scene timing becomes disordered |
HR.0 Confirm the user's requirements
Parse the user's requirements into specific output parameters:
| User requirement | Root.tsx modification | generated-scenes.ts modification | Render command |
|---|---|---|---|
| 4K / Ultra HD | Do not change | Do not change | --scale 2 |
| 60fps | fps={60} |
totalDurationInFrames Convert proportionally |
No scale needed |
| 4K 60fps | fps={60} |
totalDurationInFrames Convert proportionally |
--scale 2 |
HR.1 Modify the frame rate (only when the user requests a high frame rate)
- Modify
{projectRoot}/src/Root.tsxthefpsvalue in:
fps={60} // 从 30 改为 60
- Modify
{projectRoot}/src/compositions/generated-scenes.tsthetotalDurationInFrames:
// 帧数 = 原帧数 × (新fps / 原fps)
// 例如 30→60fps: 1572 × 2 = 3144
export const totalDurationInFrames = {原帧数 × 新fps / 原fps};
Key:{projectRoot}/src/Root.tsx in <Composition> 's width and height do not modify, must keep 1920 and 1080. Resolution upscaling is done by the --scale parameter at render time, rather than modifying the design resolution.
Main.tsxinmsToFramesmust useuseVideoConfig().fpsto dynamically get the frame rate. If you findMain.tsxhas a hardcodedFPSconstant, you must first fix it touseVideoConfig().fps, otherwise after the fps changes the scene timing will be completely disrupted.
HR.2 Verification Items
node "{scriptsRoot}/validate-project.js" \
"{projectRoot}" \
"{projectRoot}/storyboard.json"
If verification fails, you must stop and must not continue rendering.
HR.3 Execute Rendering
cd "{projectRoot}"
npx remotion render Main out/output-4k.mp4 --scale 2
--scale 2: upscale the 1920x1080 design canvas by 2x and render as 3840x2160- Vector elements (text, SVG) will be rendered at higher resolution, resulting in clearer image quality
- The layout is exactly the same as 1080p, with no issue of elements being scaled down
- If you don't need 4K and only need 60fps, remove
--scale 2and it's fine
HR.4 Completion Notification
Notify the user:
- Output path:
{projectRoot}/out/output-4k.mp4 - Output resolution, frame rate, duration
- If fps was modified, remind the user that the fps in Root.tsx has been changed from 30 to the target value
Data Structure Reference
storyboard.json
interface Storyboard {
totalDuration: number;
sceneCount: number;
scenes: {
id: string;
startTime: number;
duration: number;
segments: {
text: string;
relativeStart: number;
relativeDuration: number;
}[];
semanticTags?: string[];
visualHint?: string;
}[];
}
scene-plan JSON
interface ScenePlanCard {
sceneId: string;
goal: string;
layout: string;
visualCore: string;
surface: string;
emphasis: string;
screenShouldShow: string[];
beatPlan: {
segments: number[];
action: string;
}[];
}
SceneComponentResult
interface SceneComponentResult {
sceneId: string;
componentPath: string;
componentName?: string;
planPath?: string;
}
Resources
template/
- Lightweight template project, distributed together with the skill
- On first use, run dependency installation in the template directory; subsequent projects reuse the template dependencies
references/
storyboard-parser.md: Storyboard generation phase protocolscene-component-creator.md: Scene planning and implementation phase protocoltheme-template-switching.md: Theme template replacement guide
scripts/
ensure-template-deps.js: Check template dependencies, perform first-time installation if necessaryinit-project.js: Initialize the project based onsrtPath: Initialize the project based on SRT and groups.json to generate storyboard.jsongenerate-storyboard.js: Generate storyboard.json based on SRT and groups.jsongenerate-creator-scenes.js: Generate scenesData JSON for the specified creator based on storyboard.jsongenerate-scenes-registry.js: Generategenerated-scenes.tsscene-registry-utils.js: Shared utilities for registry and validationvalidate-project.js: Pre-render integrity verificationvalidate-scene-plan.js: Verify the scene-plan JSON structure and segment bindings
Execution Checklist
Main Flow
- Get the absolute path of the SRT provided by the user
- Run
ensure-template-deps.jsCheck template dependencies, complete first-time installation if necessary - Run
init-project.js --srt-pathCreate the project - Get
projectRoot、skillRoot、templateRoot、referencesRoot、scriptsRoot - Use
references/storyboard-parser.mdGeneratestoryboard.json - Verify
storyboard.jsonstructure is correct - Compute Creator grouping
- Use
references/scene-component-creator.mdGenerate scene-plan and scene components in parallel - Run
generate-scenes-registry.js - Run
validate-project.js - Execute rendering
Debug Mode
- Get the absolute path of the audio file provided by the user
- Copy the audio to
{projectRoot}/public/audio.mp3 - Modify
Main.tsxAdd<Audio>component - Start Remotion Studio for user preview
Re-render
- Check
Main.tsxwhether<Audio>tag exists - If it exists, remove
<Audio>and related imports - Execute rendering
High Resolution / High Frame Rate Rendering
- Parse the user's requirements into specific output resolution, frame rate, and scale values
- Confirm
Main.tsxinmsToFramesuseuseVideoConfig().fpsrather than hardcoded constants - Only when high frame rate is needed: modify
Root.tsx'sfpsandgenerated-scenes.ts'stotalDurationInFrames - Confirm
Root.tsx'swidth/heightkeep 1920/1080 unchanged - Run
validate-project.jsto validate - Use
--scale 2(at 4K) perform rendering
Notes
- All paths must use absolute paths
- The SubAgent prompt must pass actual path values, not just variable names
- Template resources are located at
{skillRoot}/template - The template is distributed in a lightweight form; on first use,
template/dependency pre-check must first be completed - The default project directory is located at
{dirname(srtPath)}/remotion-video-projects Main.tsx、Root.tsxbelongs to the protected host layer- Scene components must actually consume
segments validate-project.jsIf it fails, rendering must not continue- If the user wants to change the theme template, they must first refer to
references/theme-template-switching.md