faster-whisper를 이용하여 자막 생성하기

앞서 소개한 faster-whisper-large-v3 음성인식 라이브러리를 이용하여 자동으로 일본어나 영어자막을 생성하는 샘플 스크립트를 작성해 본다. 직접 제작한 동영상이나 영어 또는 일본어 등 외국 영화에 대한 자막파일을 자동으로 생성하여 동영상 재생 중에 음성부분에 대한 자막을 영상에 오버레이하여 보여줄 수 있다.

샘플 스크립트의 구조 및 코드

샘플 스크립트를 구동하게 위해서는 구동 하려는 PC에 Python 3.8 이상과 ffmpeg 라이브러리가 설치되어 있어야 한다.
Claude Cowork를 이용해 작성한 샘플 스크립트의 작동순서는 아래와 같으며, 테스트를 위해서는 Youtube에서 추출한 일본어 비디오 클립을 이용하였다.

  1. faster-whisper가 설치되어 있지 않은 경우에는 자동으로 설치를 진행한다.
  2. 16Hz 모노로 영상에서 오디오를 추출하여 /tmp 폴더에 저장한다.
  3. faster-whisper-large-v3 모델을 이용하여 일본어를 자동으로 추출한다.
  4. 영상파일이 위치한 폴더에 srt 확장자로 자막을 저장한다.
#!/bin/bash
# sample_video 일본어 자막 생성 스크립트
# 실행 방법: bash generate_subtitle.sh
# 필요 환경: Python 3.8+, ffmpeg
 
set -e
 
VIDEO="/movie/sample_video.mp4"
OUTPUT_DIR="/movie/"
AUDIO_TMP="/tmp/sample_video_audio.wav"
OUTPUT_SRT="${OUTPUT_DIR}/sample_video.srt"
 
echo "========================================"
echo " sample_video 일본어 자막 생성기"
echo "========================================"
echo ""
 
# ffmpeg 확인
if ! command -v ffmpeg &> /dev/null; then
    echo "[오류] ffmpeg가 설치되어 있지 않습니다."
    echo "설치: brew install ffmpeg"
    exit 1
fi
 
# Python / faster-whisper 설치 확인
echo "[1/4] faster-whisper 설치 확인..."
if ! python3 -c "import faster_whisper" &> /dev/null; then
    echo "  → faster-whisper 설치 중..."
    pip3 install faster-whisper -q
fi
echo "  → OK"
 
# 오디오 추출
echo ""
echo "[2/4] 오디오 추출 중 (16kHz 모노 WAV)..."
ffmpeg -i "${VIDEO}" -vn -ac 1 -ar 16000 -acodec pcm_s16le "${AUDIO_TMP}" -y 2>/dev/null
echo "  → 추출 완료: ${AUDIO_TMP}"
 
# Whisper 전사
echo ""
echo "[3/4] Whisper large-v3 일본어 전사 중..."
echo "  (Apple Silicon: ~5분, Intel Mac: ~15분 소요 예상)"
echo ""
 
python3 << 'PYEOF'
import sys
from faster_whisper import WhisperModel
 
AUDIO = "/tmp/sample_video_audio.wav"
OUTPUT = None  # 아래에서 덮어씀
 
import os
OUTPUT = "/movie/sample_video.srt"
 
# Apple Silicon이면 mlx 또는 coreml 사용 가능하나 기본은 CPU/int8
import platform
device = "cpu"
compute = "int8"
 
print(f"  모델 로딩: large-v3 ({device}, {compute})")
model = WhisperModel("large-v3", device=device, compute_type=compute)
 
print("  전사 시작...")
segments, info = model.transcribe(
    AUDIO,
    language="ja",
    beam_size=5,
    vad_filter=True,
    vad_parameters=dict(min_silence_duration_ms=500),
    word_timestamps=False
)
 
print(f"  감지 언어: {info.language} (확률: {info.language_probability:.0%})")
 
def fmt_time(s):
    h = int(s // 3600)
    m = int((s % 3600) // 60)
    sec = int(s % 60)
    ms = int((s - int(s)) * 1000)
    return f"{h:02d}:{m:02d}:{sec:02d},{ms:03d}"
 
srt_blocks = []
count = 0
for seg in segments:
    count += 1
    text = seg.text.strip()
    if not text:
        continue
    block = f"{count}\n{fmt_time(seg.start)} --> {fmt_time(seg.end)}\n{text}\n"
    srt_blocks.append(block)
    if count % 200 == 0:
        print(f"  {count}개 처리 중... ({fmt_time(seg.end)})")
 
srt_content = "\n".join(srt_blocks)
with open(OUTPUT, "w", encoding="utf-8") as f:
    f.write(srt_content)
 
print(f"\n  완료! 총 {count}개 자막 라인")
print(f"  저장 위치: {OUTPUT}")
PYEOF
 
# 임시 파일 삭제
echo ""
echo "[4/4] 임시 파일 정리..."
rm -f "${AUDIO_TMP}"
echo "  → 완료"
 
echo ""
echo "========================================"
echo " 자막 생성 완료!"
echo " 파일: sample_video.srt"
echo " 위치: ${OUTPUT_DIR}"
echo "========================================"
echo ""
echo "영상 플레이어(VLC, IINA 등)에서 자막 파일을 불러오시면 됩니다."

샘플 스크립트의 실행

Visual Studio Code 등의 편집기로 위의 스크립트를 작성한 후, 적당한 디렉토리에 “generate_subtitle.sh”라는 이름으로 저장한 후에 아래와 같은 명령어로 간단히 실행해 주면 된다. 결과물은 “sample_video.mp4″가 위치한 동일한 폴더에 “sample_video.srt”로 생성될 것이다.

bash ~/movie/generate_subtitle.sh

마무리하며

완성된 srt 파일은 VLC, IINA 등 대부분의 동영상 플레이어에서 문제없이 동작하였고, 사람이 직접 번역한 자막 이상의 완벽한 수준을 보여주는 듯 하다. 더 놀란 부분은 Whisper가 일본어로 설정되어 있기 때문인지 일본에서 일반적으로 사용되는 한자, 히라가나의 혼용자막이 전혀 어색하지 않다는 부분이다. 영어 뿐만이 아닌 여러 나라 언어의 음성인식과 문자출력에 대한 AI 능력에 다시 한번 놀라게 되는 경험이었던 것 같다.