HLSEmbeddingPlayer

Как встроить HLS-видео на сайт (iframe и hls.js)

Пошаговое руководство по размещению HLS-видео на веб-странице: готовый плеер в iframe, адаптивная вёрстка, параметры адреса и собственный плеер на hls.js.

HLS (HTTP Live Streaming) — формат, которым сегодня пользуется большинство сайтов для видео по запросу. Вместо одного огромного файла MP4 видео описывается небольшим текстовым плейлистом, который указывает на несколько версий одного и того же видео, нарезанных на короткие сегменты. Плеер скачивает несколько сегментов вперёд, измеряет скорость их получения и переключается между версиями на лету. Зрители с мобильным интернетом получают лёгкую версию, зрители на оптоволокне — чёткую, и никому не приходится ждать загрузки целого файла до появления первого кадра.

В этом руководстве показаны два способа разместить HLS-видео из UFOLOAD на своей странице: готовый плеер в iframe, на что уходит около минуты, и собственный элемент <video> под управлением hls.js, который даёт полный контроль над страницей. Оба используют один и тот же поток, так что можно начать с iframe и позже перейти на hls.js, ничего не загружая заново.

Как выглядит HLS-поток из UFOLOAD

После загрузки файла конвертер кодирует его в видео H.264 и стереозвук AAC в одну–четыре версии, которые называются рендишенами: 360p, 720p, 1080p и 2160p (4K). Версия никогда не больше исходника, поэтому из загрузки в 720p получаются 720p и 360p, а не растянутые 1080p. Какую максимальную версию вы получите на деле, зависит и от тарифа; актуальные лимиты указаны на странице тарифов. Если хотите подробно разобраться, как выбираются ступени, прочитайте статью лестницы адаптивного битрейта.

Каждая версия хранится как обычный MP4 с индексом в начале файла. Когда зритель запускает воспроизведение, слой хранения на лету упаковывает эти MP4 в HLS: мастер-плейлист (master.m3u8) перечисляет все версии с пиковой пропускной способностью, разрешением и кодеками, а у каждой версии есть собственный плейлист из четырёхсекундных сегментов. Ключевые кадры расставлены так, чтобы совпадать с границами сегментов, — именно это позволяет плееру чисто переключать качество посреди видео.

Плейлист и сегменты отдаются с кэш-узлов с заголовком Access-Control-Allow-Origin: *, поэтому плеер на вашем домене может запрашивать их напрямую. Каждый URL подписан и имеет срок действия — это станет важно, когда речь пойдёт о подходе с hls.js.

Шаг 1: загрузите видео и дождитесь готовности

Загрузите видео из кабинета, перетащив файл или вставив прямую ссылку, либо используйте FTP, WebDAV или API (примеры на curl, Python и Node.js — в статье загрузка видео через API). Файл проходит статусы uploading, queued, processing и ready; при статусе failed указывается причина, и загрузку можно повторить из кабинета. Короткие ролики готовы за несколько минут, длинные фильмы — дольше, а на платных тарифах есть приоритетная очередь кодирования.

Ждать окончания обработки, чтобы сделать страницу, не обязательно. Если кто-то откроет плеер, пока файл обрабатывается, он увидит уведомление об обработке с прогрессом, а когда обработка закончится, плеер сам переключится на видео. И всё же проверьте, что статус — ready, прежде чем публиковать страницу, чтобы первые посетители не увидели полосу прогресса.

Вам понадобится идентификатор видео. Кабинет показывает его в панели «Поделиться», а API возвращает его как public_id — короткий код из 11 символов. Именно этот код подставляется в адрес встраивания.

Шаг 2: встройте плеер через iframe

Кабинет выдаёт фрагмент кода с iframe сразу после загрузки и в панели «Поделиться» у каждого видео. Он выглядит как первый блок ниже. Замените VIDEO_ID на идентификатор своего видео. Сама страница плеера не индексируется поисковыми системами, и для встраивания это как раз то, что нужно: в выдаче ранжируется ваша страница, а не фрейм плеера.

