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

  • Обзор OpenAI Whisper и его производительность по сравнению с другими системами автоматического распознавания речи
  • Коммерческий API Whisper и собственное решение Whisper: преимущества и недостатки
  • Как использовать Whisper с Python
  • Место Whisper с точки зрения качества перевода по сравнению с другими моделями машинного перевода
  • Как еще больше улучшить качество транскрипции аудио
  • Мой проект для просмотра видео на YouTube с качественными субтитрами

Введение

Когда дело доходит до автоматически генерируемых субтитров на YouTube, многие люди находят некоторые аспекты, которые можно было бы улучшить, в том числе:

  1. Точность транскрипции приличная, когда речь идет об английском языке, однако ее точность снижается, когда речь идет о других языках.
  2. Текст представлен в ненормализованном формате, без знаков препинания.
  3. Субтитры появляются на экране по мере произнесения слов, хотя многие считают, что удобнее видеть строку субтитров целиком, чтобы «немного заглянуть в будущее».
  4. YouTube поддерживает только самые распространенные языки
  5. Иногда YouTube просто отказывается от определенного видео. Например, История всего мира Билла Вурца, я думаю не имеет субтитров, хотя полностью слышна. Когда дело доходит до сложных видео (таких как музыкальные клипы), на YouTube редко есть доступные субтитры, а когда они есть, они очень часто далеки от них.
  6. У YouTube иногда возникают проблемы с определением языка, даже в очевидных случаях. Например, этот мультфильм был идентифицирован как говорящий по-испански, а не по-английски.

Можно ли создавать более качественные субтитры? Это действительно так!

Я разработал алгоритм, который генерирует субтитры, которые значительно превосходят автоматически генерируемые субтитры YouTube, а также поддерживает большое количество языков. Этот алгоритм основан на Whisper, нейронной сети автоматического распознавания речи от OpenAI.

Вот демонстрационное видео моего проекта, в котором используется этот алгоритм.

В этой статье я собираюсь

  • представить вам OpenAI Whisper
  • проведет вас через процесс использования Whisper с Python
  • поделиться некоторыми техническими подробностями о том, как я еще больше улучшил качество сгенерированных субтитров по сравнению с базовым уровнем Whisper

Шепот

OpenAI Whisper — это система автоматического распознавания речи на основе трансформера (технические подробности см. в этой статье) с открытым исходным кодом. Whisper можно использовать бесплатно, и модель загружается на ваш компьютер при первом запуске. Однако у вас также есть возможность использовать коммерческий API от OpenAI.

Самая большая версия Whisper имеет 1 550 миллионов параметров. Однако доступны версии меньшего размера, которые можно использовать для экономии ресурсов.

Whisper может выполнять несколько задач, в том числе:

Транскрипция аудио на английском языке: при наличии аудиофайла (допускаются несколько форматов) он создает серию подписей для фрагментов речи. Речевые фрагменты также имеют временные метки.

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

Аудиотранскрипция не на английском языке. Whisper поддерживает 96 языков помимо английского. На приведенной ниже диаграмме показана точность транскрипции для разных языков в наборе данных Fleurs.

X→английский аудиоперевод: на диаграмме ниже показана эффективность перевода Whisper в наборе данных Fleurs для различных языков.

Распознавание языка. Самая большая модель Whisper обеспечивает точность 80,3 % в подмножестве набора данных Fleurs, которое включает только языки, поддерживаемые Whisper.

Коммерческий API Whisper

Есть два способа использования Whisper:

  1. Через коммерческий API: вы регистрируетесь на веб-сайте OpenAI, получаете токен API, а затем платите по мере использования за запросы, которые вы отправляете на серверы OpenAI.
  2. Установка Whisper из репозитория: модели Whisper размещаются на вашем компьютере. Далее в этой статье я расскажу вам об этом подходе, потому что он сложнее, чем первый.

У каждого подхода есть несколько преимуществ и недостатков:

  • Самостоятельное решение бесплатно
  • Если у вас нет очень мощного GPU-сервера, коммерческий API даст результаты гораздо быстрее.
  • Коммерческий API не поддерживает временные метки для фрагментов речи, он показывает результаты только для всего текста. Это очень важно для приложений генерации субтитров, таких как мой проект.
  • Коммерческий API проще в использовании
  • Похоже, что коммерческий API выполняет некоторую постобработку результатов, что немного повышает их качество.
  • Коммерческий API не поддерживает обработку файлов размером более 25 МБ.

Настраивать

Перед настройкой Whisper нам нужно установить командный инструмент ffmpeg, который обрабатывает аудиофайлы.

