AI 개발 가이드

AI로 유튜브 쇼츠 자동 생성 파이프라인 - 스크립트+음성+자막 전자동

소개왕 탑백귀 2026. 4. 22. 17:32

AI로 유튜브 쇼츠 자동 생성 파이프라인 - 스크립트+음성+자막 전자동

2026년 4월 기준 | AI 개발 가이드

요약: 주제 한 줄만 입력하면 LLM이 스크립트를 쓰고, TTS가 음성을 만들고, Whisper가 자막을 붙이고, moviepy가 영상으로 합치는 쇼츠 자동 생성 파이프라인을 실제 코드로 구축합니다. 9:16 세로 영상, 인트로/본문/아웃트로 구조, 키워드 강조 자막까지 한 번에 만드는 스크립트를 공유합니다.

왜 쇼츠 자동화를 해볼 가치가 있는가

짧은 영상 콘텐츠는 여전히 노출 우선 알고리즘의 핵심입니다. 주 3~5편 꾸준히 올리는 게 가장 효율적이라는 건 다들 알지만, 매번 스크립트 쓰고 녹음하고 자막 붙이는 일이 시간을 잡아먹습니다. 본업이 있는 사람이 부업으로 하기엔 한계가 명확하죠.

2026년 기준 LLM + TTS + Whisper + moviepy 조합이면 주제 한 줄에서 9:16 쇼츠 한 편이 나옵니다. 건당 수십 원~수백 원 수준. 품질은 여전히 사람 손이 닿은 콘텐츠만큼은 아니지만, 초안 자동 생성 + 최종 편집 정도의 하이브리드 워크플로우에는 쓸만합니다.

전체 파이프라인 구조

이번에 만들 시스템의 흐름입니다.

[주제 한 줄]
   ↓ (1) Claude/GPT API
[60초용 스크립트 + 자막 단위 분리]
   ↓ (2) OpenAI TTS / ElevenLabs
[mp3 음성 파일]
   ↓ (3) Whisper (word-level timestamps)
[.srt 자막 파일]
   ↓ (4) moviepy
[9:16 mp4 쇼츠 영상]

각 단계는 독립된 함수로 분리하면 테스트도 쉽고, 한 단계에서 문제가 생겨도 중단 지점부터 재실행할 수 있습니다.

환경 설정

pip install anthropic openai-whisper moviepy pillow python-dotenv

# ffmpeg 별도 설치 필수 (moviepy/whisper 의존성)
# Windows: choco install ffmpeg
# macOS:   brew install ffmpeg
# Ubuntu:  sudo apt install ffmpeg

# .env 파일
# ANTHROPIC_API_KEY=sk-ant-xxxxx
# OPENAI_API_KEY=sk-xxxxx

1단계: AI로 스크립트 생성

쇼츠는 첫 3초에서 이탈이 결정되므로 훅 문장이 중요합니다. LLM에 이 구조를 명시적으로 지시하는 게 핵심입니다.

import os, json, anthropic
from dotenv import load_dotenv
load_dotenv()

client = anthropic.Anthropic()

SYSTEM_PROMPT = """너는 유튜브 쇼츠 전문 작가야. 60초 이내 스크립트를 만들어.
구조: [훅 3초] → [본문 3~4포인트] → [클로징 3초]
스타일: 반말, 구어체, 문장 15자 이내.
JSON으로만 답해. 키: hook, points(배열), closing"""

def generate_script(topic: str) -> dict:
    msg = client.messages.create(
        model="claude-sonnet-4-6",
        max_tokens=800,
        system=SYSTEM_PROMPT,
        messages=[{"role": "user", "content": f"주제: {topic}"}],
    )
    raw = msg.content[0].text.strip()
    # 코드 펜스 제거
    if raw.startswith("```"):
        raw = raw.split("```")[1].lstrip("json").strip()
    return json.loads(raw)

script = generate_script("겨울철 전기요금 10만원 아끼는 법")
full_text = script["hook"] + " " + " ".join(script["points"]) + " " + script["closing"]
print(full_text)

시스템 프롬프트에서 "문장 15자 이내"를 강제하는 이유는 쇼츠 자막이 너무 길면 화면에 안 들어가기 때문입니다. JSON 출력은 이후 단계에서 섹션별 타임라인을 나눌 때 유용합니다.

2단계: TTS 음성 합성

OpenAI TTS가 가성비가 가장 좋고, 감정 표현이 중요하면 ElevenLabs가 낫습니다. 여기서는 OpenAI로 진행합니다.

from openai import OpenAI
from pathlib import Path

oai = OpenAI()

def synthesize_tts(text: str, out_path: str = "voice.mp3",
                   voice: str = "nova", speed: float = 1.1) -> str:
    resp = oai.audio.speech.create(
        model="tts-1-hd",
        voice=voice,
        input=text,
        speed=speed,
    )
    resp.stream_to_file(out_path)
    return out_path

synthesize_tts(full_text, "voice.mp3")

speed를 1.05~1.15로 살짝 빠르게 하는 게 쇼츠 감성에 잘 맞습니다. voice는 nova/alloy/shimmer가 한국어에서도 어색함이 적습니다. 완전히 네이티브한 느낌을 원하면 ElevenLabs의 한국어 음성을 권장합니다.

3단계: Whisper로 타임스탬프 자막

Whisper의 word-level 타임스탬프를 받아 자막(.srt)으로 변환합니다. 직접 문장을 끊기보다 실제 음성 기반으로 끊는 게 훨씬 자연스럽습니다.

import whisper

