Полное руководство по созданию AI-помощника для краткого изложения видео на YouTube — Часть 1

Исчерпывающее руководство по созданию ИИ-помощника для описания видео на YouTube — Часть 1

Транскрибируйте YouTube видео с помощью модели Whisper от OpenAI

Изображение, созданное автором с помощью Playground.ai

Эта статья является первой в серии из трех блогов, в которых пошагово объясняется, как я создал AI-помощника для подведения итогов видео на YouTube. Мы начинаем эту серию с подробными инструкциями по получению транскрипции видео на YouTube с использованием Whisper от OpenAI, модели голоса в текст с открытым исходным кодом. В следующем посте мы рассмотрим основы суммирования текста с помощью Langchain и подробные инструкции по реализации конвейера суммирования на основе Falcon-7b-instruct, модели языка с настройкой на инструкции с открытым исходным кодом. В последнем посте мы увидим, как продемонстрировать прототип решения с использованием Gradio и Hugging Face Spaces. На протяжении этих постов мы оцениваем различные архитектурные варианты для реализации каждого шага.

Вступление

Представьте себе: Вы ищете видео, содержащее информацию по конкретной теме, которая вам интересна. Быстрый поиск на YouTube засыпает ваш экран увлекательными эскизами и интригующими названиями видео. Большинство людей инстинктивно начинают пролистывать, сканируя идеальное нажимаемое драгоценное камень. Однако, насколько часто вы оказываетесь пролистывая видео, надеясь, что оно содержит ответ на ваши пылающие вопросы? Если вы похожи на меня, такая ситуация разворачивается слишком часто, и это не только трата времени, но и невероятно раздражает!

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

Для создания этого инструмента я использовал модель большого языка Falcon. И вот интересная аналогия: подобно тому, как сокол грациозно парит на больших высотах, одновременно обладая способностью увеличить масштаб любого интересующего объекта, наш инструмент на базе Falcon дарит пользователям общий обзор контента и легко переходит в детальное исследование с помощью полного транскрипта! 🙂

Вы можете спросить: “Но существуют же онлайн-сервисы, которые уже делают это?” И вы будете абсолютно правы! Однако:

  1. Они часто имеют ограничения по количеству использований, что может привести к дополнительным расходам.
  2. Я хотел иметь больше контроля над создаваемыми резюме, с возможностью установки параметров в соответствии с моими конкретными потребностями.
  3. Как говорится, “Радость в самом путешествии!”

Итак, я взял дело в свои руки и разработал приложение, которое принимает URL видео на YouTube в качестве входных данных и предоставляет краткое резюме. Довольно круто, правда?

Снимок пользовательского интерфейса приложения, размещенного на Hugging Face Spaces — Изображение автора

План решения

Движущиеся части под капотом выполняют следующие задачи:

  1. Получите транскрипцию с YouTube, если она доступна. В противном случае транскрибируйте видео с помощью модели перевода голоса в текст (Whisper) на Hugging Face.
  2. Суммируйте транскрипцию с помощью методов маппинга и редукции с использованием Langchain и модели большого языка, настроенной на подчинение инструкциям (Falcon-7b-instruct) на Hugging Face.
  3. Предоставьте приятный пользовательский интерфейс с помощью Gradio, который позволяет пользователям взаимодействовать с моделью, генерировать и просматривать резюме одновременно с видео.
Общая схема архитектуры решения — Изображение автора

При реализации каждого этапа я попробовал различные архитектурные альтернативы. Например, я реализовал каждый шаг в двух вариантах: вывод на основе локальных ресурсов vs вывод в облаке. Или, когда речь идет о размещении приложения, я попробовал варианты размещения на основе локальных ресурсов vs размещение в облаке на платформе Hugging Face Spaces.

Если что-то из этого вызывает ваше любопытство, следуйте за мной, давайте говорить и учиться друг у друга.

Перед переходом к следующему разделу, я бы порекомендовал быстро ознакомиться с прототипом, который размещен на платформе Hugging Face Spaces. Чувствуйте себя свободно попробовать его и дать мне знать в комментариях, какое у вас первое впечатление.

Шаг 1: Захват транскрипта видео на YouTube