# on Ubuntu or Debian
sudo apt update && sudo apt install ffmpeg
# on Arch Linux
sudo pacman -S ffmpeg
# on MacOS using Homebrew (https://brew.sh/)
brew install ffmpeg
# on Windows using Chocolatey (https://chocolatey.org/)
choco install ffmpeg
# on Windows using Scoop (https://scoop.sh/)
scoop install ffmpeg

Чтобы установить Whisper, мы просто запускаем эту команду:

pip install git+https://github.com/openai/whisper.git

Он установит Whisper вместе со своими зависимостями Python (pytorch, трансформеры Hugging Face и ffmpeg-python).

Транскрипция аудио

Whisper довольно прост в использовании. Вот код, который расшифровывает аудио:

import whisper
model_name = "large"
model = whisper.load_model(model_name, download_root="models")
res = model.transcribe("path//to//your//file.mp4", language='en')
  1. имя_модели – это модель Whisper, которую вы используете.
  2. download_root — это место, куда загружаются модели при первом запуске.
  3. language – это язык видео. Если вы не укажете язык, он будет определен автоматически по первой части видео (до 30 секунд).

res будет словарем, содержащим следующие поля:

  1. res.text: распознан весь текст
  2. res.segments: список словарей для речевых сегментов: res.segments[i].start и res.segments[i].end представляют временные границы (в секундах) сегмента, а res.segments[i].text содержит его текст

Результаты транскрипции аудио

Давайте сравним результаты транскрипции Whisper с автоматически сгенерированными субтитрами на YouTube.

Мы будем использовать этот фрагмент из Истории игрушек в качестве образца текста, потому что:

  1. Он содержит речь двух разных персонажей
  2. Голосовые линии существенно различаются по интонации, темпу и высоте тона.
  3. Он также имеет некоторые фоновые шумы, которые могут сбить модели с толку.

Аудио Перевод

Whisper также может выполнять голосовой перевод: если мы установим language на en, но речь в аудиофайле будет не на английском языке, Whisper вернет нам английский язык. перевод того, что говорится.

Этот подход Whisper «голосовой перевод по несоответствию языка» технически работает и для других языков. Однако качество перевода будет довольно низким, если целевой язык не английский.

Какой подход приведет к лучшему качеству перевода: перевод аудио напрямую с помощью Whisper или сначала расшифровка аудио с помощью Whisper, а затем перевод результатов с помощью отдельной переводческой нейронной сети? Я провел эксперимент, чтобы выяснить это.

Я собрал 100 предложений с Татоэба, каждое из которых доступно на 5 языках: английском, испанском, французском, немецком и русском. Средняя длина английских предложений составляет 93 символа со стандартным отклонением 25 символов и средней длиной 82 символа.

Используя технологию преобразования текста в речь Google WaveNet, я создал аудиофайл для каждого неанглоязычного предложения. Эти аудиофайлы подходят для использования с Whisper как для транскрипции, так и для перевода.

Я выбрал три решения для машинного перевода:

  1. MarianMT — это набор моделей перевода, доступных для бесплатного использования. Здесь вы можете найти полный список моделей. Я использовал большие модели (размером ~550 МБ): Helsinki-NLP/opus-mt-tc-big-cat_oci_spa-en для испанского языка (эта модель также работает с каталонским и окситанским языками); Helsinki-NLP/opus-mt-tc-big-fr-en для французского языка; Helsinki-NLP/opus-mt-tc-big-gmw-gmw для немецкого языка (переводится между всеми западногерманскими языками: английским, немецким, голландским, африкаанс, нижненемецким, шотландским, фризским, древнеанглийским и другими); Helsinki-NLP/opus-mt-tc-big-zle-en для русского языка (а также для украинского и белорусского языков)
  2. GoogleTranslate, имеющий коммерческий API (стоимостью 20 долларов за миллион символов)
  3. DeepL, который также имеет коммерческий API (цена аналогична GoogleTranslate)

Затем я измерил качество перевода для 7 сценариев:

  1. Whisper: я позвонил Whisper для перевода (X→английский) напрямую
  2. Whisper + MarianMT: сначала я расшифровал речь с помощью Whisper, а затем перевел результаты с помощью MarianMT.
  3. MarianMT: Я перевел предложение напрямую с MarianMT. Этот сценарий, очевидно, будет иметь лучшие результаты, чем предыдущий, потому что мы вообще не имеем дело со звуком; разница будет вызвана ошибками распознавания речи
  4. Whisper + GoogleTranslate: сначала я расшифровал речь с помощью Whisper, а затем перевел результаты с помощью GoogleTranslate.
  5. GoogleTranslate: я перевел предложение напрямую с помощью GoogleTranslate
  6. Whisper + DeepL: сначала я расшифровал речь с помощью Whisper, а затем перевел результаты с помощью DeepL.
  7. DeepL: Я перевел предложение напрямую с DeepL

