도입
2편에서는 Remotion 프로젝트를 처음 만들고, 코드 안에 직접 적어놓은 값(제목 텍스트, 색상 등)으로 첫 영상을 뽑았습니다.
코딩 몰라도 따라하는 Remotion 첫걸음 (Shorts 자동화 2편)
도입1편에서는 macOS와 Oracle A1 서버에 Remotion을 돌릴 준비를 마쳤습니다. 이번 편부터는 진짜 코딩이 들어갑니다. 단, 개발 경험이 없어도 명령어를 그대로 따라 치면 같은 결과가 나오도록, 나오
blog.jdevy.com
하지만 자동화를 하려면 매번 코드를 고칠 수는 없습니다 — 대본이 바뀌면 영상도 그에 맞게 바뀌어야 합니다. 이번 편에서는 코드는 그대로 두고 JSON 파일만 바꿔도 영상 내용이 바뀌는 구조를 만듭니다. 이게 바로 자동화 파이프라인의 핵심 원리입니다.

왜 이 구조가 필요한가
2편에서는 titleText: "Welcome to Remotion"처럼 글자가 코드 안에 직접 박혀 있었습니다. 이 상태에서 다른 대사로 영상을 만들려면 매번 코드 파일을 열어서 글자를 고쳐야 합니다. 코드로 하나씩 만들 때에는 상관없지만, "대본만 넣으면 자동으로 mp4가 나오게 하고 싶다"는 목표에는 맞지 않습니다. 해결책은 간단합니다 — 글자를 코드에 직접 쓰는 대신, 별도 파일(JSON)에 적어놓고 코드는 그 파일을 "읽어서 채우는" 역할만 하게 만들면 됩니다.
실습 1 — 코드는 그대로 두고 값만 바꿔보기
터미널에서 아래 명령을 실행해보세요.
cat > props.json << 'EOF'
{
"titleText": "정데비의 작업실",
"titleColor": "#FF3366",
"logoColor1": "#FFD700",
"logoColor2": "#FF6B6B"
}
EOF
npx remotion render HelloWorld --props=props.json out/test-with-data.mp4
cat > 파일명 << 'EOF' ... EOF는 터미널에서 여러 줄짜리 텍스트를 한 번에 파일로 저장하는 방법입니다. 첫 줄과 마지막 EOF 사이에 있는 내용이 그대로 props.json 파일이 됩니다. --props=props.json 옵션은 "이 파일에 적힌 값으로 렌더링해라"는 뜻입니다. 실행해보면 코드는 한 글자도 안 건드렸는데 제목과 색상이 완전히 바뀐 영상이 나옵니다. 이게 이 시리즈에서 가장 중요한 메커니즘입니다.
장면(씬) 단위로 영상 설계하기
Shorts 영상은 보통 여러 장면이 이어집니다. "장면 1에서는 이 대사와 이 이미지, 장면 2에서는 저 대사와 저 이미지"처럼요. 이제 이런 "씬"(scene)을 그리는 설계를 3개 파일로 나누어 만들어보겠습니다.
schema.ts — 데이터가 어떤 모양이어야 하는지 정해두기
src/schema.ts 파일을 새로 만듭니다.
import { z } from "zod";
export const captionWordSchema = z.object({
word: z.string(),
startFrame: z.number(),
endFrame: z.number(),
});
export const sceneSchema = z.object({
audioPath: z.string(),
imagePath: z.string(),
durationInFrames: z.number(),
captionWords: z.array(captionWordSchema),
});
export const sceneVideoSchema = z.object({
scenes: z.array(sceneSchema),
});
zod는 "이 데이터는 반드시 이런 모양이어야 한다"를 미리 적어두는 도구입니다. 예를 들어 sceneSchema는 "씬 하나는 오디오 경로, 이미지 경로, 길이(프레임), 자막 단어들로 4가지가 있어야 한다"라고 정의한 것입니다. 잘못된 데이터가 들어오면 미리 에러로 알려주니, 데이터를 자동으로 생성하는 다음 편부터는 이 실수를 미리 잡아낼 수 있어서 유용합니다.
Scene.tsx — 씬 하나를 그리는 부품
src/Scene.tsx 파일을 새로 만듭니다.
import { AbsoluteFill, Audio, Img, staticFile, useCurrentFrame } from "remotion";
import { z } from "zod";
import { sceneSchema } from "./schema";
export const Scene: React.FC<z.infer<typeof sceneSchema>> = ({
audioPath,
imagePath,
captionWords,
}) => {
const frame = useCurrentFrame();
const activeWord = captionWords.find(
(w) => frame >= w.startFrame && frame <= w.endFrame
);
return (
<AbsoluteFill>
<Img
src={staticFile(imagePath)}
style={{ width: "100%", height: "100%", objectFit: "cover" }}
/>
<Audio src={staticFile(audioPath)} />
<AbsoluteFill
style={{ justifyContent: "flex-end", alignItems: "center", paddingBottom: 120 }}
>
<div
style={{
fontSize: 60,
fontWeight: "bold",
color: "white",
textShadow: "0 4px 12px rgba(0,0,0,0.8)",
}}
>
{activeWord ? activeWord.word : ""}
</div>
</AbsoluteFill>
</AbsoluteFill>
);
};
핵심은 activeWord를 찾는 줄입니다. "지금 프레임이 이 단어의 시작과 끝 사이에 있는가?"를 계속 확인해서, 맞는 단어를 화면 아래 자막으로 보여줍니다. 이게 누적되면 대사가 나올 때마다 그에 맞는 자막이 단어 단위로 자동 전환되는 효과가 나옵니다.
SceneVideo.tsx — 씬들을 순서대로 배치
src/SceneVideo.tsx 파일을 새로 만듭니다.
import { Series } from "remotion";
import { z } from "zod";
import { Scene } from "./Scene";
import { sceneVideoSchema } from "./schema";
export const SceneVideo: React.FC<z.infer<typeof sceneVideoSchema>> = ({ scenes }) => {
return (
<Series>
{scenes.map((scene, i) => (
<Series.Sequence key={i} durationInFrames={scene.durationInFrames}>
<Scene {...scene} />
</Series.Sequence>
))}
</Series>
);
};
Series는 "장면들을 순서대로 이어붙여라"는 뜻입니다. 씬이 몇 개든 scenes 배열을 순서대로 돌리면서 이어붙여줍니다.
Root.tsx에 새 Composition 등록하기
기존 <Composition>들 아래에 이것을 추가합니다.
import { SceneVideo } from "./SceneVideo";
import { sceneVideoSchema } from "./schema";
<Composition
id="SceneVideo"
component={SceneVideo}
fps={30}
width={1080}
height={1920}
schema={sceneVideoSchema}
defaultProps={{ scenes: [] }}
durationInFrames={150}
calculateMetadata={async ({ props }) => {
const totalDuration = props.scenes.reduce(
(sum, scene) => sum + scene.durationInFrames,
0
);
return { durationInFrames: totalDuration || 1 };
}}
/>
calculateMetadata는 "씬이 몇 개든 그 길이를 다 더해서 전체 영상 길이를 자동으로 계산해라"는 뜻입니다. 이 덕분에 씬이 2개이든 10개이든 JSON만 바꾸면 전체 영상 길이도 자동으로 맞춰집니다.
테스트 데이터로 검증하기
실제 씬 2개짜리 데이터를 만들어 렌더링해보겠습니다.
cat > scene-props.json << 'EOF'
{
"scenes": [
{
"audioPath": "test.wav",
"imagePath": "test.png",
"durationInFrames": 90,
"captionWords": [
{ "word": "안녕하세요", "startFrame": 0, "endFrame": 30 },
{ "word": "테스트입니다", "startFrame": 31, "endFrame": 89 }
]
},
{
"audioPath": "test.wav",
"imagePath": "test.png",
"durationInFrames": 60,
"captionWords": [
{ "word": "두번째 씬", "startFrame": 0, "endFrame": 59 }
]
}
]
}
EOF
npx remotion render SceneVideo --props=scene-props.json out/scene-test.mp4
이렇게 만들면 첫 씬(90프레임) 다음에 두 번째 씬(60프레임)이 이어붙어 총 150프레임짜리 영상이 나옵니다. 영상 정보를 확인하는 ffprobe라는 도구로 실제 프레임 수를 세어보면 정확히 150이 나옵니다 — 씬 경계를 넘나들며 자막이 바뀌는 지점도 정확하게 맞았습니다.
주의사항 / 흔한 실수
- JSON 파일은 쉼표 하나, 따옴표 하나만 빠져도 전체가 깨집니다. 에러가 나면 제일 먼저 쉼표/중괄호를 의심해보세요.
- startFrame/endFrame은 초(시간)가 아니라 fps 기준 프레임 값입니다. fps=30이면 1초 = 30프레임입니다.
- durationInFrames를 씬마다 다르게 주면, 자막 길이보다 씬이 짧게 끝나서 말이 잘릴 수 있으니 오디오 길이보다 약간 여유있게(예: +10~15프레임) 잡는 걸 추천합니다.
마무리
이번 편에서는 코드를 건드리지 않고 JSON 데이터만 바꿔 영상 내용을 바꾸는 구조를 만들었습니다. 씬 단위로 설계(schema.ts, Scene.tsx, SceneVideo.tsx)하고, 이미지·오디오·자막이 함께 들어있는 테스트 데이터로 실제 렌더링까지 확인했습니다. 지금은 captionWords를 사람이 직접 손으로 적었지만, 다음 편에서는 한국어 음성을 자동으로 만들면서 이 값들까지 자동으로 뽑아내는 방법을 다룹니다.
한국어 AI 목소리 무료로 쓰기: edge-tts 연동하기 (Shorts 자동화 4편)
도입3편까지는 captionWords(자막이 무슨 단어이고 몇 프레임에 나오는지)를 사람이 직접 손으로 적었습니다. 대본만 바꾸면 영상이 바뀐다: Remotion 데이터 주입 구조 만들기 (Shorts 자동화 3편)도입2
blog.jdevy.com
[핵심요약] JSON 데이터로 씬(장면) 단위 Remotion 영상 설계하기
'실전 자동화 튜토리얼' 카테고리의 다른 글
| AI 이미지까지 연결해서 첫 자동 영상 완성하기 (Shorts 자동화 5편) (0) | 2026.07.18 |
|---|---|
| 한국어 AI 목소리 무료로 쓰기: edge-tts 연동하기 (Shorts 자동화 4편) (0) | 2026.07.18 |
| 코딩 몰라도 따라하는 Remotion 첫걸음 (Shorts 자동화 2편) (0) | 2026.07.18 |
| Shorts 자동화 툴을 Vrew에서 Remotion으로 바꾸면서 생긴 일들 (0) | 2026.07.18 |
| 돈 한푼 안 쓰고 백엔드 만들기: Cloudflare+Supabase 실전 구조 (0) | 2026.07.17 |