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

Введение

В нашем быстро меняющемся мире мы генерируем огромное количество аудиоданных. Вспомните свой любимый подкаст или конференц-связь на работе. Данные уже богаты в своей необработанной форме; мы, как люди, можем это понять. Тем не менее, мы могли бы пойти дальше и, например, преобразовать его в письменный формат для последующего поиска.

Для лучшего понимания поставленной задачи введем два понятия. Первый — это транскрипция, просто преобразование разговорной речи в текст. Второй аспект, который мы исследуем в этой статье, — диариза- ция . Диаризация помогает нам придать дополнительную структуру неструктурированному контенту. В данном случае нас интересует отнесение конкретных речевых сегментов к разным говорящим.

В приведенном выше контексте мы решаем обе задачи, используя разные инструменты. Мы используем Whisper, универсальную модель распознавания речи, разработанную OpenAI. Это было обучение на разнообразном наборе данных аудиосэмплов, и исследователи разработали его для выполнения нескольких задач. Во-вторых, мы используем PyAnnotate, библиотеку для диаризации динамиков. Наконец, мы используем WhisperX, исследовательский проект, который помогает совместить эти два решения, устраняя при этом некоторые ограничения Whisper.

Эта статья относится к новой еженедельной серии статей «Хроники больших языковых моделей: Навигация по границам НЛП», в которых рассказывается, как использовать возможности больших моделей для различных задач НЛП. Погружаясь в эти передовые технологии, мы стремимся дать разработчикам, исследователям и энтузиастам возможность использовать потенциал НЛП и открывать новые возможности.

Статьи, опубликованные на данный момент:

  1. Подведение итогов последних выпусков Spotify с ChatGPT
  2. Мастер семантического поиска в масштабе: индексируйте миллионы документов с молниеносным временем вывода с использованием FAISS и преобразователей предложений

Как всегда, код доступен на моем Github.

Whisper: универсальная модель распознавания речи

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

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

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

PyAnnotate: библиотека диаризации динамиков

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

PyAnnotate — это библиотека Python, специально разработанная для поддержки этой задачи. Процесс относительно прост. Он предварительно обрабатывает данные, позволяя нам извлекать функции из необработанного аудиофайла. Затем он создает кластеры похожих речевых сегментов на основе извлеченных признаков. Наконец, он приписывает сгенерированные кластеры отдельным динамикам.

WhisperX: расшифровка длинного аудио с обнаружением голосовой активности и принудительным выравниванием фонем

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

Чтобы устранить эти ограничения, исследовательская группа Оксфорда активно разрабатывает WhisperX. Препринт Arxiv был опубликован в прошлом месяце. Он использует обнаружение голосовой активности (VAD), которое определяет наличие или отсутствие человеческой речи и предварительно сегментирует входной аудиофайл. Затем он вырезает и объединяет эти сегменты в окна примерно по 30 секунд, определяя границы областей с низкой вероятностью речи (выход из модели голоса). У этого шага есть дополнительное преимущество: он позволяет использовать пакетную транскрипцию с Whisper. Это повышает производительность при одновременном снижении вероятности дрейфа или галлюцинаций, о которых мы говорили выше. Последний шаг называется принудительным выравниванием. WhisperX использует модель фонемы для согласования транскрипции со звуком. Автоматическое распознавание речи (ASR) на основе фонем распознает наименьшую единицу речи, например, элемент «g» в «big». Эта операция постобработки выравнивает сгенерированную транскрипцию с временными метками аудио на уровне слов.

Интеграция WhisperX, Whisper и PyAnnotate

В этом разделе мы интегрируем WhisperX, Whisper и PyAnnotate для создания собственной системы ASR. Мы разработали наш подход для обработки длинных аудиотранскрипций, при этом имея возможность сегментировать речь и относить конкретного говорящего к каждому сегменту. Кроме того, это снижает вероятность галлюцинаций, повышает эффективность вывода и обеспечивает правильное согласование транскрипции и звука. Давайте построим конвейер для выполнения различных задач.

Мы начинаем с транскрипции, преобразуя речь, распознанную из аудиофайла, в письменный текст. Функция transcribe загружает модель Whisper, заданную параметром model_name, и расшифровывает аудиофайл. Затем он возвращает словарь, содержащий сегменты расшифровки и код языка. OpenAI разработал Whisper также для определения языка, поскольку он является многоязычной моделью.