Я измерил сходство между переводом каждого неанглоязычного предложения в каждом сценарии с его английской версией, используя 2 метрики:

  1. BLEU score, который рассчитывается на основе долей правильно переведенных n-грамм (n от 1 до 4). Эта эвристическая мера очень хорошо коррелирует с тем, как люди воспринимают качество перевода.
  2. Косинусное расстояние между вложениями предложений с использованием BERT-подобной модели all-mpnet-base-v2 из библиотеки sentence-transformers

Для каждой пары (сценарий, исходный язык) я рассчитал средневзвешенное значение (вес равен длине предложения) этих двух показателей по всем предложениям.

Я получил следующие результаты:

Однако предложения, использованные в этом тесте, были довольно короткими, и поэтому их было легко перевести. Что произойдет, если мы будем использовать более длинные предложения?

Во втором тесте я выбрал 400 более длинных предложений из Татоэба: их медиана длины — 226 символов, средняя длина — 261 символ при стандартном отклонении 106 символов. На этот раз списки предложений для разных языков отличались друг от друга (потому что трудно найти длинные предложения, каждое из которых доступно на всех 5 языках), поэтому мы не можем напрямую сравнивать качество перевода для разных языков.

Результаты оказались несколько неожиданными: Whisper выглядит лучше по метрике BERT, тогда как Whisper+Marian лучше по метрике BLUE. Кроме того, это отношение переворачивается, если мы рассматриваем конкретно немецкий язык.

Каковы основные выводы из этих графиков?

  1. Если вы можете позволить себе отдельную модель перевода, доступную через коммерческий API, она, вероятно, даст лучшие результаты, чем прямой перевод Whisper.
  2. Если вы не можете, то на самом деле сложно сказать, что лучше, так как качество перевода зависит от того, какие типы предложений вы используете, а также от исходного языка аудио.
  3. Ошибки транскрипции шепотом снижают качество, но ненамного: разница в качестве между сценариями 2–3, 4–5 и 6–7 примерно такая же, как между MarianMT и GoogleTranslate.
  4. Существуют заметные различия в качестве перевода между разными языками: испанский всегда легче всего перевести, за ним следуют французский, немецкий и затем русский.

Обнаружение языка

Если вы не укажете язык для метода transcribe, Whisper определит язык аудио на основе первых 30 секунд.

Однако что, если первые 30 секунд не включают реальную речь? В этом случае результаты определения языка будут случайными. Это кажется ненадежным.

Я реализовал более точное решение. Он берет указанное количество выборок из аудио в случайных местах и ​​определяет вероятность для каждого языка в каждой выборке. Затем он возвращает язык с наибольшей средней вероятностью по всем образцам.

import whisper
from collections import defaultdict
import random