Прежде чем мы сможем суммировать видео, нам нужна его транскрипция в текстовом формате. Хотя транскрипции доступны для многих видео на YouTube, иногда вы можете столкнуться с видео, для которых транскрипция не предоставлена. Если транскрипция доступна, мы просто загружаем ее при помощи youtube_transcript_api и pytube:

from youtube_transcript_api import YouTubeTranscriptApiimport pytube# получаем транскрипт с YouTubedef get_yt_transcript(url):    text = ''    vid_id = pytube.extract.video_id(url)    temp = YouTubeTranscriptApi.get_transcript(vid_id)    for t in temp:        text+=t['text']+' '    return text

Код просто получает идентификатор видео на YouTube из URL и использует YouTubeTranscriptApi для получения объекта транскрипта. Объект транскрипта – это список словарей, каждый из которых содержит текст транскрипта, время начала и длительность показа на видео. Здесь нас интересует только текст.

Но что, если на YouTube нет транскрипта для видео? Теперь вещи становятся еще интереснее…

Транскрипция с использованием Whisper

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

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

from pytube import YouTubeyt = YouTube(str(url))audio = yt.streams.filter(only_audio = True).first()out_file = audio.download(filename="audio.wav",output_path="./docs/youtube/")

Теперь мы готовы использовать Whisper, чтобы прямо взять аудиофайл в качестве входных данных и выполнить его транскрипцию. Сначала мы создаем объект Transformers Pipeline, который загружает модель из HuggingFace:

import transformerswhisper_asr = transformers.pipeline(     "automatic-speech-recognition", model="openai/whisper-large", device_map= 'auto',)

Whisper представлен в различных размерах, от маленькой модели (с 39 миллионами параметров) до большой модели (с 1,55 миллиарда параметров). Я использовал модель whisper-large, чтобы получить наивысшее качество результатов. Когда она была загружена и начала оценку, она занимала 12 ГБ из 16 ГБ памяти моей видеокарты, что было нормально. Однако вы можете выбрать более маленькие версии, если они подходят для вашего случая использования.

Затем нам нужно установить параметры конфигурации модели, включая язык и задачу:

whisper_asr.model.config.forced_decoder_ids = (    whisper_asr.tokenizer.get_decoder_prompt_ids(        language="en",        task="transcribe"    ))

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

Наконец, мы вызываем модель для вывода:

temp = whisper_asr(out_file,chunk_length_s=20)text = temp['text']

Но что такое аргумент chunk_length_s? Модель Whisper предназначена для обработки аудиофайлов с максимальной длиной 30 секунд. Поэтому файл нужно разделить на фрагменты перед передачей его модели. Chunk_length_s просто управляет длиной этих фрагментов.

Собирая все это вместе, код будет выглядеть так:

from pytube import YouTubeimport transformersimport torch# транскрибирует видеоdef transcribe_yt_vid(url):    # загрузка аудио с YouTube    save_dir="./docs/youtube/"    yt = YouTube(str(url))    audio = yt.streams.filter(only_audio = True).first()    out_file = audio.download(filename="audio.wav",                              output_path = save_dir)    # определение конфигурационных параметров модели    whisper_asr = transformers.pipeline(        "automatic-speech-recognition",        model="openai/whisper-large",        device_map= 'auto',    )    whisper_asr.model.config.forced_decoder_ids = (        whisper_asr.tokenizer.get_decoder_prompt_ids(            language="en",            task="transcribe"        )    )    # вызов модели Whisper    temp = whisper_asr(out_file,chunk_length_s=20)    text = temp['text']       # освобождение памяти GPU    del(whisper_asr)    torch.cuda.empty_cache()       return text

OK, Великолепно!!! Но подождите! Что, если у меня недостаточно вычислительной мощности на локальном компьютере и я хочу выполнить вывод в облаке?

Вывод с использованием API HuggingFace Hub

Хорошая новость в том, что HuggingFace позволяет выполнять вывод на их облачной платформе с использованием API HuggingFace Hub.

Вот как это работает:

from HuggingFace_hub import InferenceClient# Инициализация клиента для модели Whisperclient = InferenceClient(model="openai/whisper-large", token="xxxxxxxxxxx")

Вам нужно только передать аргумент token, который можно получить бесплатно от HuggingFace.

