πŸ–₯οΈπŸ”€ Вранскрибация Π²ΠΈΠ΄Π΅ΠΎ ΠΈ созданиС субтитров с ΠΏΠΎΠΌΠΎΡ‰ΡŒΡŽ Whisper, FFmpeg ΠΈ Python

БлСдуя Π½Π°ΡˆΠ΅ΠΌΡƒ ΠΏΠΎΡˆΠ°Π³ΠΎΠ²ΠΎΠΌΡƒ руководству, Π²Ρ‹ смоТСтС автоматичСски Ρ‚Ρ€Π°Π½ΡΠΊΡ€ΠΈΠ±ΠΈΡ€ΠΎΠ²Π°Ρ‚ΡŒ Π°ΡƒΠ΄ΠΈΠΎ ΠΈ Π΄ΠΎΠ±Π°Π²Π»ΡΡ‚ΡŒ субтитры ΠΊ своим Π²ΠΈΠ΄Π΅ΠΎ всСго Π·Π° нСсколько ΠΌΠΈΠ½ΡƒΡ‚.

Данная ΡΡ‚Π°Ρ‚ΡŒΡ являСтся ΠΏΠ΅Ρ€Π΅Π²ΠΎΠ΄ΠΎΠΌ. Бсылка Π½Π° ΠΎΡ€ΠΈΠ³ΠΈΠ½Π°Π».

НСобходимыС инструмСнты: Python, Whisper, FFmpeg.

Настройка Ρ€Π°Π±ΠΎΡ‡Π΅Π³ΠΎ пространства

Π‘ΠΎΠ·Π΄Π°Π΄ΠΈΠΌ Ρ€Π°Π±ΠΎΡ‡ΡƒΡŽ ΠΏΠ°ΠΏΠΊΡƒ

mkdir open-ai-whisper-ffmpeg

ΠŸΠ΅Ρ€Π΅ΠΉΠ΄Π΅ΠΌ Π² ΠΏΠ°ΠΏΠΊΡƒ ΠΏΡ€ΠΎΠ΅ΠΊΡ‚Π° ΠΈ создадим Π²ΠΈΡ€Ρ‚ΡƒΠ°Π»ΡŒΠ½ΠΎΠ΅ ΠΎΠΊΡ€ΡƒΠΆΠ΅Π½ΠΈΠ΅:

cd open-ai-whisper-ffmpeg
python3 -m venv .venv
source .venv/bin/activate

Установим Π½Π΅ΠΎΠ±Ρ…ΠΎΠ΄ΠΈΠΌΡ‹Π΅ ΠΏΠ°ΠΊΠ΅Ρ‚Ρ‹ для OpenAI Whisper:

pip install git+https://github.com/m-bain/whisperx.git
🐍 Π‘ΠΈΠ±Π»ΠΈΠΎΡ‚Π΅ΠΊΠ° питониста
Π‘ΠΎΠ»ΡŒΡˆΠ΅ ΠΏΠΎΠ»Π΅Π·Π½Ρ‹Ρ… ΠΌΠ°Ρ‚Π΅Ρ€ΠΈΠ°Π»ΠΎΠ² Π²Ρ‹ Π½Π°ΠΉΠ΄Π΅Ρ‚Π΅ Π½Π° нашСм Ρ‚Π΅Π»Π΅Π³Ρ€Π°ΠΌ-ΠΊΠ°Π½Π°Π»Π΅ Β«Π‘ΠΈΠ±Π»ΠΈΠΎΡ‚Π΅ΠΊΠ° питониста»
πŸπŸŽ“ Π‘ΠΈΠ±Π»ΠΈΠΎΡ‚Π΅ΠΊΠ° собСса ΠΏΠΎ Python
ΠŸΠΎΠ΄Ρ‚ΡΠ½ΡƒΡ‚ΡŒ свои знания ΠΏΠΎ Python Π²Ρ‹ ΠΌΠΎΠΆΠ΅Ρ‚Π΅ Π½Π° нашСм Ρ‚Π΅Π»Π΅Π³Ρ€Π°ΠΌ-ΠΊΠ°Π½Π°Π»Π΅ Β«Π‘ΠΈΠ±Π»ΠΈΠΎΡ‚Π΅ΠΊΠ° собСса ΠΏΠΎ PythonΒ»
🐍🧩 Π‘ΠΈΠ±Π»ΠΈΠΎΡ‚Π΅ΠΊΠ° Π·Π°Π΄Π°Ρ‡ ΠΏΠΎ Python
Π˜Π½Ρ‚Π΅Ρ€Π΅ΡΠ½Ρ‹Π΅ Π·Π°Π΄Π°Ρ‡ΠΈ ΠΏΠΎ Python для ΠΏΡ€Π°ΠΊΡ‚ΠΈΠΊΠΈ ΠΌΠΎΠΆΠ½ΠΎ Π½Π°ΠΉΡ‚ΠΈ Π½Π° нашСм Ρ‚Π΅Π»Π΅Π³Ρ€Π°ΠΌ-ΠΊΠ°Π½Π°Π»Π΅ Β«Π‘ΠΈΠ±Π»ΠΈΠΎΡ‚Π΅ΠΊΠ° Π·Π°Π΄Π°Ρ‡ ΠΏΠΎ PythonΒ»