def detect_language(audio_file_path: str, whisper_model_name: str, samples_number=5):
    # load audio
    audio = whisper.load_audio(audio_file_path)

    # load the Whisper model
    model = whisper.load_model(whisper_model_name, download_root="models")

    # optimization: if the audio length is <= Whisper chunk length, then we will only take 1 sample
    if len(audio) <= whisper.audio.CHUNK_LENGTH * whisper.audio.SAMPLE_RATE:
        samples_number = 1

    probabilities_map = defaultdict(list)
    
    for i in range(samples_number):
        # select a random audio fragment
        random_center = random.randint(0, len(audio))
        start = random_center - (whisper.audio.CHUNK_LENGTH // 2) * whisper.audio.SAMPLE_RATE
        end = random_center + (whisper.audio.CHUNK_LENGTH // 2) * whisper.audio.SAMPLE_RATE
        start = max(0, start)
        start = min(start, len(audio) - 1)
        end = max(0, end)
        end = min(end, len(audio) - 1)
        audio_fragment = audio[start:end]
        
        # pad or trim the audio fragment to match Whisper chunk length
        audio_fragment = whisper.pad_or_trim(audio_fragment)

        # extract the Mel spectrogram and detect the language of the fragment
        mel = whisper.log_mel_spectrogram(audio_fragment)
        _, _probs = model.detect_language(mel)
        for lang_key in _probs:
            probabilities_map[lang_key].append(_probs[lang_key])

    # calculate the average probability for each language
    for lang_key in probabilities_map:
        probabilities_map[lang_key] = sum(probabilities_map[lang_key]) / len(probabilities_map[lang_key])

    # return the language with the highest probability
    detected_lang = max(probabilities_map, key=probabilities_map.get)
    return detected_lang

Улучшения

Я внедрил программное обеспечение, которое генерирует субтитры для аудиофайла с помощью Whisper. Мое решение также включает в себя некоторые улучшения для повышения общего качества генерируемых субтитров.

Обнаружение голосовой активности

Whisper представляет собой комбинацию акустических и языковых нейронных сетей. Когда речь смешивается с не-речью, Whisper иногда может сильно запутаться — это вызывает дегенерацию нейронного текста и десинхронизацию. Чтобы предотвратить это, лучше передавать Whisper фрагменты аудио, которые содержат только речь.

Для этого применяется алгоритм обнаружения голосовой активности. Результатом алгоритма VAD является последовательность интервалов, предположительно содержащих только речь. Сейчас я использую для этого нейросеть Brouhana.

Исправление текстовых аномалий

Иногда (обычно при неестественной речи, такой как громкие крики) линия, генерируемая Whisper, может быть заполнена повторяющимся шаблоном (например, AAAAAAAAAAAAAAAAAAAAAA…). Довольно часто такая строка будет охватывать сегмент аудио, который также содержит некоторую обычную речь, эффективно удаляя субтитры для последней. Я называю эти случаи «текстовыми аномалиями».

Я разработал решение для устранения этой проблемы:

  1. Во-первых, я обнаруживаю текстовые аномалии с помощью эвристического алгоритма и удаляю их из субтитров.
  2. Затем я генерирую новые субтитры для фрагмента, который ранее был покрыт аномалией. Чтобы аномалия не появлялась снова, я итеративно сдвигаю начало фрагмента вперед до тех пор, пока в результате не будет аномалии

Перевод субтитров

Перевод субтитров представляет собой проблему: если мы будем переводить каждую строку субтитров по отдельности, то общее качество перевода будет низким, потому что модель перевода не имеет достаточного контекста.

Рассмотрим пример: немецкое предложение «Eine Katze hatte Bekanntschaft mit einer Maus gemacht». означает «Кошка познакомилась с мышью», и это именно то, что выводит Google Translate. Однако представьте, если бы это предложение было разделено на три части: «Eine Katze hatte», «Bekanntschaft mit einer» и «Maus gemacht». «Eine Katze hatte» переводится как «была кошка», «Bekanntschaft mit einer» переводится как «знакомство с одним» и «Maus gemacht». становится «сделано мышью». Если сложить их вместе, получится «познакомился кот с одной мышкой». что звучит плохо.

Я разработал решение этой проблемы. Мой алгоритм сначала группирует строки субтитров в большие блоки текста. Эти блоки затем передаются в модель перевода, поэтому модель имеет много контекста и может работать хорошо. Затем мы разделяем полученные тексты на небольшие фрагменты, соответствующие исходным строкам субтитров. Этот алгоритм разделения основан на обработке вложений токенов LaBSE.

Веб-приложение YouTube Subtitles

Я разработал веб-приложение, в котором можно смотреть видео на YouTube с субтитрами, созданными моим алгоритмом на основе Whisper.

Главная страница

Я обработал много видео с нашим алгоритмом, сформировав этот каталог. На главной странице вы можете осуществлять поиск по каталогу и находить видео, которые вам нравятся.

Видео можно искать по:

  1. Релевантность поисковому запросу
  2. Оригинальный язык видео. Существует также опция «Любой», которая доставит вам видео на всех языках.
  3. Режим субтитров: оригинальные, переведенные на ваш родной язык (который можно изменить в настройках) или двойные субтитры.

Нажав на видео, вы перейдете на страницу с видео.

Страница видео

На странице видео есть встроенный проигрыватель YouTube, поверх которого отображаются субтитры.

Страница запроса

На странице запроса можно запросить видео для обработки моим сервером и добавления в каталог.

Ваш запрос будет добавлен в очередь на обработку, вы будете перенаправлены на страницу с видео. Если вы вернетесь на эту страницу через некоторое время, там будут сгенерированные субтитры. Однако имейте в виду, что создание и перевод субтитров займет некоторое время (видео продолжительностью 1 час будет обрабатываться на текущем процессорном сервере 2 часа; кроме того, могут быть другие запросы в очереди перед вашим). Если в видео уже есть субтитры, написанные человеком, сервер просто подтянет их (что займет гораздо меньше времени).

Контакты

Если у вас есть какие-либо вопросы или предложения по этому проекту, не стесняйтесь обращаться к нам по электронной почте [email protected].