model = whisper.load_model("small")  # 한국어는 small 이상 권장

def make_captions(audio_path: str, out_srt: str = "captions.srt"):
    result = model.transcribe(
        audio_path, language="ko",
        word_timestamps=True, verbose=False,
    )
    lines = []
    idx = 1
    for seg in result["segments"]:
        words = seg.get("words", [])
        # 5~6단어씩 묶어 한 자막 줄로 만든다
        buf, start = [], None
        for w in words:
            if start is None:
                start = w["start"]
            buf.append(w["word"])
            if len(buf) >= 5:
                end = w["end"]
                lines.append((idx, start, end, "".join(buf).strip()))
                idx += 1
                buf, start = [], None
        if buf:
            lines.append((idx, start, words[-1]["end"], "".join(buf).strip()))
            idx += 1

    def fmt(t):
        h = int(t//3600); m = int((t%3600)//60); s = t%60
        return f"{h:02d}:{m:02d}:{s:06.3f}".replace(".", ",")

    with open(out_srt, "w", encoding="utf-8") as f:
        for i, st, ed, text in lines:
            f.write(f"{i}\n{fmt(st)} --> {fmt(ed)}\n{text}\n\n")
    return out_srt

make_captions("voice.mp3", "captions.srt")

한 자막 줄당 5단어 정도면 세로 화면에서 1~2줄로 예쁘게 들어갑니다. 더 짧게 하고 싶으면 3~4단어로 줄이면 됩니다.

4단계: moviepy로 영상 조립

9:16 배경 + 음성 + 자막을 한 번에 조립합니다. 배경은 단색이나 스톡 영상 루프를 쓰면 됩니다.

from moviepy.editor import (
    AudioFileClip, ColorClip, CompositeVideoClip, TextClip,
)
import re

W, H = 1080, 1920  # 세로 쇼츠 해상도

def parse_srt(path: str):
    entries = []
    for block in open(path, encoding="utf-8").read().strip().split("\n\n"):
        lines = block.splitlines()
        if len(lines) < 3:
            continue
        m = re.match(r"(\d+:\d+:\d+,\d+) --> (\d+:\d+:\d+,\d+)", lines[1])
        def to_sec(t):
            h, m2, s = t.replace(",", ".").split(":")
            return int(h)*3600 + int(m2)*60 + float(s)
        entries.append((to_sec(m.group(1)), to_sec(m.group(2)), " ".join(lines[2:])))
    return entries

def assemble_video(audio_path, srt_path, out_path="short.mp4"):
    audio = AudioFileClip(audio_path)
    duration = audio.duration

    bg = ColorClip(size=(W, H), color=(20, 22, 35), duration=duration)

    caption_clips = []
    for start, end, text in parse_srt(srt_path):
        tc = (TextClip(text, fontsize=78, color="white",
                       stroke_color="black", stroke_width=4,
                       font="NanumGothic-Bold", method="caption", size=(W-140, None))
              .set_position(("center", H*0.72))
              .set_start(start).set_end(end))
        caption_clips.append(tc)

    video = CompositeVideoClip([bg, *caption_clips]).set_audio(audio).set_duration(duration)
    video.write_videofile(out_path, fps=30, codec="libx264", audio_codec="aac")

assemble_video("voice.mp3", "captions.srt", "short.mp4")

한글이 깨진다면 font 매개변수에 시스템에 설치된 한글 폰트(예: "NanumGothic-Bold", "Malgun Gothic")를 정확히 지정해야 합니다. Windows에서는 ImageMagick 경로 설정이 필요할 수 있습니다.

배경을 스톡 비디오로 바꾸고 싶다면 VideoFileClip("stock.mp4").loop(duration=duration).resize((W,H))로 대체하면 됩니다. Pexels, Pixabay에서 무료 세로 영상을 얻을 수 있습니다.

건당 비용 & 주의사항

영상 1편 생성 시 예상 비용(환율 1,350원 기준)입니다.

  • 스크립트 생성 (Claude Sonnet): 약 30~100원
  • TTS (OpenAI tts-1-hd, 60초): 약 50~80원
  • Whisper (로컬 실행): 전기료만
  • moviepy (로컬 실행): 전기료만
  • 총합: 영상 1편당 100~200원대

자동 업로드까지 하고 싶다면 YouTube Data API v3를 쓰면 됩니다. 다만 AI로 만든 콘텐츠는 유튜브 가이드라인상 '변형된 콘텐츠'로 취급될 수 있어 설명란에 명시하고 최소한의 편집을 추가하는 게 안전합니다. 동일 템플릿 영상을 대량 업로드하면 스팸으로 간주될 위험도 있으니, 하루 2~3편 수준으로 제한하고 매번 스크립트 스타일을 조금씩 바꾸는 게 좋습니다.

마무리

이번 파이프라인은 "자동 완성 AI 콘텐츠 공장"이 아니라 "초안을 빠르게 만들고 최종 편집만 사람이 하는 하이브리드 도구"로 생각하는 게 현실적입니다. 실제로 써 보면 타이밍, 강조, 표정 요소가 필요한 부분은 여전히 사람이 개입해야 합니다.

확장 아이디어로는 ①주제 큐레이션 자동화(구글 트렌드 크롤러), ②배경 이미지 자동 생성(DALL-E 3/Stable Diffusion), ③썸네일 자동 생성, ④자막 단어 단위 하이라이트 등을 붙여볼 수 있습니다. 전체 코드를 하나의 CLI로 묶어 두면 하루에 여러 편을 찍어낼 수 있는 개인용 스튜디오가 됩니다.