Вранскрибация Π²ΠΈΠ΄Π΅ΠΎ

Π‘Π½Π°Ρ‡Π°Π»Π° создадим Π½ΠΎΠ²Ρ‹ΠΉ Ρ„Π°ΠΉΠ» Python – main.py.

touch main.py

И добавим в нСго код:

from datetime import timedelta
import os
import whisperx

def transcribe_video(input_video):
    batch_size = 32 
    compute_type = "float32"  
    device = "cpu"

    model = whisperx.load_model("large-v2", device=device, compute_type=compute_type)

    audio = whisperx.load_audio(input_video)
    result = model.transcribe(audio, batch_size=batch_size, language="en")

    model_a, metadata = whisperx.load_align_model(language_code=result["language"], device=device)
    result = whisperx.align(result["segments"], model_a, metadata, audio, device, return_char_alignments=False)

    segments = result["segments"]


   # if srt file exists, delete it
    if os.path.exists("subtitles.srt"):
        os.remove("subtitles.srt")
    for index, segment in enumerate(segments):
        startTime = str(0)+str(timedelta(seconds=int(segment['start'])))+',000'
        endTime = str(0)+str(timedelta(seconds=int(segment['end'])))+',000'
        text = segment['text']
        print(text)
        segment = f"{index + 1}\n{startTime} --> {endTime}\n{text[1:] if text[0] == ' ' else text}\n\n"

        srtFilename = os.path.join(f"subtitles.srt")
        with open(srtFilename, 'a', encoding='utf-8') as srtFile:
            srtFile.write(segment)

    return srtFilename



def main():
    input_video_path = "input.mp4"
    transcribe_video(input_video_path)

main()

Π”Π°Π²Π°ΠΉΡ‚Π΅ рассмотрим, Ρ‡Ρ‚ΠΎ ΠΌΡ‹ Π΄Π΅Π»Π°Π΅ΠΌ Π² ΠΏΡ€ΠΈΠ²Π΅Π΄Π΅Π½Π½ΠΎΠΌ Π²Ρ‹ΡˆΠ΅ ΠΊΠΎΠ΄Π΅. Π’ этих строках ΠΌΡ‹ ΠΈΠΌΠΏΠΎΡ€Ρ‚ΠΈΡ€ΡƒΠ΅ΠΌ Π½Π΅ΠΎΠ±Ρ…ΠΎΠ΄ΠΈΠΌΡ‹Π΅ ΠΏΠ°ΠΊΠ΅Ρ‚Ρ‹ для Ρ€Π°Π±ΠΎΡ‚Ρ‹: whisperx для Π·Π°Π³Ρ€ΡƒΠ·ΠΊΠΈ ΠΌΠΎΠ΄Π΅Π»ΠΈ Whisper, os для получСния ΠΏΡƒΡ‚ΠΈ ΠΊ Ρ„Π°ΠΉΠ»Ρƒ субтитров ΠΈ timedelta для форматирования тСкста Π²Ρ€Π΅ΠΌΠ΅Π½Π½Ρ‹Ρ… ΠΌΠ΅Ρ‚ΠΎΠΊ.

from datetime import timedelta
import os
import whisperx

