갈루아의 반서재

728x90

Google Colab과 faster-whisper로 MP3에서 스크립트를 추출하는 방법을 단계별로 설명합니다. 모델 선택, VAD 설정, SRT/VTT/DOCX 내보내기까지 실무 팁을 담았습니다.

🎧 Whisper 기반 클라우드 전사(Colab)

이 노트북은 Google Colab에서 한국어 음성을 Whisper로 전사하여 TXT / SRT / VTT / CSV 형식으로 내보냅니다.

사용 방법

  1. 상단 메뉴에서 런타임 → 모두 실행을 누르세요.
  2. 중간에 파일 업로드 셀에서 MP3 파일을 선택합니다.
  3. 완료 후 하단 셀에서 결과 파일을 다운로드하거나 Google Drive에 저장하세요.

> 아래 노트북은 Whisper(faster-whisper)를 사용하며, GPU가 있으면 자동으로 감지하여 속도를 높입니다. 언어는 기본 ‘ko’로 설정되어 한국어 인식에 최적화되어 있어요.

# ====== 설치 & 환경 점검 ======
from pathlib import Path

# 표준 라이브러리 임포트 (파이썬/OS/프로세스/플랫폼 정보)
import sys, subprocess, os, platform

# pip install 를 파이썬에서 호출하는 헬퍼 함수 (-q 는 로그 최소화)
def pipi(pkg):
    subprocess.run([sys.executable, '-m', 'pip', 'install', '-q', pkg], check=True)

# 현재 파이썬/플랫폼 버전 출력 (디버깅용)
print('Python', sys.version)
print('Platform', platform.platform())

# PyTorch 로드 실패시 설치 후 임포트.
# CUDA(GPU) 사용 가능 여부 출력
try:
    import torch
except Exception:
    pipi('torch')
    import torch
print('Torch CUDA available:', torch.cuda.is_available())

# 전사용 패키지 설치
#  * `faster-whisper`: Whisper의 빠른 추론 구현
#  * `pydub`: 오디오 유틸(이번 노트북에서는 주로 ffmpeg 체크용)
#  * `python-docx`: Word 문서 출력
#  * `pandas`: 표 형태 데이터 처리
#  * `tqdm`: 진행바(필수는 아님)
pipi('faster-whisper==1.0.3')
pipi('pydub')
pipi('python-docx')
pipi('pandas')
pipi('tqdm')

# ffmpeg 설치(Colab에는 보통 내장)
# ffmpeg 존재 여부 확인(오디오 디코딩에 필요). Colab엔 대개 기본 내장.
try:
    subprocess.run(['ffmpeg', '-version'], check=True, stdout=subprocess.PIPE, stderr=subprocess.PIPE)
    print('ffmpeg OK')
except Exception:
    print('ffmpeg 설치 필요. Colab에서는 보통 기본 제공됩니다.')

 

Python 3.12.11 (main, Jun  4 2025, 08:56:18) [GCC 11.4.0]
Platform Linux-6.1.123+-x86_64-with-glibc2.35
Torch CUDA available: False
ffmpeg OK

 

# ====== 파일 업로드 ======
from google.colab import files

# Colab의 파일 업로더 UI 표시.
# 1개 이상 업로드했는지 검증.
up = files.upload()
assert len(up) > 0, '오디오 파일을 업로드하세요.'

# 업로드된 파일명 추출(첫 번째 파일 사용).
# 확인 메시지 출력.
audio_filename = list(up.keys())[0]
print('업로드 완료:', audio_filename)

 

# ====== 설정 ======
# `Path` 임포트(v2에서 추가).
# Whisper 관련 기본 설정:
#  * `model_size`: 모델 크기(정확도↔속도/메모리 트레이드오프)
#  * `language`: `ko`로 고정(자동감지는 `None`)
#  * `beam_size`: 탐색 폭(클수록 정확도↑/속도↓)
#  * `vad_filter`: 무성 구간 제거 필터
#  * `word_timestamps`: 단어 수준 타임스탬프 포함
model_size = 'large-v3'   # 'small', 'medium', 'large-v3' 등 선택 가능
language = 'ko'          # 한국어 고정; 자동 감지를 원하면 None 으로 변경
beam_size = 5
vad_filter = True        # VAD(음성활동감지)로 잡음 구간 억제
word_timestamps = True   # 단어 단위 타임스탬프

# 출력 파일명 접두어 생성(원본 파일명 + `_whisper`).
from datetime import datetime
stem = Path(audio_filename).stem
out_prefix = f"{stem}_whisper"

 

# ====== 전사 실행 ======
# v2에서 `import torch`를 선행(안정성).
# 필요한 라이브러리 로드.
from faster_whisper import WhisperModel
import pandas as pd
import torch
from tqdm import tqdm

# GPU 있으면 `cuda`+`float16`, 없으면 `cpu`+`int8`(메모리 절약)로 자동 설정.
compute_type = 'float16' if (hasattr(torch, 'cuda') and torch.cuda.is_available()) else 'int8'
device = 'cuda' if torch.cuda.is_available() else 'cpu'
print('Device:', device, 'Compute type:', compute_type)

# Whisper 모델 로드
model = WhisperModel(model_size, device=device, compute_type=compute_type)

# 오디오 전사 수행.
# 감지된 언어/확률 출력(언어를 `ko`로 고정했어도 메타 확인용).
segments, info = model.transcribe(
    audio_filename,
    language=language,
    beam_size=beam_size,
    vad_filter=vad_filter,
    word_timestamps=word_timestamps,
)
print('감지 언어:', info.language, '확신도:', round(info.language_probability, 3))

