Блог / Руководство

Как скачать M3U8 / HLS-видео в Chrome

Как скачать M3U8 / HLS-видео в Chrome

Есть простой способ скачать HLS-видео в Chrome: установить MAX Video Downloader (бесплатно) и нажать Скачать на странице с видео.

Вот и всё.

Или можно сделать всё вручную (кто ты, воин?).

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

Я серьёзно, просто установите MAX.

Всё ещё хотите вручную? Отлично. Давайте разберёмся, от чего именно вас спасает кнопка Скачать.

M3U8 – это карта, а не видео

Первая проблема в том, что HLS-видео обычно не лежит на сервере одним удобным видеофайлом, который только и ждёт, пока вы его скачаете.

HLS (HTTP Live Streaming) разбивает медиа на сегменты и описывает их с помощью текстовых плейлистов. Медиаплейлист перечисляет сегменты конкретного потока в порядке воспроизведения. Мастер-плейлист может вести на несколько других плейлистов – для разных качеств видео, аудиодорожек или субтитров. Спецификация HLS описывает эти типы плейлистов и работу URI сегментов.

Поэтому, когда вы находите что-нибудь вроде:

master.m3u8

вполне возможно, что вы нашли инструкцию о том, где найти другие инструкции.

А уже в конце этой цепочки находятся сами медиаданные:

segment001.ts
segment002.ts
segment003.ts
...

Короткое видео может состоять из десятков сегментов. Длинное – из сотен или тысяч, в зависимости от того, как упакован поток. Какого-то полезного фиксированного количества здесь нет.

Схема HLS: мастер-плейлист ведёт к медиаплейлисту, тот – к последовательности сегментов, из которых получается итоговый видеофайл

Если сохранить .m3u8 напрямую и Chrome выдаст крошечный текстовый файл, ничего не сломалось. Вы успешно скачали плейлист. Поздравляю.

Жаль только, что вам было нужно видео.

Значит, теперь нужны сегменты.

Ладно. Скачиваем все сегменты

Когда нужный медиаплейлист уже найден, задача наконец начинает звучать вполне разумно.

Прочитать плейлист, разрешить URL сегментов, скачать каждый указанный фрагмент в правильном порядке, сохранить тайминги и получить из всего этого непрерывный медиапоток.

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

С live HLS появляется ещё одна проблема. Плейлист видео по запросу обычно описывает конечную запись. Live-плейлист может постоянно меняться: новые сегменты появляются, а старые постепенно исчезают из его скользящего окна. В примерах HLS-плейлистов Apple показаны и VOD-, и скользящие live-плейлисты.

Поэтому при записи прямого эфира иногда приходится постоянно следить за обновляющимся плейлистом. Если старый сегмент уже выпал из него и сервер больше его не отдаёт, найденный позже M3U8 этот сегмент обратно не материализует.

Пока терпимо.

Но мы незаметно предположили, что в этих сегментах вообще есть всё необходимое.

Иногда нет.

Видео скачали. Отлично. А звук где?

Мастер-плейлист HLS может описывать несколько вариантов видео и отдельные аудиопотоки. Например, сайт может предлагать видео в 1080p, 720p и 480p, отдельно английскую и японскую аудиодорожки, а заодно ещё и субтитры.

В примерах HLS от Apple как раз встречается такая схема, где видео связано с отдельными аудиодорожками.

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

Ничего не сломалось. Вы скачали видеопоток (а вам ещё и звук нужен?).

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

Эта операция называется мультиплексированием, или muxing.

И нет, это ещё не означает, что видео обязательно придётся конвертировать.

Пожалуйста, не транскодируйте всё подряд

Здесь есть важное различие: «сделать из этих потоков MP4» и «перекодировать это видео» – не одно и то же.

Если видео и аудио уже закодированы кодеками, подходящими для нужного результата, их часто можно просто ремультиплексировать (remux): поместить уже закодированные пакеты в новый контейнер, не декодируя и не кодируя медиа заново.

Схематично:

закодированное видео + закодированное аудио → mux → итоговый файл

Нет никакой необходимости выбрасывать исходное качество только потому, что видео приехало в виде HLS-сегментов.

В FFmpeg это называется streamcopy: пакеты копируются без декодирования и повторного кодирования. Это быстро и сохраняет исходное кодирование потока.

Транскодирование – совсем другая операция:

закодированное видео → декодирование → сырое видео → кодирование → новое закодированное видео