Π—Π΄Π΅ΡΡŒ ΠΌΡ‹ ΠΎΠΏΡ€Π΅Π΄Π΅Π»ΠΈΠ»ΠΈ Ρ„ΡƒΠ½ΠΊΡ†ΠΈΡŽ, которая ΠΏΡ€ΠΈΠ½ΠΈΠΌΠ°Π΅Ρ‚ Π²Ρ…ΠΎΠ΄Π½ΠΎΠ΅ Π²ΠΈΠ΄Π΅ΠΎ, Π·Π°Π³Ρ€ΡƒΠΆΠ°Π΅Ρ‚ модСль Whisper large-v2, ΡƒΠΊΠ°Π·Ρ‹Π²Π°Π΅Ρ‚ Ρ‚ΠΈΠΏ вычислСний ΠΈ настраиваСт модСль Π½Π° использованиС CPU вмСсто GPU.

ПослС этого функция Π·Π°Π³Ρ€ΡƒΠΆΠ°Π΅Ρ‚ Π°ΡƒΠ΄ΠΈΠΎ Π² модСль, Π·Π°Ρ‚Π΅ΠΌ транскрибируСт ΠΈ Π²ΠΎΠ·Π²Ρ€Π°Ρ‰Π°Π΅Ρ‚ тСкст с Π²Ρ€Π΅ΠΌΠ΅Π½Π½Ρ‹ΠΌΠΈ ΠΌΠ΅Ρ‚ΠΊΠ°ΠΌΠΈ.

def transcribe_video(input_video):
    batch_size = 32 
    compute_type = "float32"  
    device = "cpu"

    model = whisperx.load_model("large-v2", device=device, compute_type=compute_type)

    audio = whisperx.load_audio(input_video)
    result = model.transcribe(audio, batch_size=batch_size, language="en")

    model_a, metadata = whisperx.load_align_model(language_code=result["language"], device=device)
    result = whisperx.align(result["segments"], model_a, metadata, audio, device, return_char_alignments=False)

    segments = result["segments"]

ПослС этого функция ΠΏΡ€ΠΎΡ…ΠΎΠ΄ΠΈΡ‚ ΠΏΠΎ всСм ΠΏΠΎΠ»ΡƒΡ‡Π΅Π½Π½Ρ‹ΠΌ модСлью Ρ€Π΅Π·ΡƒΠ»ΡŒΡ‚Π°Ρ‚Π°ΠΌ, ΠΏΡ€Π΅ΠΎΠ±Ρ€Π°Π·ΡƒΠ΅Ρ‚ ΠΈΡ… Π² Ρ„ΠΎΡ€ΠΌΠ°Ρ‚ .srt ΠΈ добавляСт ΠΊΠ°ΠΆΠ΄Ρ‹ΠΉ элСмСнт слова Π² Ρ„Π°ΠΉΠ» subtitles.srt.

   # if srt file exists, delete it
    if os.path.exists("subtitles.srt"):
        os.remove("subtitles.srt")
    for index, segment in enumerate(segments):
        startTime = str(0)+str(timedelta(seconds=int(segment['start'])))+',000'
        endTime = str(0)+str(timedelta(seconds=int(segment['end'])))+',000'
        text = segment['text']
        print(text)
        segment = f"{index + 1}\n{startTime} --> {endTime}\n{text[1:] if text[0] == ' ' else text}\n\n"

        srtFilename = os.path.join(f"subtitles.srt")
        with open(srtFilename, 'a', encoding='utf-8') as srtFile:
            srtFile.write(segment)

    return srtFilename

Π”ΠΎΠ±Π°Π²Π»Π΅Π½ΠΈΠ΅ субтитров ΠΊ Π²ΠΈΠ΄Π΅ΠΎ

Π”Π°Π»Π΅Π΅ ΠΌΡ‹ Π·Π°Π³Ρ€ΡƒΠΆΠ°Π΅ΠΌ subtitles.srt Π² Π²ΠΈΠ΄Π΅ΠΎ с ΠΏΠΎΠΌΠΎΡ‰ΡŒΡŽ FFmpeg. Π’ ΠΈΡ‚ΠΎΠ³Π΅ ΠΏΠΎΠ»ΡƒΡ‡Π°Π΅ΠΌ ΡΠ»Π΅Π΄ΡƒΡŽΡ‰ΠΈΠΉ скрипт:

from datetime import timedelta
import os
import whisperx
import subprocess

