Утилита называется yt-dlp, а не
yt-dl. Оригинальныйyoutube-dlфактически заброшен (последний значимый релиз — конец 2021) и регулярно ломается на актуальном YouTube из-за изменений в плеере. Активный форк —yt-dlp, drop-in замена с тем же синтаксисом плюс существенные расширения. Везде ниже имеется в виду он.
Архитектура: что вообще происходит при извлечении субтитров
yt-dlp состоит из набора extractor'ов (по одному на сайт) и слоя
post-processor'ов. При запросе субтитров extractor парсит страницу/плеер YouTube,
находит ссылки на дорожки субтитров и скачивает их в том формате, который отдаёт сам
сайт. Для YouTube это VTT (WebVTT) или внутренний srv3/json3; формат srt
YouTube напрямую не отдаёт — его yt-dlp получает конвертацией через ffmpeg
(post-processor --convert-subs).
Из этого следуют два практических факта:
--sub-format srtне гарантирует srt напрямую. yt-dlp скачает доступный формат (обычно vtt) и сконвертирует. Поэтому для конвертации нужен установленный ffmpeg.- Различают два типа дорожек: загруженные автором (
--write-subs, ключsubtitles) и автоматически сгенерированные распознаванием речи (--write-auto-subs, ключautomatic_captions). Это разные сущности — у большинства YouTube-роликов есть только вторые. Для полноты обычно запрашивают оба типа.
Базовые операции
Сначала всегда полезно посмотреть, какие дорожки вообще есть, не скачивая ничего:
yt-dlp --list-subs "https://www.youtube.com/watch?v=jNQXAC9IVRw"
Вывод разделён на Available subtitles (ручные) и Available automatic captions
(автогенерация, обычно десятки языков, многие — машинный перевод).
Скачать субтитры без видео:
# ручные + авто, английский, в исходном формате (vtt), без видео
yt-dlp --skip-download --write-subs --write-auto-subs --sub-langs en \
"https://www.youtube.com/watch?v=jNQXAC9IVRw"
Ключевые опции:
--skip-download— не качать сам медиафайл (для текста — всегда).--write-subs/--write-auto-subs— ручные / автоматические дорожки.--sub-langs en,ru— список языков.all— всё;en.*— все варианты английского (напримерen-US,en-orig);en-origу YouTube означает оригинальную дорожку до перевода.--sub-format vtt/srt/best— желаемый формат (для YouTube реально доступны vtt/srv*).--convert-subs srt— пост-конвертация в srt/ass/lrc/vtt через ffmpeg.-o/--output— шаблон имени файла (см. ниже).
Файл получит имя по шаблону %(title)s [%(id)s].%(ext)s, ext будет вида en.vtt.
Выбор языка: оригинал, а не перевод
Ключевое различие — между оригинальной дорожкой и машинным переводом. YouTube
делает автоматическое распознавание речи (ASR) на языке оригинала, а любой другой язык
в списке доступных автодорожек генерирует машинным переводом этой дорожки. То есть для
англоязычного ролика --sub-langs ru даст текст, дважды прогнанный через автоматику:
сначала ASR со своими ошибками, затем машинный перевод поверх этих ошибок. Качество
деградирует на каждом шаге.
Отсюда правило: всегда бери дорожку на языке оригинала, а не перевод под удобный язык. Для LLM это вдвойне верно — модель свободно анализирует и английский, и русский на входе, а качество анализа определяется качеством исходного текста, а не его языком. Чистый оригинал лучше зашумлённого машинного перевода. Язык результата задаётся промптом к модели и от языка транскрипта не зависит.
Практически: для русскоязычного ролика оригинал — это ru, для англоязычного — en;
машинный перевод (ru поверх английского ролика) не брать никогда. YouTube помечает
оригинальную автодорожку суффиксом -orig, поэтому при неизвестном заранее языке можно
перечислить приоритеты — yt-dlp возьмёт первый доступный из списка:
yt-dlp --skip-download --write-auto-subs --sub-langs "en-orig,en,ru-orig,ru" \
--sub-format json3 -o "%(id)s.%(ext)s" "URL"
Это работает, но хрупко на разноязычных каналах: порядок приоритетов фиксирован. Для
надёжного выбора оригинала язык определяют программно по метаданным (поле
automatic_captions, дорожка с суффиксом -orig) — но это уже задача твоего скрипта.
Отдельный приоритет — субтитры, залитые автором (subtitles, не
automatic_captions). Если они есть, бери их раньше любой автогенерации, включая
оригинальный ASR: они вычитаны человеком и качественнее. Запрос обоих типов
(--write-subs --write-auto-subs) даёт yt-dlp выбрать ручные, когда они доступны.
Получение чистого текста без тайм-кодов
Это твой основной сценарий, и здесь есть подводный камень. Сырой VTT от YouTube
непригоден для прямого grep-удаления тайм-кодов. Автосубтитры YouTube используют
эффект "roll-up": каждая реплика дублируется в нескольких соседних cue, а внутри строк
стоят инлайн-теги тайминга по словам (<00:00:01.234><c> word</c>). Наивная фильтрация
тайм-кодов даст текст с массой повторов.
Вариант 1 — рекомендуемый: srv3/json3 как источник
YouTube отдаёт формат json3 (он же srv3), где текст структурирован и не содержит
roll-up-дублей. Самый чистый путь — скачать именно его и собрать текст собственной
постобработкой:
yt-dlp --skip-download --write-auto-subs --sub-langs en --sub-format json3 \
-o "transcript" "https://www.youtube.com/watch?v=jNQXAC9IVRw"
Структура файла: объект с массивом events, в каждом событии — массив segs, где
полезный текст лежит в поле utf8. Чтобы получить связный текст, достаточно пройти по
events[].segs[].utf8, отбросить пустые сегменты и склеить с нормализацией пробелов и
переносов. Никакой временнóй разметки в результате не остаётся — это и есть оптимальный
вход для LLM. (Сам разбор делается отдельным скриптом — здесь он не приводится.)
Вариант 2 — простой: конвертация в srt + чистка
Если json3 по какой-то причине недоступен, работает связка --convert-subs srt плюс
постобработка. yt-dlp при конвертации vtt→srt уже схлопывает roll-up-дубли, поэтому из
srt текст вычищается надёжно:
yt-dlp --skip-download --write-auto-subs --sub-langs en --convert-subs srt \
-o "transcript" "https://www.youtube.com/watch?v=jNQXAC9IVRw"
Получится transcript.en.srt вида:
1
00:00:00,000 --> 00:00:02,500
Hello and welcome to the channel
Чистка в plain text одной командой (удаляем номера, тайм-коды и пустые строки, склеиваем):
sed -E '/^[0-9]+$/d; /-->/d; /^[[:space:]]*$/d' transcript.en.srt \
| tr '\n' ' ' | sed -E 's/[[:space:]]+/ /g' > transcript.txt
Разбор фильтров sed: /^[0-9]+$/d убирает строки-номера cue, /-->/d — строки
тайм-кодов, /^[[:space:]]*$/d — пустые. Затем tr склеивает переносы в пробелы и
финальный sed схлопывает кратные пробелы.
Вариант 3 — встроенный downloader без ffmpeg
Если ffmpeg ставить не хочешь, у автодорожек YouTube часто доступен формат vtt, но
для чистого текста его всё равно надо обработать. Тогда проще json3 (вариант 1) —
ffmpeg для него не нужен, обработка чисто текстовая.
Вывод по форматам для LLM: бери json3 (вариант 1) — это самый устойчивый к
дублям путь и без зависимости от ffmpeg. srt-связка (вариант 2) — хорошая запасная,
когда хочется одной строкой и ffmpeg уже есть. Чистого --sub-format txt, который бы
сразу давал готовый текст без тайм-кодов, у yt-dlp нет — постобработка неизбежна.
Пакетная обработка канала
Для твоей задачи (LLM по содержимому каналов) обычно нужен не один ролик, а весь канал или плейлист. yt-dlp принимает URL канала/плейлиста напрямую и обходит все видео.
yt-dlp --skip-download --write-auto-subs --sub-langs en --sub-format json3 \
-o "%(channel)s/%(upload_date)s_%(id)s.%(ext)s" \
"https://www.youtube.com/@channelname/videos"
Полезное при массовом обходе:
--download-archive archive.txt— ведёт журнал уже обработанных id; повторный запуск скачивает только новые видео. Это база для инкрементального обновления.--sleep-requests 1и--min-sleep-interval/--max-sleep-interval— паузы между запросами, чтобы не словить временную блокировку (HTTP 429) при обходе сотен видео.--match-filter "duration > 60"— отсев, например, Shorts.-I 1:50(--playlist-items) — срез по диапазону.--lazy-playlist— начинать обход, не дожидаясь полного разбора плейлиста.
Только метаданные без скачивания чего-либо (заголовки, описания, длительности — пригодится для индексации перед тем как качать субтитры):
yt-dlp --skip-download --print "%(id)s\t%(upload_date)s\t%(title)s" \
"https://www.youtube.com/@channelname/videos" > index.tsv
Эксплуатационные нюансы
- Свежесть версии критична. YouTube периодически меняет формат плеера, и устаревший
yt-dlp отваливается с ошибками извлечения. Самообновляющаяся установка:
yt-dlp -U. Установка из pip:pip install -U yt-dlp. Релизы выходят примерно раз в месяц (последний на сентябрь 2026 —2026.08.19), а рядом живёт nightly-ветка с более частыми фиксами extractor'ов. - Безопасность. За 2026 год закрыты две инъекции произвольных команд: CVE-2026-26331
через
--netrc-cmd(исправлено в2026.02.21) и CVE-2026-55404 через недостаточную санитизацию вывода--write-link(исправлено в2026.08.19). Ещё одна причина не сидеть на старой версии. - Блокировки и "Sign in to confirm you're not a bot". При активном обходе YouTube
может требовать аутентификацию. Решается передачей cookies:
--cookies-from-browser firefoxили--cookies cookies.txt. Не злоупотребляй частотой запросов с залогиненного аккаунта. - ffmpeg как зависимость. Нужен для
--convert-subsи любой пост-конвертации. Для пути через json3 не требуется. - Кодировки. json3 и vtt от YouTube — UTF-8. При последующей обработке в Windows-окружении явно работай в UTF-8, иначе кириллица и спецсимволы поедут.
Итог
Для подготовки текста под LLM оптимальный путь — скачивать субтитры в формате json3
и собирать текст из структуры events[].segs[].utf8 собственной постобработкой, получая
связный текст без тайм-кодов и без roll-up-дублей, без зависимости от ffmpeg. srt-связка
с чисткой через sed — надёжная запасная при наличии ffmpeg. По языку: всегда бери
оригинальную дорожку (для русскоязычных каналов ru, для англоязычных en), приоритет
ручным субтитрам автора над автогенерацией, и никогда — машинный перевод; язык ответа
задаётся промптом к модели. Для каналов обязательно --download-archive для
инкрементальности и троттлинг запросов против блокировок.
Связанные заметки
- Медиасервер: Transmission + Sonarr/Radarr + Plex — смежный сценарий работы с медиа
- Локальный инференс LLM: движки, квантование, бюджет памяти — что происходит с этим текстом дальше: контекстное окно и его цена
Из библиотеки института уносят только знания. Читателей здесь не считают: посещение не регистрируется, отметок в издании не остаётся, счётчиков нет ни у одного издания фонда.
Издание пополняется и пересверяется. Текст доступен на условиях CC BY-SA 4.0 — унесённое можно передавать дальше на тех же условиях.