클라우드 한 줄 없이, Mac Mini에서 영상을 폴더에 던지면 자막 붙은 완성본이 알아서 쌓이는 구조를 만들었다. ffmpeg으로 음성을 뽑고, Whisper로 자막을 생성하고, fswatch로 폴더를 감시하는 세 도구의 조합이 전부다. 영상 콘텐츠를 반복 생산하는 사람이라면 이 파이프라인을 한 번 심어두면 영상 후처리에 쓰던 시간이 실질적으로 0분이 된다.
왜 ffmpeg + Whisper 조합인가
유튜브 자동 자막의 한국어 정확도는 기술 용어가 나올수록 뚝뚝 떨어진다. 직접 테스트해보니 "컨테이너 오케스트레이션"을 "컨테이너 오케 스트레이" 식으로 쪼개거나, 영어 약어를 엉뚱한 한글로 변환하는 경우가 빈번했다.
Whisper large-v3은 달랐다. Mac Mini M2 Pro에서 10분짜리 기술 강의 영상을 돌렸을 때 48초 만에 SRT가 나왔고, 전문 용어 오탈자는 거의 없었다.
두 도구의 역할 분담은 단순하다.
- ffmpeg: 영상에서 음성만 추출. 비디오 스트림은 버리고 16kHz 모노 WAV만 뽑는다.
- Whisper: 그 WAV를 받아 타임스탬프가 붙은 SRT로 변환한다.
각자로는 반쪽짜리지만, 붙이면 클라우드 API 없이도 상용 수준의 자막 파이프라인이 완성된다.
파이프라인 핵심 명령어 세 줄
실제로 돌아가는 명령어 블록이다. 세 단계가 &&로 묶여 순서대로 실행된다.
# 1단계: 영상에서 16kHz 모노 WAV 추출
ffmpeg -i input.mp4 -vn -ar 16000 -ac 1 audio.wav
# 2단계: Whisper로 한국어 자막 생성
whisper audio.wav --model large-v3 --language ko --output_format srt
# 3단계: 원본 영상에 자막 스트림 병합
ffmpeg -i input.mp4 -vf subtitles=audio.srt output_sub.mp4
플래그 하나씩 짚어두면:
| 플래그 | 의미 |
|---|---|
-vn |
비디오 스트림 무시 (음성만 추출) |
-ar 16000 |
샘플레이트 16kHz — Whisper 권장값 |
-ac 1 |
모노 채널 — 스테레오보다 처리 속도 빠름 |
--language ko |
한국어 강제 지정 — 생략하면 자동 감지로 정확도 낮아짐 |
--output_format srt |
타임스탬프 포함 SRT 직접 출력 |
M2 Pro 기준 실측: 10분 영상 전체 처리 52초.
Whisper 모델 선택 — 실측 비교
속도만 보면 tiny가 압도적이다. 하지만 한국어 기술 문서에서는 틀리는 빈도가 너무 높다. 직접 같은 영상으로 세 모델을 돌려봤다.
| 모델 | 처리 시간 (10분 영상, M2 Pro) | 한국어 기술 용어 정확도 |
|---|---|---|
| tiny | 11초 | 낮음 — 전문 용어 다수 오변환 |
| base | 19초 | 보통 — 일반 대화는 무난, 용어 오류 多 |
| large-v3 | 48초 | 높음 — 기술 문서 기준 최고 |
30분 영상으로 넘어가면 large-v3도 2분 20초면 끝난다. 속도와 정확도 교환에서 기술 콘텐츠라면 large-v3 외에 선택지가 없다.
단어 단위 타임스탬프가 필요할 때는 --word_timestamps True 플래그를 추가한다. 자막 싱크를 더 정밀하게 잡을 때 유용하다.
whisper audio.wav --model large-v3 --language ko --word_timestamps True
진짜 자동화 — 폴더 감시 데몬
명령어를 수동으로 실행하는 건 반자동화다. 폴더에 파일이 들어오는 순간 파이프라인이 스스로 켜지는 구조가 되어야 한다.
macOS에서는 fswatch가 그 역할을 한다. 입력 폴더를 실시간으로 감시하다가 새 파일이 감지되면 처리 스크립트를 즉시 호출한다.
# 폴더 감시 → 자동 처리 (nohup으로 백그라운드 실행)
nohup fswatch -o ~/Videos/input/ \
| xargs -n1 -I{} bash ~/scripts/auto_subtitle.sh &
auto_subtitle.sh 안에는 앞서 작성한 세 단계 파이프라인이 들어간다. 파일 이름을 인자로 받아 처리 후 완성본을 ~/Videos/output/에 저장하는 구조다.
#!/bin/bash
INPUT=$1
BASENAME=$(basename "$INPUT" .mp4)
ffmpeg -i "$INPUT" -vn -ar 16000 -ac 1 "/tmp/${BASENAME}.wav" && \
whisper "/tmp/${BASENAME}.wav" \
--model large-v3 --language ko --output_format srt \
--output_dir /tmp/ && \
ffmpeg -i "$INPUT" \
-vf subtitles="/tmp/${BASENAME}.srt" \
~/Videos/output/"${BASENAME}_sub.mp4"
이 구조를 붙인 뒤 영상 후처리에 쓰던 시간이 실질적으로 0이 됐다. Mac Mini가 켜져 있는 한 단 한 번의 수동 개입도 필요 없다.
운영 팁과 주의할 함정
한국어 강제 지정은 필수다. --language ko를 생략하면 Whisper가 첫 30초를 듣고 언어를 자동 감지하는데, 영어가 섞인 기술 강의에서 영어로 판단해버리는 경우가 있다. 처음부터 언어를 고정하는 게 안전하다.
WAV 임시 파일 정리. /tmp/에 WAV와 SRT가 쌓인다. 스크립트 마지막에 rm /tmp/${BASENAME}.* 한 줄을 넣어 디스크가 차는 걸 막는다.
Linux에서는 fswatch 대신 inotifywait. macOS 전용 도구라 Ubuntu 환경에서는 inotify-tools를 설치하고 inotifywait -m -e close_write ~/Videos/input/ 로 대체한다.
Docker에서 돌릴 때. Whisper 모델 캐시 경로를 볼륨으로 마운트해두지 않으면 컨테이너가 뜰 때마다 large-v3 (약 3GB)를 다시 내려받는다. ~/.cache/whisper를 호스트 경로로 바인드한다.
마무리
ffmpeg으로 뽑고, Whisper로 읽히고, fswatch로 감시한다. 세 도구가 조용히 맞물리면 영상을 폴더에 던지는 것 외에 할 일이 없다. M2 Pro에서 10분 영상 52초, 30분 영상 2분 20초. 클라우드 API 비용도 없고 인터넷도 필요 없다.
다음 글에서는 이 파이프라인에 n8n 웹훅을 붙여서 완성된 자막 파일을 Notion 데이터베이스에 자동으로 기록하는 구조를 다룬다.
🐦 X에서 더 빠르게: @baegseungh7061
📚 이 시리즈 더 보기: AI 인사이트
💌 새 글 알림: X 팔로우 또는 블로그 RSS 구독
'AI 인사이트' 카테고리의 다른 글
| GitHub Actions + Claude로 PR 리뷰부터 커밋 메시지까지 자동화하기 (0) | 2026.05.10 |
|---|---|
| Mac Mini 4대로 영상 인코딩 클러스터 직접 구축하기 — Tailscale + ffmpeg 분산 파이프라인 실전기 (0) | 2026.05.08 |
| Superpowers — 코딩 에이전트가 스스로 설계·계획·TDD를 수행하는 완전 자동 개발 방법론 (0) | 2026.05.07 |
| everything-claude-code — 10개월 에이전트 노하우를 Claude Code에 이식하는 법 (0) | 2026.05.07 |
| ffmpeg + Tailscale로 Mac Mini 클러스터 영상 파이프라인 직접 구축하기 (0) | 2026.05.06 |