Реалізація розпізнавання мовлення з відеофайлів Вилучення аудіодоріжки з відео та її транскрибація - стандартне завдання при створенні субтитрів, індексування відеоархівів, аналітиці вебінарів. Ключовий момент: якість вихідної аудіодоріжки визначає WER більше ніж вибір моделі. ### Pipeline вилучення та транскрибації```python
import subprocess import tempfile from pathlib import Path from faster_whisper import WhisperModel
def extract_audio_from_video(video_path: str) -> str: """Извлекаем аудио из видео через FFmpeg""" output_path = tempfile.mktemp(suffix='.wav') cmd = [ 'ffmpeg', '-i', video_path, '-vn', # отключаем видео '-ar', '16000', # 16kHz для ASR '-ac', '1', # моно '-acodec', 'pcm_s16le', # PCM 16-bit '-af', 'loudnorm', # нормализация громкости output_path, '-y', '-loglevel', 'error' ] subprocess.run(cmd, check=True) return output_path
def transcribe_video(video_path: str, model: WhisperModel) -> dict:
audio_path = extract_audio_from_video(video_path)
try:
segments, info = model.transcribe(
audio_path,
vad_filter=True,
word_timestamps=True,
language="ru"
)
return {
"language": info.language,
"segments": [
{
"start": seg.start,
"end": seg.end,
"text": seg.text
}
for seg in segments
]
}
finally:
Path(audio_path).unlink(missing_ok=True)
### Формати відео FFmpeg підтримує все: MP4, MKV, AVI, MOV, WebM, FLV. При записах вебінарів (Zoom, Teams) часто зустрічається низький bitrate аудіо - застосовуємо `loudnorm` фільтр і опціонально `highpass=f=200` для видалення низькочастотного шуму. ### Обробка багатодоріжкового відео У відеоконференціях кожен учасник може бути на окремій аудіодоріжці:python
Получаем информацию о дорожках
probe = ffmpeg.probe(video_path) audio_streams = [s for s in probe['streams'] if s['codec_type'] == 'audio']
Обрабатываем каждую дорожку отдельно для диаризации
### Генерація субтитрів З результату транскрибації автоматично генеруємо SRT/VTT:python
def to_srt(segments) -> str:
lines = []
for i, seg in enumerate(segments, 1):
start = format_timestamp(seg['start'])
end = format_timestamp(seg['end'])
lines.append(f"{i}\n{start} --> {end}\n{seg['text'].strip()}\n")
return "\n".join(lines)







