Парокит Автозаголовок — Автоматическое создание SRT файлов с помощью Parakeet v3

Парокит Автозаголовок — Автоматическое создание SRT файлов с помощью Parakeet v3


Три года назад мир глубокого обучения в области распознавания речи (ASR) потрясла публикация первых настоящих базовых моделей в наборе Whisper от OpenAI. В частности, Whisper Large продолжает развиваться, и Whisper Large v3 является базовой моделью для множества различных инструментов с открытым исходным кодом, веб-приложений и бизнес-применений.

Вот уже долгое время Whisper занимает первые позиции в рейтингах ASR по точности, уровню ошибок в словах и удобству использования. Но теперь появился новый конкурент — Parakeet v3 от NVIDIA. Parakeet v3 соперничает и даже превосходит Whisper Large v3 и другие модели, такие как Seamless M4T, по нескольким тестам на уровень ошибок в словах при транскрипции на английском языке. Более того, его невероятно легко внедрить, и для его работы требуется низкая вычислительная мощность.

В этом учебном пособии мы рады объявить о выпуске Parakeet AutoCaption здесь и на HuggingFace. Этот скрипт и веб-приложения используют Parakeet v3 для создания наложенных английских субтитров на видео с соответствующими выходными .srt файлами с высокой степенью успеха. В этом учебнике мы покажем, как использовать эти веб-приложения на полную мощность! Читатели могут ожидать, что после прохождения учебного пособия научатся создавать это приложение с нуля.

Ключевые выводы

  • Parakeet AutoCaption использует Parakeet v3 для перевода и транскрибирования любых видеобразцов на английский язык с субтитрами и временными метками на до 25 европейских языках.
  • Мы публикуем Parakeet AutoCaption с открытым исходным кодом на HuggingFace и призываем других улучшать дизайн.

Попугай v3

Согласно их документации, «parakeet-tdt-0.6b-v3 — это модель автоматического распознавания речи (ASR) с 600 миллионами параметров, разработанная для высокоскоростной транскрипции речи в текст.» На практике версия v3 этой модели расширяет модель parakeet-tdt-0.6b-v2. Она увеличивает поддержку языков с английского на 25 европейских языков, включая болгарский (bg), хорватский (hr), чешский (cs), датский (da), нидерландский (nl), английский (en), эстонский (et), финский (fi), французский (fr), немецкий (de), греческий (el), венгерский (hu), итальянский (it), латвийский (lv), литовский (lt), мальтийский (mt), польский (pl), португальский (pt), румынский (ro), словацкий (sk), словенский (sl), испанский (es), шведский (sv), русский (ru), украинский (uk). Упрощая все, модель на самом деле способна автоматически определять входной язык аудио и транскрибировать его без необходимости в дополнительных подсказках. Она является частью серии моделей, которые используют многоязычный корпус Granary в качестве основного обучающего набора данных.

Как мы можем увидеть из графика, который они предоставили для выпуска модели, Parakeet превзошел whisper-large-v3, seamless-m4t-medium и seamless-m4t-large по сравнению с уровнем ошибок слов в нескольких benchmarks на 24 поддерживаемых языках.

Автоподпись попугайчика

Теперь, когда мы представили Parakeet v3 и обсудили его невероятную полезность в качестве модели ASR, давайте взглянем на скрипт веб-приложения. Мы можем использовать его для генерации .srt файла и субтитров, использованных в приведенных выше примерах.

Сначала давайте разберем установку и импорты.

Pip3 install torch torchvision moviepy pydub opencv-python-headless gradio braceexpand editdistance einops jiwer>=3.1.0,<4.0.0 kaldi-python-io lhotse!=1.31.0 librosa>=0.10.1 marshmallow optuna packaging pyannote.core pyannote.metrics pydub pyloudnorm resampy ruamel.yaml scipy>=0.14 soundfile sox<=1.5.0 texterrors<1.0.0 hydra-core pytorch-lightning flash-attn cuda-python spaces git+https://github.com/NVIDIA/NeMo.git@main#egg=nemo_toolkit[asr] 

Это установит всё необходимое для работы Parakeet AutoCaption! Далее давайте посмотрим, как мы их импортируем.

## Imports: helpers from __future__ import unicode_literals import cv2 import pandas as pd import os import csv, re, sys from pathlib import Path import urllib.request  ## import moviepy from moviepy.video.tools.subtitles import SubtitlesClip from moviepy.video.io.VideoFileClip import VideoFileClip from moviepy import CompositeVideoClip from moviepy import TextClip  #import nemo asr library and gradio import nemo.collections.asr as nemo_asr import gradio as gr import spaces  ## get font urllib.request.urlretrieve("https://github.com/Jameshskelton/fonts/raw/refs/heads/main/P052-Roman.ttf", "P052-Roman.ttf") 

Установка всех необходимых пакетов гарантирует, что мы сможем успешно импортировать их для приложения. Убедитесь, что все эти установки прошли успешно, прежде чем продолжать.