# 결과 저장용 구조 초기화(SRT/VTT 헤더 포함).
rows = []
srt_lines = []
vtt_lines = ['WEBVTT\n']

# 초 단위를 **SRT 시각 포맷**(HH\:MM\:SS,mmm)으로 변환.
def srt_ts(t):
    h = int(t//3600); m = int((t%3600)//60); s = t - h*3600 - m*60
    ms = int(round((s - int(s)) * 1000))
    return f"{h:02d}:{m:02d}:{int(s):02d},{ms:03d}"

# 초 단위를 **VTT 시각 포맷**(HH\:MM\:SS.mmm)으로 변환.
def vtt_ts(t):
    h = int(t//3600); m = int((t%3600)//60); s = t - h*3600 - m*60
    ms = int(round((s - int(s)) * 1000))
    return f"{h:02d}:{m:02d}:{int(s):02d}.{ms:03d}"

# 각 세그먼트(문장 단위)에 대해 텍스트/시작/끝 시간 추출.
# 판다스 테이블용 행 구성.
idx = 1
for seg in segments:
    text = (seg.text or '').strip()
    start = float(seg.start)
    end = float(seg.end)
    rows.append({
        'index': idx,
        'start': start,
        'end': end,
        'start_srt': srt_ts(start),
        'end_srt': srt_ts(end),
        'text': text,
    })
# SRT 블록(번호/타임스탬프/문장/빈줄) 작성
    srt_lines.append(str(idx))
    srt_lines.append(f"{srt_ts(start)} --> {srt_ts(end)}")
    srt_lines.append(text if text else '...')
    srt_lines.append('')

# VTT 라인 추가 후 인덱스 증가.
    vtt_lines.append(f"{vtt_ts(start)} --> {vtt_ts(end)}")
    vtt_lines.append(text if text else '...')
    vtt_lines.append('')
    idx += 1

# 결과물 파일 경로 설정.
df = pd.DataFrame(rows)
txt_path = f"{out_prefix}.txt"
srt_path = f"{out_prefix}.srt"
vtt_path = f"{out_prefix}.vtt"
csv_path = f"{out_prefix}.csv"

# TXT/SRT/VTT/CSV 파일 저장.
# CSV는 Excel 호환을 위해 `utf-8-sig`.
with open(txt_path, 'w', encoding='utf-8') as f:
    f.write('\n'.join(df['text']))
with open(srt_path, 'w', encoding='utf-8') as f:
    f.write('\n'.join(srt_lines))
with open(vtt_path, 'w', encoding='utf-8') as f:
    f.write('\n'.join(vtt_lines))
df.to_csv(csv_path, index=False, encoding='utf-8-sig')

# 생성 결과 요약 출력.
print('생성 파일:', txt_path, srt_path, vtt_path, csv_path)

 

 

# ====== (선택) Word 파일(.docx)로 내보내기 ======
# Word 문서 시작/제목/파일명/빈 줄.
from docx import Document
doc = Document()
doc.add_heading('전사 결과', level=1)
doc.add_paragraph(f'파일명: {audio_filename}')
doc.add_paragraph('')

# 각 세그먼트를 **\[시작\~끝] 텍스트** 형식으로 문단 추가(시간 범위는 볼드).
for _, r in df.iterrows():
    p = doc.add_paragraph()
    p.add_run(f"[{r['start_srt']} ~ {r['end_srt']}] ").bold = True
    p.add_run(r['text'])

# docx 저장 및 경로 출력.
docx_path = f"{out_prefix}.docx"
doc.save(docx_path)
print('생성 파일:', docx_path)

 

생성 파일:XXXX_whisper.docx

# ====== (선택) Google Drive 저장 ======
# 드라이브 마운트(처음 1번은 권한 승인 필요).
from google.colab import drive
drive.mount('/content/drive')

# 저장 폴더 생성(없으면 자동 생성).
import shutil, os
target_dir = '/content/drive/MyDrive/whisper_outputs'
os.makedirs(target_dir, exist_ok=True)

# 생성된 파일들을 드라이브 폴더로 복사.
for p in [txt_path, srt_path, vtt_path, csv_path, docx_path]:
    if os.path.exists(p):
        shutil.copy(p, target_dir)
print('Drive 저장 위치:', target_dir)

 

Mounted at /content/drive

Drive 저장 위치: /content/drive/MyDrive/whisper_outputs

 

# ====== 결과 다운로드 링크 ======
# Colab 파일 다운로드 창을 띄워, 결과물을 로컬로 저장.
from google.colab import files
for p in [txt_path, srt_path, vtt_path, csv_path, docx_path]:
    if os.path.exists(p):
        files.download(p)

 

 

자주 바꾸는 옵션 요약

 

정확도 vs 속도/메모리
  `model_size`: `'large-v3'`(정확도↑ 메모리↑) → 느리면 `'medium'`/`'small'`.
   `compute_type`: 자동(`float16`/`int8`); CPU라 느리면 모델 축소 권장.

 

언어
   `language = 'ko'` → 다국어 혼합이면 `None`으로 자동감지.

 

세부 품질
   `beam_size = 5`(정확도↑/속도↓), `vad_filter = True`(잡음 억제), `word_timestamps = True`(단어 타임스탬프).

 

 

728x90