Всем привет. В нашу поддержку ежедневно открывают десятки различных обращений, от простых вопросов «помогите настроить кластер» до очень сложных «не работает поток, иногда заикается» поток, но есть вопросы, от которых уже глаз дергается и каждый сотрудник компании может подробно ответить.
А раз уж вопросы не прекращаются, а значит можно и тут ответить.
У нас в блоге уже две статьи (раз, два) на эту тему, прочитайте их, если работаете с видео, а тут я дам короткий и исчерпывающий ответ:
Современный интернет стримминг — это 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 часа время жизни ссылки — это нормально, все равно они защищены и существуют способы ограничить количество одновременных просмотров.
Расскажите в комментариях, как обойти такой механизм защиты ссылок?
А раз уж вопросы не прекращаются, а значит можно и тут ответить.
Почему видео вещается с задержкой?
У нас в блоге уже две статьи (раз, два) на эту тему, прочитайте их, если работаете с видео, а тут я дам короткий и исчерпывающий ответ:
Современный интернет стримминг — это 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 часа время жизни ссылки — это нормально, все равно они защищены и существуют способы ограничить количество одновременных просмотров.
Вместо итога
Расскажите в комментариях, как обойти такой механизм защиты ссылок?