def transcribe(audio_file: str, model_name: str, device: str = "cpu") -> Dict[str, Any]:
    """
    Transcribe an audio file using a speech-to-text model.

    Args:
        audio_file: Path to the audio file to transcribe.
        model_name: Name of the model to use for transcription.
        device: The device to use for inference (e.g., "cpu" or "cuda").

    Returns:
        A dictionary representing the transcript, including the segments, the language code, and the duration of the audio file.
    """
    model = whisper.load_model(model_name, device)
    result = model.transcribe(audio_file)

    language_code = result["language"]
    return {
        "segments": result["segments"],
        "language_code": language_code,
    }

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

def align_segments(
    segments: List[Dict[str, Any]],
    language_code: str,
    audio_file: str,
    device: str = "cpu",
) -> Dict[str, Any]:
    """
    Align the transcript segments using a pretrained alignment model.

    Args:
        segments: List of transcript segments to align.
        language_code: Language code of the audio file.
        audio_file: Path to the audio file containing the audio data.
        device: The device to use for inference (e.g., "cpu" or "cuda").

    Returns:
        A dictionary representing the aligned transcript segments.
    """
    model_a, metadata = load_align_model(language_code=language_code, device=device)
    result_aligned = align(segments, model_a, metadata, audio_file, device)
    return result_aligned

Теперь, когда сегменты расшифровки выровнены, мы можем выполнить диаризацию говорящего. Мы используем функцию diarize, которая использует библиотеку PyAnnotate:

def diarize(audio_file: str, hf_token: str) -> Dict[str, Any]:
    """
    Perform speaker diarization on an audio file.

    Args:
        audio_file: Path to the audio file to diarize.
        hf_token: Authentication token for accessing the Hugging Face API.

    Returns:
        A dictionary representing the diarized audio file, including the speaker embeddings and the number of speakers.
    """
    diarization_pipeline = DiarizationPipeline(use_auth_token=hf_token)
    diarization_result = diarization_pipeline(audio_file)
    return diarization_result

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

def assign_speakers(
    diarization_result: Dict[str, Any], aligned_segments: Dict[str, Any]
) -> List[Dict[str, Any]]:
    """
    Assign speakers to each transcript segment based on the speaker diarization result.

    Args:
        diarization_result: Dictionary representing the diarized audio file, including the speaker embeddings and the number of speakers.
        aligned_segments: Dictionary representing the aligned transcript segments.

    Returns:
        A list of dictionaries representing each segment of the transcript, including the start and end times, the
        spoken text, and the speaker ID.
    """
    result_segments, word_seg = assign_word_speakers(
        diarization_result, aligned_segments["segments"]
    )
    results_segments_w_speakers: List[Dict[str, Any]] = []
    for result_segment in result_segments:
        results_segments_w_speakers.append(
            {
                "start": result_segment["start"],
                "end": result_segment["end"],
                "text": result_segment["text"],
                "speaker": result_segment["speaker"],
            }
        )
    return results_segments_w_speakers

Наконец, мы объединяем все шаги в одну функцию transcribe_and_diarize. Эта функция возвращает список словарей, представляющих каждый сегмент расшифровки, включая время начала и окончания, произносимый текст и идентификатор говорящего. Обратите внимание, что для запуска конвейера вам нужен токен Hugging Face API.

def transcribe_and_diarize(
    audio_file: str,
    hf_token: str,
    model_name: str,
    device: str = "cpu",
) -> List[Dict[str, Any]]:
    """
    Transcribe an audio file and perform speaker diarization to determine which words were spoken by each speaker.

    Args:
        audio_file: Path to the audio file to transcribe and diarize.
        hf_token: Authentication token for accessing the Hugging Face API.
        model_name: Name of the model to use for transcription.
        device: The device to use for inference (e.g., "cpu" or "cuda").

    Returns:
        A list of dictionaries representing each segment of the transcript, including the start and end times, the
        spoken text, and the speaker ID.
    """
    transcript = transcribe(audio_file, model_name, device)
    aligned_segments = align_segments(
        transcript["segments"], transcript["language_code"], audio_file, device
    )
    diarization_result = diarize(audio_file, hf_token)
    results_segments_w_speakers = assign_speakers(diarization_result, aligned_segments)

    # Print the results in a user-friendly way
    for i, segment in enumerate(results_segments_w_speakers):
        print(f"Segment {i + 1}:")
        print(f"Start time: {segment['start']:.2f}")
        print(f"End time: {segment['end']:.2f}")
        print(f"Speaker: {segment['speaker']}")
        print(f"Transcript: {segment['text']}")
        print("")

    return results_segments_w_speakers