Фрагмент кода из кабинета · html
<iframe width="640" height="360"
  src="https://iframe.andromedans.live/e/VIDEO_ID"
  title="My video"
  frameborder="0"
  allow="autoplay; fullscreen; picture-in-picture"
  allowfullscreen></iframe>

Фиксированные размеры в пикселях ломаются на телефонах. Для адаптивной страницы оберните iframe в блок, сохраняющий пропорции 16:9, и пусть фрейм заполняет его. Плеер занимает весь фрейм, поэтому видео масштабируется без искажений.

Адаптивное встраивание · html
<div style="position:relative;aspect-ratio:16/9;max-width:960px">
  <iframe src="https://iframe.andromedans.live/e/VIDEO_ID"
    title="My video"
    style="position:absolute;inset:0;width:100%;height:100%;border:0"
    loading="lazy"
    allow="autoplay; fullscreen; picture-in-picture"
    allowfullscreen></iframe>
</div>

Параметры, которые можно добавить в адрес

  • autoplay=1 запускает воспроизведение при загрузке плеера. В большинстве случаев браузеры блокируют автозапуск со звуком, поэтому сочетайте его с mute=1.
  • mute=1 запускает видео без звука; зритель может включить звук в любой момент.
  • loop=1 запускает видео заново, когда оно заканчивается.
  • t=30 начинает воспроизведение с 30-й секунды — удобно для ссылок на конкретный момент длинного видео.

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

Совет

Если плеер сообщает, что встраивание запрещено, скорее всего, домена вашей страницы нет в списке разрешённых доменов для встраивания. Как работает этот список, объясняется в статье привязка к домену и гео-ограничения.

Шаг 3 (необязательно): воспроизведение потока через hls.js

iframe — самый короткий путь, но иногда нужна своя вёрстка: собственная панель управления, видео внутри карусели, события аналитики из вашего кода. Тогда нужны адрес плейлиста и библиотека плеера. Браузеры, кроме Safari, не умеют воспроизводить HLS сами, поэтому обычно выбирают hls.js — JavaScript-библиотеку, которая подаёт HLS-сегменты в стандартный элемент <video>. Safari и iOS воспроизводят HLS нативно, и библиотека им не нужна.

Адрес плейлиста находится в поле links.playback объекта видео. Запрашивайте его со своего сервера с API-ключом, потому что ключ никогда не должен попадать в код браузера. Тот же вызов возвращает links.expires_at, а ссылки подписаны и ограничены по времени, поэтому запрашивайте свежую ссылку при каждом формировании страницы, а не храните её в базе данных.

На сервере (Node.js 18+): получение подписанной ссылки на плейлист · js
const BASE = 'https://ufoload.com/api/v1'

export async function playbackUrl(fileId) {
  const res = await fetch(`${BASE}/files/${fileId}`, {
    headers: { Authorization: `Bearer ${process.env.UFOLOAD_API_KEY}` },
  })
  if (!res.ok) throw new Error(`UFOLOAD API: ${res.status}`)
  const { file, links } = await res.json()
  if (file.status !== 'ready') return null // still processing
  return links.playback // signed master.m3u8 URL
}

Если нужен срок действия, отличный от стандартного, POST /files/{id}/links принимает ttl от 60 секунд до 30 дней и может привязать ссылку к IP-адресу или cookie. Всё это подробно описано в документации API. Есть и публичный эндпоинт GET /api/v1/public/files/{id}, которому ключ не нужен; его используют страницы просмотра и встраивания, а его ссылки действуют шесть часов.

На странице создайте плеер. Блок ниже использует hls.js там, где он поддерживается, переходит на нативное воспроизведение в Safari, а в остальных случаях показывает простое сообщение. Размещайте файл библиотеки у себя или фиксируйте версию, а не подгружайте каждый раз самую свежую.