В следующем разделе у нас есть ряд вспомогательных функций.

def parse_time_to_srt(t):     s = str(t).strip()     if re.fullmatch(r"d+(.d+)?", s):         total_ms = int(round(float(s) * 1000))     else:         parts = s.split(':')         if len(parts) == 2:             mm, ss = parts             sec = float(ss)             total_ms = int(round((int(mm) * 60 + sec) * 1000))         elif len(parts) == 3:             hh, mm, ss = parts             sec = float(ss)             total_ms = int(round(((int(hh) * 3600) + (int(mm) * 60) + sec) * 1000))         else:             raise ValueError(f"Unrecognized time format: {s}")     hours = total_ms // 3_600_000     rem = total_ms % 3_600_000     minutes = rem // 60_000     rem = rem % 60_000     seconds = rem // 1000     millis = rem % 1000     return f"{hours:02}:{minutes:02}:{seconds:02},{millis:03}"  def map_position_to_tag(pos):     if not pos:         return ""     s = str(pos).strip().lower()     m = re.search(r"\?an([1-9])", s)     if m:         return "{\an" + m.group(1) + "}"     if "top left" in s or ("top" in s and "left" in s):         return "{\an7}"     if "top right" in s or ("top" in s and "right" in s):         return "{\an9}"     if "bottom left" in s or ("bottom" in s and "left" in s):         return "{\an1}"     if "bottom right" in s or ("bottom" in s and "right" in s):         return "{\an3}"     if "top" in s:         return "{\an8}"     if "middle" in s or "center" in s or "centre" in s:         return "{\an5}"     if "bottom" in s:         return "{\an2}"     return ""  def looks_like_header(row):     joined = ",".join(c.strip().lower() for c in row[:4])     header_words = ["position", "pos", "align", "start", "begin", "end", "stop", "subtitle", "text", "caption"]     return any(w in joined for w in header_words)  def csv_to_srt(csv_path: Path, srt_path: Path):     with open(f'{csv_path}',"r", encoding="utf-8-sig", newline="") as f:         reader = csv.reader(f)         rows = [row for row in reader if any(cell.strip() for cell in row)]     if not rows:         raise ValueError("CSV is empty.")     start_index = 1 if looks_like_header(rows[0]) else 0     normalized = []     for i, row in enumerate(rows[start_index:], start=start_index+1):         if len(row) < 4:             raise ValueError(f"Row {i} has fewer than 4 columns: {row}")         position, start, end, text = row[0].strip(), row[1].strip(), row[2].strip(), row[3]         normalized.append((position, start, end, text))     with open(f"{srt_path}", "w", encoding="utf-8") as out:         for idx, (position, start, end, text) in enumerate(normalized, start=1):             start_srt = parse_time_to_srt(start)             end_srt = parse_time_to_srt(end)             pos_tag = map_position_to_tag(position)             final_text = f"{pos_tag}{text}" if pos_tag else text             out.write(f"{idx}n")             out.write(f"{start_srt} --> {end_srt}n")             out.write(f"{final_text}nn")  from pydub import AudioSegment  def convert_audio_to_mono_16khz(input_path, output_path):     """     Converts an audio file to mono and resamples it to 16 kHz.      Args:         input_path (str): The path to the input audio file.         output_path (str): The path to save the converted audio file.     """     try:         audio = AudioSegment.from_file(input_path)         # Set channels to 1 (mono)         audio = audio.set_channels(1)         # Set frame rate (sample rate) to 16000 Hz         audio = audio.set_frame_rate(16000)         audio.export(output_path, format="wav") # Export as WAV or desired format         print(f"Audio converted successfully to mono, 16kHz at: {output_path}")     except Exception as e:         print(f"Error converting audio: {e}") 

Эти вспомогательные функции необходимы для выполнения основной функции. parse_time_to_srt() преобразует временные метки, используемые Parakeet, в формат, который можно прочитать как файл SRT. map_position_to_tag() находит и назначает позиционный тег словам. looks_like_header() подтверждает положение слова-заголовка. Наконец, csv_to_srt() использует эти вспомогательные функции для создания нашей основной вспомогательной функции, которая конвертирует CSV, который мы создаем с Parakeet, в файл SRT. У нас есть одна дополнительная вспомогательная функция, convert_audio_to_mono_16khz(), которая необходима для того, чтобы наш аудиофайл можно было прочитать Parakeet в первую очередь.

В следующем разделе мы покажем основную функцию subtitle_video() в полном объеме. Следите за поясняющими комментариями внутри функции, чтобы понять, как работает эта функция, построчно.

