ChatGPT сейчас на хайпе, но я тут решил немного поиграть в другой продукт от Open AI — Whisper — который умеет распознавать голос на куче языков и превращать их в текст.
Сначала я просто потрогал через curl их API, потом я моргнул, и через два дня у меня появился инструмент, который может локально прямо на макбуке распознать аудиозапись звонка и разметить в нем разных спикеров. Хочу в этом посте рассказать как самому сделать так же.
Картинка с финальным результатом для привлечения внимания.
Чтобы получить такую же, нужно выполнить следующие шаги. Все выполнялось на MacBook Pro M1 Pro 32 Gb c macOS Ventura 13.2.1.
0. Настройка окружения
Для работы понадобятся Python3.10, git и clang.
Python3.10 уже есть в поставке вместе с macOS. Чтобы установить git и clang (если у вас их еще нет), выполните команду xcode-select --install
.
Теперь нужно настроить виртуальное окружение для Python, куда будем ставить все пакеты и библиотеки. Для этого выполните следующие команды:
python3.10 -m venv whisper && cd whisper
source bin/activate
1. Установка whisper.cpp
whisper.cpp — реализация Whisper на C++. Стоит использовать именно ее, а не оригинальный Whisper от OpenAI, так как она значительно быстрее работает. При этом сами модели нейронных сетей используются те же, что и у OpenAI.
Скачиваем репозиторий с whisper.cpp, собираем программу и скачиваем самую большую (large-v1) модель от OpenAI:
git clone https://github.com/ggerganov/whisper.cpp.git && cd whisper.cpp
make
./models/download-ggml-model.sh large-v1
Уже на этом шаге можно попробовать расшифровать аудиозапись в текст, выполнив следующую команду
./main -m models/ggml-large-v1.bin -l ru --no-timestamps -f ~/output.wav -of output -otxt
Параметры означают следующее:
-m
— путь до файла с моделью-l
— язык--no-timestamps
— не выводить временные метки в расшифровки (оставить только текст)-f
— путь до аудиофайла в формате wav-of
— имя файла с расшифровкой (без расширения!)-otxt
— вывод в формате txt (текстовый файл)
Если ваш аудиофайл не в формате wav, то его можно сконвертировать при помощи утилиты ffmpeg:
ffmpeg -i audio1470766962.m4a -ar 16000 output.wav
2. Устанавливаем библиотеки для распознавания спикеров
Чтобы разметить аудиофайл на сегменты с речью каждого спикера в отдельности, понадобятся следующие:
- pywhispercpp — Python-бингдинги к whispercpp, чтобы можно было использовать быстрое применение моделей на плюсах прямо из питона.
- pyannote-audio — набор библиотек для разделения аудио-потока на сегменты и для распознавания в нем отдельных спикеров.
- pyannote-whisper — обвязка вокруг pyannote-audio, чтобы использовать обученные языковые модели от Whisper.
Чтобы все это установить, выполняем следующие команды:
pip3 install openai-whisper pywhispercpp pyannote-audio
Скорее всего установка pyannote-audio упадет с ошибкой при сборке пакета hmmlearn примерно со следующим текстом
note: This error originates from a subprocess, and is likely not a problem with pip.
error: legacy-install-failure
× Encountered error while trying to install package.
╰─> hmmlearn
note: This is an issue with the package mentioned above, not pip.
hint: See above for output from the failure.
Поэтому дальше зависимости придется доустанавливать вручную при помощи следующих команд:
pip3 install pytorch_lightning==1.6 torch-audiomentations==0.11.0 asteroid-filterbanks==0.4 pyannote.metrics==3.2 pyannote.pipeline==2.3 speechbrain torchaudio==2.0.0 torch==2.0.0 hmmlearn==0.2.6
pip3 install pyannote.audio --no-deps
Наконец скачиваем pyannote-whisper:
git clone https://github.com/yinruiqing/pyannote-whisper.git && cd pyannote-whisper
3. Настраиваем модель для сегментации аудиофайла
Теперь нужно скачать модель от pyannote-audio, которая будет разбирать аудиофайл на сегменты и файл конфигурации модели. Для этого выполните следующие шаги:
- Зарегистрируйтесь на сайте HuggingFace
- Скачайте файл с моделью segmentation/pytorch_model.bin
- Скачайте файл конфигурации conifig.yaml
- Сохраните оба файла в директорию
pyannote-whisper
- Отредактируйте в файле
conifig.yaml
следующие поля
pipeline.params.embedding_batch_size
установите в 1pipeline.params.segmentation
укажите имя файлаpytorch_model.bin
В результате файл config.yaml должен выглядеть следующим образом:
pipeline:
name: pyannote.audio.pipelines.SpeakerDiarization
params:
clustering: AgglomerativeClustering
embedding: speechbrain/spkrec-ecapa-voxceleb
embedding_batch_size: 1 # уменьшение с 32 до 1 внезапно значительно ускоряет процесс, подсказка найдена в issues на гитхабе
embedding_exclude_overlap: true
segmentation: pytorch_model.bin # имя файла с моделью
segmentation_batch_size: 32
params:
clustering:
method: centroid
min_cluster_size: 15
threshold: 0.7153814381597874
segmentation:
min_duration_off: 0.5817029604921046
threshold: 0.4442333667381752
4. Выполняем код для расшифровки и разметки аудио
После этого, имея на руках все библиотеки, модели и конфиг, останется только выполнить Python код, который обработает аудиофайл.
Сохраните в директории pyannote-whisper
в файл diarize.py
следующий код.
from pyannote.audio import Pipeline
from pyannote_whisper.utils import diarize_text
from pywhispercpp.model import Model
# Указываем путь до файла с конфигом, он должен быть в той же директории, как сказано на шаге 3.
pipeline = Pipeline.from_pretrained("config.yaml")
# Указываем название модели large-v1 и путь до директории с whisper-моделями из шага 1.
model = Model('large-v1', '/Users/guschin/whisper.cpp/models', n_threads=6)
# Указываем путь до аудио-файл, кторый будем расшифровывать в текст. Путь обязательно абсолютный.
asr_result = model.transcribe("/Users/guschin/audio1470766962.wav", language="ru")
# Конвертация результата в формат, который понимает pyannote-whisper.
result = {'segments': list()}
for item in asr_result:
result['segments'].append({
'start': item.t0 / 100,
'end': item.t1 / 100,
'text': item.text
}
)
# Сегментация аудио-файла на реплики спикеров. Путь обязательно абсолютный.
diarization_result = pipeline("/Users/guschin/audio1470766962.wav")
# Пересечение расшифровки и сегментаци.
final_result = diarize_text(result, diarization_result)
# Вывод результата.
for seg, spk, sent in final_result:
line = f'{seg.start:.2f} {seg.end:.2f} {spk} {sent}'
print(line)
Запустите код следующей командой
python3 diarize.py
В результате работы на экран выведутся сегменты исходного аудиофайла: время начала и конца сегмента в секундах, идентификатор спикера и текст сегмента.
В целом, получившаяся связка позволяет локально расшифровывать звонки и подкасты, что заменяет такие платные сервисы как otter.ai (17 долоров в месяц или 100 за год).
Если кто-то попробует повторить такое у себя и столкнется с проблемами — пишите в комментарии, возможно, я забыл указать какие-то еще мелкие особенности.
Еще из интересного. В Elixir комьюнити недавно выходил туториал как сделать веб приложение с потоковым распознанием речи с локальным Whisper за 15 минут
https://www.phoenixframework.org/blog/whisper-speech-to-text-phoenix
Идея продукта появилась. Бот - "протоколист". Приглашаешь такого бота в зум-звонок, после окончания он всё распознает, потом прогоняет через ChatGPT с промтом "сделай выжимку, тезисами перечисли action items для каждого" и рассылает всем участникам на почту.
Наверное уже есть такое? =)
😱 Комментарий удален его автором...
Ещё вот такое вот есть красивое — https://goodsnooze.gumroad.com/l/macwhisper
Если не париться с обозначением говорящих (или вообще не париться), то можно взять готовое https://github.com/m1guelpf/auto-subtitle и записать субтитры прямо в файл командой вида
ffmpeg -i 1.mp3 -i 1.srt -metadata:s:s:0 language=eng oup.mka
Всплыла потому что комментарии свежие появились
https://github.com/kaixxx/noScribe
Прикольный инструмент, сделанный на тех же технологиях, что и в посте описаны, только появился позже, чем я этот пост написал.
В отличие от других бесплатных инструментов дает возможность большую (и более качественную) модель использовать, что безусловно хорошо
На гитхабе Whisper постоянно публикуют ссылки на новые приложения для распознавания речи https://github.com/openai/whisper/discussions в том числе с удобным графическим интерфейсом, вроде Buzz. Я тоже обратил внимание, что whisper.cpp быстрее, но пока не разобрался, как ей скармливать аудио с компьютера, чтобы в реальном времени распознавать видео с youtube или звонок по ip-телефонии с иностранцем.
Спасибо!
Вот пример https://docs.google.com/document/d/1G4XAzeur6hnud07ZDI3qvHKrU9-J6RofMVZas6SS-uA/edit
распознал подкаст и вычитал результат
я там специально правки делал в режиме рецензирования, чтобы качество распознавания можно было оценить.
У кого ошибка
ModuleNotFoundError: No module named 'speechbrain.pretrained'
Вот issue по ней
https://github.com/speechbrain/speechbrain/issues/2436
В файле
lib/python3.11/site-packages/pyannote/audio/pipelines/speaker_verification.py переименовать speechbrain.pretrained в speechbrain.inference
А какая часть этого пайплайна обеспечивает такую красивую пунктуацию на выходе?
Микрофон - это же чтобы расшифровывать, что я говорю. Я хочу захватывать любой источник звука на компьютере и расшифровывать его.
Мне очень нравится, что в MS Teams есть встроенная функция транслитерации и перевода речи собеседников на лету. Я хочу примерно то же самое для ip-звонилки. Я пробовал всякие готовые решения, они работают, но очень медленно, отставая примерно на пару предложений.
Насколько реально это прикрутить для рил-тайма, хватит ли на это M1 Pro?
Попробовал на M2 Pro, завелось с небольшими поправками.
При запуске столкнулся с ошибкой
brew install libsndfile
не помогло. Точнее, sndfile поставился, но не туда :) После копирования вручную в папку где он пытался искать (/Users/igor/.pyenv/versions/3.10.10/lib/python3.10/site-packages/_soundfile_data/libsndfile.dylib
) заработало прекрасно.всё? это счастье пролетит мимо меня? M2, RAM 8Gb
Я по инструкции распознавал это весной, но сейчас столкнулся с проблемой: при запуске diarize.py меня встречает вот такая ошибка.
Feature extraction using pretrained models are not available because something went wrong at import: "cannot import name 'SafeFunction' from 'joblib._parallel_backends' (/usr/local/lib/python3.11/site-packages/joblib/_parallel_backends.py)". Traceback (most recent call last): File "/Users/burivuh26/pyannote-whisper/diarize.py", line 6, in <module> Pipeline = pipeline.from_pretrained("config.yaml") ^^^^^^^^^^^^^^^^^^^^^^^^ AttributeError: module 'pyannote.audio.pipeline' has no attribute 'from_pretrained'
что нужно тут поправить?
Раз это работает в реал тайме, и есть модели которые переводят на другой язык сохраняя голос (видел какую то превьюшку в линкедине), то мы в шаге от снятия речевого барьера, верно?
есть уже такие решения?
Upd: что-то я на радостях затупил. Структура языков то разная. Так что рил тайм вряд ли
Что-то падает постоянно, с ошибкой:
А как установить этот speechbrain с нужным embedding-ом не пойму.
никто не знает, заработал ли сабж на v3 модели? Или может есть что-то, что работает локально на v3?
Заранее спасибо.