Она требует значительно больше вычислений и, если используется кодек с потерями, может добавить ещё одно поколение потери качества. Транскодирование нужно, когда действительно требуется изменить кодек или преобразовать медиа. Оно не должно быть реакцией по умолчанию на обнаруженный M3U8.

Итак: скачиваем потоки, по возможности сохраняем их исходное кодирование и помещаем в подходящий выходной контейнер.

Легко.

Правда, слово «подходящий» здесь взяло на себя подозрительно много работы.

Расширение файла не умеет договариваться с кодеками

MP4, MKV и WebM – это контейнеры. Они определяют, как медиадорожки и связанная с ними информация упаковываются в файл.

H.264, HEVC, AV1 и VP9 – примеры видеокодеков. AAC и Opus – примеры аудиокодеков.

Это разные уровни одной задачи.

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

Разумный порядок такой:

  1. Сохранить исходные потоки и сделать remux, если целевой контейнер и проигрыватель их поддерживают.
  2. Если с кодеками всё хорошо, но контейнер не подходит, выбрать другой совместимый контейнер.
  3. Транскодировать только тогда, когда этого действительно требует совместимость кодеков.

Да, мы всё ещё просто пытаемся скачать видео с веб-страницы.

И мы пока даже не обсудили, разрешит ли сервер нашему новому загрузчику скачать все эти URL.

Наличие M3U8 ещё не означает наличие доступа к видео

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

Сайт может использовать подписанные URL с ограниченным сроком действия. Запросы сегментов могут зависеть от той же авторизованной сессии, что и сама веб-страница. Сервер может ожидать cookies или заголовки вроде Referer, которые присутствовали, когда видео воспроизводилось в браузере.

Поэтому вполне возможна такая последовательность:

  1. Видео прекрасно воспроизводится в Chrome.
  2. Вы находите M3U8.
  3. Копируете его в другой инструмент.
  4. Сервер отвечает 403 Forbidden.

URL необязательно был неправильным. Просто новый запрос оказался не тем запросом, который делал браузер в рамках авторизованной сессии.

HLS также умеет описывать зашифрованное медиа. Например, EXT-X-KEY может указывать на шифрование AES-128 и содержать информацию, необходимую авторизованному клиенту для получения ключа и расшифровки соответствующих сегментов.

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

Итак, к этому моменту наш невинный проект «скачать видео» уже включает разбор плейлистов, разрешение URL, загрузку сегментов, обновление live-плейлистов, выбор дорожек, запросы с контекстом сессии, возможную расшифровку, muxing, контейнеры, кодеки и, возможно, транскодирование.

Обычно примерно здесь в разговоре появляется FFmpeg.

FFmpeg берёт на себя медиаинженерию

FFmpeg здесь исключительно полезен, потому что именно для таких медиапайплайнов он и создан.

Его HLS-демультиплексор умеет читать поддерживаемые плейлисты как медиавходы. FFmpeg может демультиплексировать потоки, мультиплексировать их в выходные контейнеры, копировать совместимые закодированные потоки без повторного кодирования и транскодировать их, когда преобразование действительно необходимо. Подробнее эти операции описаны в документации по форматам и документации по streamcopy.

То есть если дать FFmpeg плейлист, к которому он имеет доступ и который умеет интерпретировать, значительную часть всей описанной выше механики уже не придётся реализовывать самостоятельно.

Но FFmpeg всё равно нужен рабочий вход.

Плейлист может истечь. Запросы сегментов могут зависеть от cookies или заголовков браузера. В потоке могут быть отдельные дорожки, которые нужно правильно выбрать. А реальная доставка медиа на конкретном сайте может вести себя совсем не так аккуратно, как примеры из спецификации протокола.

FFmpeg решает задачу обработки медиа. А правильно получить реальный браузерный поток вместе с нужным ему контекстом – это уже другая задача.

(Всегда есть ещё одна задача.)

А вот эту часть MAX делает скучной

MAX начинает с той страницы, где видео уже воспроизводится.

Он обнаруживает поддерживаемые медиазапросы, разбирает поддерживаемые HLS-плейлисты и показывает найденные медиа и доступные варианты прямо в расширении. Вместо охоты за запросами и самостоятельного разбора плейлиста вы выбираете найденный поток и качество.