## instantiate the ASR model outside the function so it doesn’t have to be reloaded each run asr_model = nemo_asr.models.ASRModel.from_pretrained(model_name="nvidia/parakeet-tdt-0.6b-v3")  @spaces.GPU def subtitle_video(input_file): #------------------------------------------------------------------------------------------------------------------------------     Params: #------------------------------------------------------------------------------------------------------------------------------     input_file:    str, path to video file for MoviePy to caption #------------------------------------------------------------------------------------------------------------------------------     Returns:        output_video: An annotated video with translated captions into english output_subs: Subtitles in csv format, displayed as table on web app output_subs_srt_file: path to srt file containing timestamped subtitles #------------------------------------------------------------------------------------------------------------------------------          ## First, this checks if your experiment name is taken. If not, it will create the directory.     ## Otherwise, we will be prompted to retry with a new name     name = 'run'     try:         os.mkdir(f'experiments/{name}')         print('Starting AutoCaptioning...')         print(f'Results will be stored in experiments/{name}')              except:         None          # Use VideoFileClip to instantiate video     my_clip = VideoFileClip(input_file)     my_clip.write_videofile(f"experiments/{name}/{input_file.split('/')[-1]}")     my_clip.audio.write_audiofile(f'experiments/{name}/audio_file.wav', codec="mp3")      # load parakeet model as model variable     model = asr_model      # convert to format parakeet can interpret     convert_audio_to_mono_16khz(f'experiments/{name}/audio_file.wav', f'experiments/{name}/audio_file.wav')      # transcribe audio with Parakeet     output = model.transcribe([f'experiments/{name}/audio_file.wav'], timestamps=True)      # Convert audio to text with timestamps, dump into dataframe     df = pd.DataFrame(output[0].timestamp['segment'])     df['text'] = df['segment']     df = df.drop(['start_offset', 'end_offset', 'segment'],axis = 1)      # save csv and srt files     df.to_csv(f'experiments/{name}/subs.csv')     csv_to_srt(f"experiments/{name}/subs.csv",f"experiments/{name}/subs.srt")      # Capture video     vidcap = cv2.VideoCapture(f'''experiments/{name}/{input_file}''')     success, image = vidcap.read()          # Instantiate MoviePy subtitle generator with TextClip, subtitles, and SubtitlesClip     generator = lambda txt: TextClip(     "./P052-Roman.ttf",     text = txt,     font_size = int(my_clip.w/50),     stroke_width=1,     color= "white",     stroke_color="black",     size = (my_clip.w, my_clip.h),     vertical_align = 'bottom',     horizontal_align = 'center',     method='caption')      subs = SubtitlesClip(f"experiments/{name}/subs.srt", make_textclip=generator)  ## Write subs to video file and return     video = VideoFileClip(input_file)     final = CompositeVideoClip([video, subs])     final.write_videofile(f'experiments/{name}/output.mp4', fps=video.fps, remove_temp=True, codec="libx264", audio_codec="aac")     return f'experiments/{name}/output.mp4', df, f"experiments/{name}/subs.srt"  web app code with gr.Blocks() as demo:     gr.Markdown("<div style='display:flex;justify-content:center;align-items:center;gap:.5rem;font-size:24px;'>🦜 <strong>Parakeet AutoCaption Web App</strong></div>")     with gr.Column():         input_video = gr.Video(label = 'Input your video for captioning')         # input_name = gr.Textbox(label = 'Name of your experiment run')     with gr.Column():         run_button = gr.Button('Run Video Captioning')     with gr.Column():         output_video = gr.Video(label = 'Output Video')         output_subs = gr.Dataframe(label = 'Output Subtitles')         output_subs_srt_file = gr.DownloadButton(label = 'Download subtitles as SRT file')     gr.on(         triggers=[run_button.click],         fn=subtitle_video,         inputs=[             input_video,         ],         outputs=[output_video, output_subs, output_subs_srt_file],     ) if __name__ == "__main__":     demo.launch(share=True)  

Вместе мы создаем полное веб-приложение Gradio для Parakeet AutoCaption. Оно будет принимать любой видеофайл, транскрибировать и, если необходимо, переводить аудиоконтент, а также добавлять субтитры к видео на английском языке.

Это приложение в настоящее время работает как HuggingFace Space, но его можно легко развернуть на GPU Droplet от DigitalOcean, склонировав репозиторий HuggingFace на машину. Просто установите все необходимые пакеты и запустите веб-приложение с помощью следующего кода.

git clone https://huggingface.co/spaces/JamesDigitalOcean/Parakeet-AutoCaption cd Parakeet-AutoCaption pip install -r requirements.txt python3 app.py --share 

Заключительные мысли

Parakeet v3 — это невероятно мощная модель ASR от NVIDIA, и мы очень рады обновить систему AutoCaption, чтобы использовать её. С выпуском Parakeet AutoCaption мы открываем дверь в новое поколение доступных, эффективных и многоязычных субтитров для видео. Независимо от того, являетесь ли вы разработчиком, стремящимся интегрировать передовые ASR в свою систему, создателем контента, целеустремлённо работающим над улучшением видимости своих видео, или исследователем, который оценивает последние модели распознавания речи, этот инструмент предоставляет простой, но мощный старт. Мы приглашаем сообщество протестировать его, развивать и делиться своими собственными вкладами.

Комментарии

Добавить комментарий

Ваш адрес email не будет опубликован. Обязательные поля помечены *