Теперь у меня возникла проблема! API вывода обрезал результат по какой-то причине. Я не смог выяснить из онлайн-ресурсов, является ли это ожидаемым поведением или может быть просто ограничением из-за использования бесплатного сервиса. В любом случае, можно обойти эту проблему, разделив аудио на фрагменты перед отправкой их через API вывода. Для этого можно использовать библиотеку librosa для загрузки аудиофайла в формате numpy array, затем разделить его на фрагменты заданной длины, которая не будет обрезаться API (20 секунд подошло для меня), и, наконец, сохранить каждый фрагмент в файл, который затем отправляется через API для вывода:

import librosaimport soundfile as sfx, sr = librosa.load(out_file, sr=None)t=20 # длина фрагмента аудио в секундах# Это даст x в виде аудиофайла в формате numpy array и sr — исходную частоту дискретизации# Аудио нужно разделить на фрагменты по 20 секунд, поскольку API вывода обрезает ответtext = ''for i in range(0, (len(x)//(t * sr)) +1):    y = x[t * sr * i: t * sr *(i+1)]    split_path = save_dir+"audio_split.wav"    sf.write(split_path, y, sr)    text += client.automatic_speech_recognition(split_path)

С помощью этого обходного решения мне удалось транскрибировать длинные видео с помощью API. Однако имейте в виду, что бесплатная подписка ограничивает скорость вывода. Это означает, что если вы слишком часто вызываете API в течение короткого периода времени, вы можете получить ошибку. Хорошая новость в том, что лимит сбрасывается каждый час, так что вам не придется ждать слишком долго, прежде чем снова можно будет протестировать ваш код. Но это также означает, что вы, возможно, не сможете использовать это обходное решение для очень длинных видео!

Конечный результат может выглядеть так:

from pytube import YouTubefrom huggingface_hub import InferenceClient# транскрибирует видео с использованием API Hugging Face Hubdef transcribe_yt_vid_api(url):    # загрузка аудио с YouTube    yt = YouTube(str(url))    audio = yt.streams.filter(only_audio = True).first()    out_file = audio.download(filename="audio.wav",                              output_path = save_dir)       # Инициализация клиента для модели Whisper    client = InferenceClient(model="openai/whisper-large",                       token=os.environ["HUGGINGFACEHUB_API_TOKEN"])    import librosa    import soundfile as sf    text = ''    t=20 # длина фрагмента аудио в секундах    x, sr = librosa.load(out_file, sr=None)    # Это даст x в виде аудиофайла в формате numpy array и sr — исходную частоту дискретизации    # Аудио нужно разделить на фрагменты по 20 секунд, поскольку API вывода обрезает ответ    for i in range(0, (len(x)//(t * sr)) +1):        y = x[t * sr * i: t * sr *(i+1)]        split_path = save_dir+"audio_split.wav"        sf.write(split_path, y, sr)        text += client.automatic_speech_recognition(split_path)    return text

Все вместе

Теперь, чтобы объединить два подхода в одной функции, можно сделать следующее:

def transcribe_youtube_video(url, force_transcribe=False,use_api=False):       yt = YouTube(str(url))    text = ''    # получаем транскрипцию с YouTube, если она доступна    try:        text = get_yt_transcript(url)    except:        print('Транскрипция недоступна, транскрибируем сейчас ...')        pass       # транскрибируем видео, если YouTube не предоставил транскрипцию    # или если вы хотите принудительно выполнить транскрипцию    if text == '' or force_transcribe:        if use_api:            text = transcribe_yt_vid_api(url)        else:            text = transcribe_yt_vid(url)       return yt.title, text

Заключение

Давайте подведем итоги того, что мы рассмотрели в этом посте. Мы создали три разные функции для захвата транскрипции видео на YouTube: первая загружает ее непосредственно с YouTube, вторая транскрибирует ее с использованием модели Whisper от OpenAI на локальном компьютере, а третья делает это через вызовы API Hugging Face Hub. Стоит отметить, что развертывание в производственных средах может потребовать некоторых дополнительных действий. В зависимости от пропускной способности вывода и объема ресурсов, необходимых модели, она может быть размещена на конечной точке. Hugging Face предоставляет услуги конечной точки вывода, где модель развертывается на выделенной и автомасштабируемой инфраструктуре. Мы оставляем эту дискуссию на другой раз.

В следующем посте я расскажу вам о шагах для получения транскрипции и ее кратком изложении с использованием Langchain и Falcon-7b-instruct на платформе HuggingFace.