На стороне клиента · html
<video id="player" controls playsinline preload="metadata"
       poster="POSTER_URL" style="width:100%;aspect-ratio:16/9;background:#000"></video>
<script src="/vendor/hls.min.js"></script>
<script>
  const video = document.getElementById('player')
  const src = 'PLAYLIST_URL_FROM_YOUR_SERVER'

  if (window.Hls && Hls.isSupported()) {
    const hls = new Hls()
    hls.loadSource(src)
    hls.attachMedia(video)
    hls.on(Hls.Events.ERROR, (_, data) => {
      if (!data.fatal) return
      if (data.type === Hls.ErrorTypes.NETWORK_ERROR) hls.startLoad()
      else if (data.type === Hls.ErrorTypes.MEDIA_ERROR) hls.recoverMediaError()
      else hls.destroy()
    })
  } else if (video.canPlayType('application/vnd.apple.mpegurl')) {
    video.src = src // Safari, iOS
  } else {
    video.outerHTML = '<p>This browser cannot play HLS video.</p>'
  }
</script>

Объект видео также содержит links.poster для обложки и links.sprite для превью при наведении — они пригодятся, если вы делаете собственную шкалу перемотки. С hls.js вы отказываетесь от того, что плеер UFOLOAD делает за вас: меню качества, глав, выбора субтитров, логотипа поверх видео и, когда реклама доступна, рекламы. В этом и состоит реальный компромисс, а таблица ниже подводит итог.

iframe или hls.js: что выбрать

ВопросПлеер в iframehls.js на вашей странице
Время настройкиМинута: скопировать и вставитьЧас или больше плюс небольшой эндпоинт на сервере
Возможности плеераМеню качества, главы, субтитры, превью при наведении, логотип, реклама, когда доступнаВсё, что вы сделаете сами
МонетизацияКогда реклама доступна, она показывается и учитывается в плеереНедоступна, потому что рекламный слой находится в плеере UFOLOAD
ОформлениеСкин, цвета, логотип и кнопки в студии плеераЛюбой HTML и CSS на ваш вкус
Срок действия ссылокУчитывается автоматическиВы запрашиваете свежую ссылку при каждом формировании страницы
Привязка к доменуРазрешённые домены для встраивания соблюдаютсяНе применяется к ссылке, которую вы отдаёте сами, поэтому используйте короткий TTL и привязку к IP или cookie

Чек-лист для решения проблем

  • Чёрный кадр или бесконечная загрузка. Откройте в браузере панель сети и найдите master.m3u8. Ответ 403 означает, что ссылка истекла или зритель заблокирован правилом по стране или IP; запросите свежую ссылку.
  • Браузер блокирует видео на HTTPS-странице. Всё должно идти по HTTPS. Никогда не вставляйте адрес http:// в iframe или в hls.js.
  • Автозапуск не срабатывает. Браузеры блокируют автозапуск со звуком. Добавьте mute=1 или в hls.js установите video.muted = true перед вызовом play().
  • Уведомление об обработке вместо видео. Файл ещё не готов. Опрашивайте GET /files/{id}, пока status не станет ready.
  • Воспроизводится только низкое качество. Плеер начинает осторожно и поднимает качество, как только измерит пропускную способность. Максимальную версию ограничивают также ваш тариф и исходник; сверьтесь с тарифами и страницей возможностей.

Когда страница заработает, возможно, вы захотите защитить её от хотлинкинга или, если реклама доступна, зарабатывать на ней. Об этом следующие руководства: как ограничить, где можно встраивать видео и как монетизировать видеосайт рекламой в плеере. Если вы ещё выбираете, где размещать видео, чек-лист выбора видеохостинга подскажет, что сравнивать.

Попробуйте с бесплатным аккаунтом

Загрузите видео и получите HLS-плеер и API-ключ за несколько минут. Лимиты тарифов указаны на странице тарифов.