Оценка производительности интегрированной системы ASR

Давайте начнем с тестирования нашего пайплайна с помощью короткого аудиоклипа, который я записал сам. На видео есть два динамика, которых нам нужно идентифицировать. Кроме того, обратите внимание на несколько неуверенности в речи одного из ораторов, что затрудняет расшифровку. Мы будем использовать базовую модель от Whisper, чтобы оценить ее возможности. Для большей точности вы можете использовать средние или крупные. Транскрипция представлена ​​ниже:

Сегмент 1:
Время начала: 0,95
Время окончания: 2,44
Докладчик: SPEAKER_01
Стенограмма: Какое телешоу вы смотрите?

Сегмент 2:
Время начала: 3:56
Время окончания: 5:40
Докладчик: SPEAKER_00
Стенограмма: Сейчас я смотрю «Это мы».

Сегмент 3:
Время начала: 6:18
Время окончания: 6:93
Докладчик: SPEAKER_01
Стенограмма: О чем речь?

Сегмент 4:
Время начала: 8.30
Время окончания: 15.44
Докладчик: SPEAKER_00
Стенограмма: Речь идет о жизни семьи на протяжении нескольких поколений.

Сегмент 5:
Время начала: 15.88
Время окончания: 21.42
Докладчик: SPEAKER_00
Стенограмма: А можно как-то прожить свою жизнь через сериал.

Сегмент 6:
Время начала: 22.34
Время окончания: 23.55
Докладчик: SPEAKER_01
Стенограмма: Что будет дальше?

Сегмент 7:
Время начала: 25:48
Время окончания: 28:81
Докладчик: SPEAKER_00
Стенограмма: Может быть, говядина Я слышал об этом очень хорошие отзывы.

Время выполнения для базы: 8,57 секунды
Использование памяти для базы: 3,67 ГБ

Наш подход достигает своих основных целей с помощью приведенной выше транскрипции. Во-первых, обратите внимание, что транскрипция точна и что мы можем успешно игнорировать колебания речи. Мы подготовили текст с правильным синтаксисом, что способствует удобочитаемости. Сегменты были хорошо разделены и правильно выровнены с отметками времени аудио. Наконец, диаризация говорящего также была выполнена адекватно, причем два говорящих точно соотносились с каждым речевым сегментом.

Другим важным аспектом является эффективность вычислений различных моделей для длинноформатного аудио при выполнении логических выводов на ЦП и ГП. Мы выбрали аудиофайл продолжительностью около 30 минут. Ниже вы можете найти результаты:

Главный вывод заключается в том, что эти модели очень тяжелые и должны быть более эффективными для работы в масштабе. Для 30-минутного видео нам требуется около 70–75 минут для запуска транскрипции на ЦП и примерно 15 минут на графическом процессоре. Кроме того, помните, что нам нужно около 10 ГБ видеопамяти для запуска большой модели. Мы должны ожидать этих результатов, поскольку модели все еще находятся в стадии исследования.

Заключение

В этой статье представлено подробное пошаговое руководство по анализу аудиоданных с использованием современных технологий распознавания речи и диаризации говорящего. Мы представили Whisper, PyAnnotate и WhisperX, вместе сформировав мощную интегрированную систему ASR — наш подход дает многообещающие результаты при работе с длинными аудиотранскрипциями. Это также устраняет основные ограничения Whisper, связанные с галлюцинациями на длинных аудиотранскрипциях, обеспечивая согласование между транскрипцией и аудио, точную сегментацию речи и приписывание говорящих каждому сегменту.

Тем не менее, вычислительная эффективность этих моделей остается проблемой, особенно для длинноформатного звука и при выполнении логических выводов на ограниченном оборудовании. Тем не менее, интеграция Whisper, WhisperX и PyAnnotate демонстрирует потенциал этих инструментов для преобразования способов обработки и анализа аудиоданных, открывая новые возможности для приложений в различных отраслях и вариантах использования.

Оставайтесь на связи: LinkedIn