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

А раз уж вопросы не прекращаются, а значит можно и тут ответить.

Почему видео вещается с задержкой?


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

Современный интернет стримминг — это HLS протокол. Иногда DASH, но это не принципиально, ведь они оба сегментные.

Как это работает? Потоковое видео «нарезается» на небольшие файлы (как правило, 2-8 секунд, в зависимости от динамичности контента), накапливается 3-10 таких сегментов и описываются специальным плейлистом, который автоматически обновляется при удалении старого сегмента и добавлении нового. Вот так просто. Больше сегментов — больше задержка, больше продолжительность каждого сегмента — больше задержка. 10-20 секунд — это нормально.

Зачем это нужно? Зачем накапливать так много видео в памяти видеосервера? Сегментация позволяет плееру не реагироваться на нестабильность интернет-соединения, не прерывать видео при переключении с Wi-Fi сети на мобильное подключение. Если бы видео не было заранее подготовлено и упаковано в отдельные файлы, то при малейших сбоях или нехватке полосы мы бы видео на экране артефакты, а сегментация дает плееру порядка 4-20 секунд на восстановление соединения плеера и подгрузку новых данных.

Что делать, если нужно видео без задержки? Выбирайте другой протокол, если вы собираетесь устраивать веб-чат, управлять коптером через интернет, смотреть видео IP-камеры. Вот примеры: WebRTC, MSE-LD, RTMP.

Как защитить видео? Вставить только на свой сайт


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

На все подобные обращения у меня всегда один ответ — вам нужно настроить Securelink на вашем сайте. Защита контента невозможна в одностороннем порядке — сайт должен сам генерировать ссылки, нельзя просто взять и вставить статическую ссылку на сайт.

Securelink — старая и весьма эффективная технология для защиты ссылок. Многим хабрачитателям известно про специальный модулья для Nginx — ngx_http_secure_link_module. У нас не используется Nginx, но есть аналогичная и не менее эффективная реализация, разница лишь в порядке параметров.

Как это работает? Сайт генерирует уникальную одноразовую ссылку на основе данных о пользователе. А что веб-серверу известно о клиенте? Правильно, это IP-адрес, User-Agent, Cookie, запрашиваемый URL. Если клиент авторизован, то в переменных сессии можно получить и другую информацию, например, уникальный ID клиент в базе сервиса, или, например, срок действия подписки.

Собираем параметры в одну строку и хешируем любимым алгоритмом, например, SHA1. Получается набор бесполезных символов. Например, хеш от строки «127.0.0.1Habr» будет: 70ebe94671dd21bd65f4a00dfd988adc83fe6bda.

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

Берем строку «127.0.0.1Habr1540327100SECRET» и получаем SHA1 99fe961672c52aa3033b98b545ec2cdec93bf515, а теперь формируем ссылку вида:

example.com/Habr/index.m3u8?token=99fe961672c52aa3033b98b545ec2cdec93bf515-1540327100

example.com — ваш видеосервер, Habr — запрашиваемое видео, index.m3u8 — стандартное имя HLS плейлиста, значение token — строка от веб-сервера, которую мы с вами сгенерировали.

Видеостример легко извлекает из этих данных все, что нужно для получения такого же хеша: IP-адрес читается из переменной веб-сервера, запрашиваемый контент из URL, время жизни — из параметра token, единственное что ему не хватает — это секретного ключа, его придется прописать в конфиг файле и хранить в секрете.

Такую ссылку не получится отправить другу или открыть в другом браузере — в формуле хеширования присутствует IP-адрес, и срок жизни подменить не получится — тогда не совпадет хеш.

Подводные камни


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

Очень часто бывает, что сайт и веб-сервер неправильно определяют IP-адрес клиента, это нормально, если используются CDN сети, например, CloudFlare. В таком случае нужно забирать IP-адрес из правильного заголовка, может потребоваться помощь провайдера CDN. Например, у CloudFlare это CF-Connecting-IP.

Неправильное время. Неправильное время на одном из серверов, в сочетации с попытками максимально сократить время жизни ссылки, не редко приводят к неработающим ссылкам. А еще бывает, что пользователь оставляет вкладку открытой на несколько часов, а потом не может воспроизвести видео из-за короткого времени жизни.

3-24 часа время жизни ссылки — это нормально, все равно они защищены и существуют способы ограничить количество одновременных просмотров.

Вместо итога


Расскажите в комментариях, как обойти такой механизм защиты ссылок?

Комментарии (4)


  1. barbos6
    24.10.2018 10:41

    Непонятно, зачем в секьюрных ссылках используется ip адрес, при том, что

    существуют способы ограничить количество одновременных просмотров.


    1. klu4ik Автор
      24.10.2018 10:48

      Хороший вопрос. Чтобы ограничить кол-во одновременных сессий для пользователя, нужно его авторизовать: т.е. передать в адресной строке какой-то уникальный ID (id или username), тогда видеостример сможет опознать какому пользователю какая сессия просмотра принадлежит.

      Такой метод не подходит для публичных(анонимных) сервисов, поэтому и используется IP-адрес, т.к. имя пользователя неизвестно.


  1. OlegStrekalovsky
    24.10.2018 20:59

    Что насчёт ситуаций, когда пользователи сидят за NAT? Особенно когда эти пользователи ещё и знают друг друга (например сотрудники одной организации или какого-то небольшого интернет провайдера)


    1. klu4ik Автор
      24.10.2018 21:03

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