def transcribe_video(input_video):
    batch_size = 32 
    compute_type = "float32"  
    device = "cpu"

    model = whisperx.load_model("large-v2", device=device, compute_type=compute_type)

    audio = whisperx.load_audio(input_video)
    result = model.transcribe(audio, batch_size=batch_size, language="en")

    model_a, metadata = whisperx.load_align_model(language_code=result["language"], device=device)
    result = whisperx.align(result["segments"], model_a, metadata, audio, device, return_char_alignments=False)

    segments = result["segments"]


   # if srt file exists, delete it
    if os.path.exists("subtitles.srt"):
        os.remove("subtitles.srt")
    for index, segment in enumerate(segments):
        startTime = str(0)+str(timedelta(seconds=int(segment['start'])))+',000'
        endTime = str(0)+str(timedelta(seconds=int(segment['end'])))+',000'
        text = segment['text']
        print(text)
        segment = f"{index + 1}\n{startTime} --> {endTime}\n{text[1:] if text[0] == ' ' else text}\n\n"

        srtFilename = os.path.join(f"subtitles.srt")
        with open(srtFilename, 'a', encoding='utf-8') as srtFile:
            srtFile.write(segment)

    return srtFilename

def add_srt_to_video(input_video, output_file):

    # FFmpeg command
    subtitles_file = 'subtitles.srt'

    # FFmpeg command
    ffmpeg_command = f"""ffmpeg -i {input_video} -vf "subtitles={subtitles_file}:force_style='FontName=Arial,FontSize=10,PrimaryColour=&HFFFFFF,OutlineColour=&H000000,BorderStyle=3,Outline=1,Shadow=1,Alignment=2,MarginV=10'" -c:a copy {output_file} -y """

    # Run the FFmpeg command
    subprocess.run(ffmpeg_command, shell=True)

<u>def main():</u>
 


    input_video_path = "input.mp4"
    output_file = "output.mp4"
    transcribe_video(input_video_path)
    add_srt_to_video(input_video_path, output_file)


main()

Π Π΅Π·ΡƒΠ»ΡŒΡ‚Π°Ρ‚

Вранскрибация Π²ΠΈΠ΄Π΅ΠΎ ΠΈ созданиС субтитров с ΠΏΠΎΠΌΠΎΡ‰ΡŒΡŽ Whisper, FFmpeg ΠΈ Python

Π›Π£Π§Π¨Π˜Π• БВАВЬИ ПО Π’Π•ΠœΠ•

admin
11 дСкабря 2018

ООП Π½Π° Python: ΠΊΠΎΠ½Ρ†Π΅ΠΏΡ†ΠΈΠΈ, ΠΏΡ€ΠΈΠ½Ρ†ΠΈΠΏΡ‹ ΠΈ ΠΏΡ€ΠΈΠΌΠ΅Ρ€Ρ‹ Ρ€Π΅Π°Π»ΠΈΠ·Π°Ρ†ΠΈΠΈ

ΠŸΡ€ΠΎΠ³Ρ€Π°ΠΌΠΌΠΈΡ€ΠΎΠ²Π°Π½ΠΈΠ΅ Π½Π° Python допускаСт Ρ€Π°Π·Π»ΠΈΡ‡Π½Ρ‹Π΅ ΠΌΠ΅Ρ‚ΠΎΠ΄ΠΎΠ»ΠΎΠ³ΠΈΠΈ, Π½ΠΎ Π² Π΅Π³ΠΎ основС...
admin
28 июня 2018

3 самых Π²Π°ΠΆΠ½Ρ‹Ρ… сфСры примСнСния Python: возмоТности языка

БущСствуСт мноТСство областСй примСнСния Python, Π½ΠΎ Π² Π½Π΅ΠΊΠΎΡ‚ΠΎΡ€Ρ‹Ρ… ΠΎΠ½ особСнно...
admin
13 фСвраля 2017

ΠŸΡ€ΠΎΠ³Ρ€Π°ΠΌΠΌΠΈΡ€ΠΎΠ²Π°Π½ΠΈΠ΅ Π½Π° Python: ΠΎΡ‚ Π½ΠΎΠ²ΠΈΡ‡ΠΊΠ° Π΄ΠΎ профСссионала

Пошаговая инструкция для всСх, ΠΊΡ‚ΠΎ Ρ…ΠΎΡ‡Π΅Ρ‚ ΠΈΠ·ΡƒΡ‡ΠΈΡ‚ΡŒΒ ΠΏΡ€ΠΎΠ³Ρ€Π°ΠΌΠΌΠΈΡ€ΠΎΠ²Π°Π½ΠΈΠ΅ Π½Π° Python...