LangGraph, Whisper, FFmpeg을 사용하여 AI 비디오 클리핑 파이프라인을 구축한 방법
요약
LangGraph, Whisper, FFmpeg을 활용하여 비디오 클리핑 과정을 자동화하는 AI 파이프라인 구축 방법을 소개합니다. 단일 스크립트의 한계를 극복하기 위해 워크플로우를 상태 기반의 노드로 분리하여 디버깅 효율과 에러 핸들링을 높였습니다.
핵심 포인트
- LangGraph를 통한 단계별 노드 격리 및 상태 관리
- Whisper를 이용한 단어 단위 타임스탬프 추출
- LLM 기반의 몰입도 높은 클립 구간 자동 선택
- 피사체 탐지를 통한 세로형 크롭 위치 결정
저는 제 콘텐츠를 클리핑(clipping)하는 일을 계속 피하고 있었습니다. 짧은 클립을 원하지 않아서가 아니었습니다. 원했습니다. 하지만 그 과정이 정말 고통스러웠습니다 — 긴 영상을 훑어보고, 좋은 순간을 찾고, 자르고, 세로형으로 크롭(crop)하고, 자막을 추가하고, 내보내기(export)를 합니다. 이 과정을 세 번 반복하면 두 시간이 훌쩍 지나가 버립니다. 그래서 저는 이 모든 과정을 자동으로 수행하는 도구를 만들었습니다. 내부적으로 어떻게 작동하는지 소개하겠습니다.
단순한 스크립트의 문제점
저의 첫 번째 본능은 단일 Python 스크립트를 만드는 것이었습니다 — Whisper를 호출하고, 전사(transcript)를 파싱하고, FFmpeg을 실행하는 것이죠. 끝입니다. 작동했습니다. 하지만 작동하지 않을 때가 문제였습니다. LLM이 잘못된 클립 선택을 반환하면, 전사(transcription)를 다시 실행해야 했습니다. FFmpeg이 이상한 비디오 형식에서 실패하면, 포커스 감지(focus detection) 결과를 잃어버렸습니다. 디버깅(debugging)은 매번 모든 것을 처음부터 다시 실행하는 것을 의미했습니다. 저는 각 단계가 격리될 필요가 있었습니다. 바로 그 지점에서 LangGraph가 등장했습니다.
왜 LangGraph인가
LangGraph를 사용하면 파이프라인을 각각 고유한 상태(state)를 가진 개별 노드(node)의 그래프로 모델링할 수 있습니다. 하나의 거대한 순차적 스크립트 대신, 워크플로우는 다음과 같이 구성됩니다: 전사(transcription) → 클립 선택(clip_selection) → 포커스 감지(focus_detection) → 렌더링(rendering)
각 노드는:
- 필요한 상태(state)만 수신합니다.
- 출력을 공유 상태(shared state)에 다시 기록합니다.
- 실패 시 독립적으로 재시도할 수 있습니다.
- 전체 그래프를 실행하지 않고도 격리된 상태에서 테스트할 수 있습니다.
마지막 포인트 하나만으로도 저는 디버깅 시간을 몇 시간이나 아낄 수 있었습니다. 클립 선택이 좋지 않은 순간을 반환할 때, Whisper나 FFmpeg을 건드리지 않고도 테스트용 전사(transcript)를 직접 입력할 수 있었습니다. 조건부 엣지(conditional edges)를 통해 에러 핸들링(error handling)도 깔끔하게 추가할 수 있었습니다 — 만약 포커스 감지가 실패하면, 전체 파이프라인을 중단시키는 대신 폴백(fallback) 센터 크롭(center-crop)으로 경로를 지정할 수 있습니다.
전체 파이프라인
노드 1 — 전사(Transcription)
비디오(또는 yt-dlp를 통한 YouTube URL)에서 오디오를 추출하고 로컬에서 OpenAI Whisper를 실행합니다. 출력값은 단어 단위 타임스탬프(word-level timestamps)가 포함된 전체 전사(transcript)입니다. 단어 단위 타임스탬프는 매우 중요한데, 이를 통해 선택된 텍스트 순간을 편집을 위한 정확한 비디오 타임코드(timecode)로 매핑할 수 있기 때문입니다.
노드 2 — 클립 선택(Clip Selection)
가장 몰입도 높은 3가지 순간을 식별하도록 요청하는 프롬프트와 함께 전사(transcript)를 LLM에 보냅니다.
모델은 각 선택된 구간에 대한 시작/종료 타임스탬프(timestamps)와 짧은 이유를 반환합니다. 프롬프트는 다음과 같은 순간을 명시적으로 요청합니다:
- 명확한 시작과 끝이 있는 순간
- 주변 맥락 없이도 의미가 통하는 순간
- 스크롤을 멈추게 할 만한 순간
Node 3 — 포커스 탐지 (Focus Detection)
선택된 각 클립에 대해 얼굴/피사체 탐지 (face/subject detection)를 실행하여 프레임 내의 주요 피사체가 어디에 있는지 찾습니다. 이는 9:16 세로형 출력을 위한 크롭(crop) 위치를 결정합니다. 단일 화자 콘텐츠의 경우 이 방식이 잘 작동합니다. 다수 인원이 포함된 구도는 여전히 개선 중인 부분입니다.
Node 4 — 렌더링 (Rendering)
FFmpeg은 다음 사항을 포함하여 각 클립을 렌더링합니다:
- 포커스 탐지 결과에 기반한 9:16 크롭
- 비디오에 삽입된 자동 생성 자막 (Auto-generated captions)
- TikTok / Reels / Shorts에 최적화된 출력
UI에서의 실시간 진행 상황 (Real-Time Progress in the UI)
LangGraph 아키텍처의 한 가지 좋은 부수 효과는 실시간 진행 상황 업데이트가 거의 공짜로 따라왔다는 점입니다. 상태(state)가 각 노드를 통과할 때 백엔드(backend)에서 이벤트를 방출합니다. 프론트엔드(frontend)는 이를 수신하여 진행 표시기를 업데이트합니다. 따라서 3분 동안 로딩 스피너(loading spinner)만 바라보는 대신, 파이프라인이 움직이는 것을 지켜볼 수 있습니다:
✓ 전사 (Transcription) 완료
✓ 클립 순간 식별 완료
✓ 포커스 탐지 완료
⏳ 클립 렌더링 중...
사용자들은 이 부분이 UX(사용자 경험) 측면에서 가장 안심이 되는 부분이라고 말했습니다. 무언가 실제로 진행되고 있다는 것을 아는 것만으로도 대기 시간이 더 짧게 느껴지기 때문입니다.
기술 스택 (Stack)
- 레이어 (Layer) | 기술 (Tech)
- 백엔드 (Backend) | FastAPI
- 프론트엔드 (Frontend) | Next.js 14
- 전사 (Transcription) | OpenAI Whisper
- 비디오 처리 (Video Processing) | FFmpeg
- 파이프라인 오케스트레이션 (Pipeline Orchestration) | LangGraph
- 저장 및 인증 (Storage & Auth) | Supabase
- YouTube 수집 (YouTube ingestion) | yt-dlp
잘 작동하는 것과 그렇지 않은 것
잘 작동하는 것: 대화 중심의 콘텐츠 — 팟캐스트, 인터뷰, 컨퍼런스 강연, 강의. 전사 데이터가 풍부하여 LLM이 진정으로 좋은 순간을 골라냅니다.
여전히 개선이 필요한 것: 말보다 영상이 이야기를 더 많이 전달하는 B-roll 중심의 비디오. 전사 데이터만으로는 어떤 순간이 시각적으로 매력적인지를 포착할 수 없습니다. 이것이 제가 다음에 해결하고 싶은 문제이며, 아마도 전사 데이터와 함께 프레임 단위의 시각적 분석 (frame-level visual analysis)을 병행하여 해결할 것 같습니다. 포커스 탐지를 위한 다수 인원 구도 잡기 또한 아직 미흡합니다. 단일 화자는 안정적입니다.
지금 바로 체험해 보세요. 가입 없이 무료로 이용 가능합니다: https://video-generator-six-coral.vercel.app/ 만약 LangGraph 아키텍처(architecture)나 파이프라인(pipeline)의 특정 부분에 대해 궁금한 점이 있다면 댓글로 질문해 주세요. 어떤 내용이든 더 자세히 설명해 드릴 준비가 되어 있습니다. 그리고 여러분의 콘텐츠로 직접 테스트해 보신다면, 클립 선택(clip selection)이 실제로 좋은 순간들을 잘 골라내는지 진심으로 알고 싶습니다.
AI 자동 생성 콘텐츠
본 콘텐츠는 Dev.to AI tag의 원문을 AI가 자동으로 요약·번역·분석한 것입니다. 원 저작권은 원저작자에게 있으며, 정확한 내용은 반드시 원문을 확인해 주세요.
원문 바로가기