DAY 2 · 15교시 · 60분

영상 합성: moviepy로 이미지+음성 조립

📚1단계: 주요 개념 설명

이번 단원의 목표

파이썬 moviepy로 이미지와 음성 파일을 동기화 결합해 MP4로 렌더링하고, '영상 생성(13교시)'과 '영상 합성(조립)'의 차이를 구분한다.

🗂️강의 슬라이드
슬라이드 1 / 10

영상 합성 개론 — 생성이 아니라 '조립'

합성 개론 — 생성이 아니라 '조립'생성(13교시)모델이 픽셀 생성무거움합성(moviepy)있는 소스 배치가볍고 안정
  • 13교시는 모델이 움직임을 '생성'했다면, 여기서는 이미 있는 이미지·소리를 '조립'합니다(편집).
  • 모든 소스(대본, Qwen 0.6B TTS 오디오, FLUX 이미지 카드) 준비 후 최종 미디어 결합을 실시합니다.
  • 파이썬 moviepy 모듈과 미디어 전용 FFmpeg 엔진으로 단일 비디오 인코딩을 지휘합니다.

🛠️2단계: 따라하기 실습

🛠 따라 만들기 · AI 바이브 코딩
moviepy로 최종 영상 합성하기

만든 이미지와 음성을 시간 순서대로 합쳐 하나의 MP4 영상으로 렌더링합니다. Day 1~2의 모든 조각이 여기서 한 편의 영상이 됩니다.

🎯 완성 결과: 이미지+음성을 합쳐 final_shorts.mp4를 만들어 주는 함수와 API
1영상 패키지 설치

코드로 영상 편집을 자동화할 도구를 준비합니다.

▶ 터미널에서 실행
pip install moviepy
💡 핵심 코드 설명
  • moviepy는 내부적으로 FFmpeg를 사용해 이미지·음성을 영상으로 합칩니다.
  • 처음 실행 시 FFmpeg가 없으면 설치가 필요할 수 있습니다.
2합성 함수 만들기 (타이밍 동기화)

이미지 노출 시간을 음성 길이에 맞춰 합칩니다.

🤖 AI에게 이렇게 시켜보세요

파이썬 moviepy로, 장면별 이미지(jpg)와 음성(wav)을 받아 각 이미지 노출 시간을 그 장면 음성 길이(audio.duration)에 맞추고, 장면들을 이어붙여 final_shorts.mp4로 저장하는 함수를 만들어줘. 코덱은 libx264.

💡 핵심 코드 설명
  • audio.duration을 읽어 이미지 클립 길이로 맞추면 소리와 화면이 어긋나지 않습니다.
  • libx264(H.264)로 저장해야 폰·SNS에서 바로 재생됩니다.
3서버에 영상 API 붙이기

화면의 '영상 만들기' 버튼이 부를 라우트를 만듭니다.

🤖 AI에게 이렇게 시켜보세요

main.py에 POST /api/render-video 라우트를 추가해서, 위 합성 함수를 호출하고 만들어진 mp4 파일을 반환하도록 해줘.

💡 핵심 코드 설명
  • 이제 화면에서 버튼을 누르면 서버가 영상을 만들어 되돌려줍니다.
  • 인코딩 중 CPU 사용량이 잠깐 치솟는 것은 정상입니다.
🎯 스스로 해볼 미션
0 / 2 완료
최종 영상 설정, 내가 바꿔보기

합성 설정을 조금 바꿔 최종 mp4가 어떻게 달라지는지 직접 확인합니다.

출발점(강사와 함께 만든 것): 강사와 함께 moviepy로 이미지+음성을 MP4로 합성했다.
✅ 완료 기준: 내가 바꾼 설정이 최종 mp4에 반영되면 성공.
실습 미션 체크리스트
1개념 직관

13교시의 '영상 생성(AI가 움직임을 만듦)'과 달리, 여기서는 이미 만든 정지 이미지와 음성을 시간축에 맞춰 '조립'합니다. 로컬에 흩어져 저장된 FLUX 이미지 카드와 Qwen 0.6B TTS WAV 음성을 타임라인 위로 정렬 병합해 단일 MP4로 인코딩합니다. 무거운 영상모델 없이도 쇼츠를 완성하는 가장 현실적인 방법입니다.

2실습 미션

우측 비디오 렌더 타임라인 스티처에서 장면 카드에 알맞은 이미지 트랙과 TTS 사운드 트랙을 올바른 순서대로 조립하고 비디오 렌더러를 가동해 합성해 보세요.

moviepy 비디오 결합 렌더링
from moviepy.editor import ImageClip, AudioFileClip, concatenate_videoclips

# 이미지와 오디오 클립을 한 덩어리로 묶어 결합
clips = [
    ImageClip("flux_scene_1.jpg").set_duration(AudioFileClip("scene_1.wav").duration)
    .set_audio(AudioFileClip("scene_1.wav"))
]
final = concatenate_videoclips(clips)
final.write_videofile("final_shorts.mp4", fps=24)

💡 코딩 중 막히나요? 모범 솔루션 코드

🧩3단계: 개념 검증 퀴즈

검증 챌린지 미션

디렉토리에 final_shorts.mp4 비디오 파일이 인코딩 출력되어 디스크에 완성 저장되는 과정을 점검합니다.

📝 객관식 개념 확인 (2문항)

Q1. moviepy에서 각 이미지의 화면 노출 시간을 무엇에 맞추나?

Q2. 스마트폰·브라우저에서 바로 재생되도록 쓰는 표준 비디오 코덱은?

🔬 인터랙티브 체험 (선택)— 개념을 직접 조작하며 확인해 보세요

장면별 이미지 트랙과 TTS 오디오 트랙을 시간축 순서대로 동기화 매칭하는 비디오 결합 렌더러를 시뮬레이션합니다.

SCENE 1
🎬 매칭완료
JPG + WAV
SCENE 2
🎬 매칭완료
JPG + WAV
SCENE 3
🎬 매칭완료
JPG + WAV
SCENE 4
❔ 트랙대기
미완료
다음 교시로 이동하기 (16교시: 로컬↔배포 연결: zrok 터널링 및 통합 시연) ➡️