Если медиа использует поддерживаемые раздельные аудио- и видеодорожки, MAX умеет обрабатывать их выбор и muxing. Также доступны поддерживаемые сценарии работы с субтитрами и записи прямых эфиров. Где это применимо, обработка выполняется в браузере/WASM, а для требующих этого сценариев можно использовать опциональный десктопный FFmpeg-помощник.

А если вы вообще пришли сюда именно за самим M3U8 URL, иконка ссылки у найденного HLS-элемента скопирует его.

Для обычного поддерживаемого потока вся ваша часть этого пайплайна выглядит так:

открыть страницу → при необходимости запустить видео → открыть MAX → выбрать поток → Скачать

Остальное – наша проблема.

Границы, конечно, остаются. MAX не может скачать абсолютно любой поток, не поддерживает DRM-защищённые медиа и загрузку с YouTube и не может создать доступ, которого исходный сайт вам не предоставил.

Но обычно вам не нужно знать, что такое muxing, прежде чем нажать Скачать.

Теперь знаете (простите).

Если вы всё-таки настаиваете на ручном способе

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

  1. Откройте исходную страницу с видео и запустите воспроизведение, чтобы браузер запросил медиа.
  2. Откройте Network в Chrome DevTools и отфильтруйте запросы по m3u8. Вы можете увидеть мастер-плейлист, медиаплейлисты или и то и другое. В справке Chrome по панели Network описаны инструменты фильтрации запросов.
  3. Определите, какой плейлист и какой вариант содержат нужное видео.
  4. Проверьте, входят ли аудио и субтитры в этот поток или предоставляются отдельными дорожками.
  5. Разрешите URL и получите указанные медиасегменты и необходимые данные инициализации в правильном порядке.
  6. Сохраняйте запросы в рамках обычного авторизованного доступа сайта. Подписанные URL могут истекать, а другому клиенту может понадобиться легитимная информация о сессии или запросе, которую Chrome уже отправлял.
  7. Работайте только с тем шифрованием, которое поддерживает ваш инструмент и к которому у вас есть право доступа. Не пытайтесь обходить DRM.
  8. Объедините выбранные видео и аудио в совместимый выходной контейнер.
  9. Транскодируйте только в том случае, если исходные кодеки действительно несовместимы с нужным форматом или проигрывателем.
  10. Проверьте, что итоговый файл воспроизводится до конца с ожидаемыми видео, звуком, длительностью и субтитрами, если они были выбраны.

Вот и всё.

Десять шагов, несколько протоколов и целый мультимедийный фреймворк спустя мы наконец самостоятельно нажали Скачать.

Когда получилось не то, что вы ожидали

Когда понятно, что загрузчик на самом деле делает под капотом, большинство проблем с HLS перестают выглядеть загадочно.

Что произошло Возможная причина Что проверить
Chrome сохранил крошечный файл .m3u8 Вы сохранили плейлист, а не медиа, на которое он ссылается. Используйте HLS-загрузчик, который следует по плейлисту и получает его сегменты.
Видео скачалось без звука Выбранный поток может содержать только видео, а аудио находиться в отдельном плейлисте. Проверьте мастер-плейлист или элемент в MAX на наличие отдельной аудиодорожки и при необходимости объедините её с видео.
Плейлист или сегмент внезапно отвечает 403 Возможно, URL истёк либо запрос зависит от авторизованной сессии страницы или её заголовков. Повторите попытку с исходной страницы, оставаясь нормально авторизованным. Не предполагайте, что скопированный URL полностью воспроизводит запрос браузера.
Запись прямого эфира закончилась раньше времени Live-плейлист мог обновиться, старые сегменты могли перестать отдаваться сервером либо запись началась уже после начала эфира. Записывайте поток, пока он активен. Уже недоступные старые сегменты не всегда можно восстановить позже.
Итоговый файл существует, но не воспроизводится Файл может быть неполным либо сочетание кодеков и контейнера не подходит целевому проигрывателю. Проверьте потоки и кодеки, затем попробуйте подходящий контейнер, прежде чем решать, что нужно транскодирование.
Поток защищён DRM Контент использует систему защиты, которая находится за пределами поддерживаемого сценария загрузки. MAX не поддерживает DRM-защищённые медиа. Используйте разрешённый сервисом способ доступа к контенту.

Если вам действительно интересно разбираться в плейлистах, сегментах, дорожках и медиаконтейнерах, HLS определённо стоит изучить.

А если вы просто хотели скачать видео – кнопка Скачать всё ещё там.