Плеер
Матрица поддержки HLS средствами HTML5
Матрица поддержки плагинов и ядра плеера
Настройка плеера в ЛК
Сервис доступен в Личном Кабинете CDNvideo, в разделе Плеер
.
Также можно мгновенно получить базовый плеер (или перейти к настройке более сложного) прямо в разделе настройки трансляции (меню Стриминг -> Трансляции
).
Общее описание плеера
В качестве базовых библиотек для плеера мы используем опенсорсные разработки HLS.js, Shaka и Clappr. Дополнительные фичи (в виде плагинов к Clappr) разрабатываем самостоятельно: некоторые выложены в опенсорс, а основная масса доступна клиентам платно.
Сами библиотеки и файлы плагинов размещены на нашем CDN и могут быть добавлены на страницу следующим образом:
<!-- Player --> <script type="text/javascript" src="//playercdn.cdnvideo.ru/aloha/clappr/clappr5.min.js"></script> <script type="text/javascript" src="//playercdn.cdnvideo.ru/aloha/clappr/level-selector.min.js"></script> <script type="text/javascript" src="//playercdn.cdnvideo.ru/aloha/clappr/stream-selector.min.js"></script> <script type="text/javascript" src="//playercdn.cdnvideo.ru/aloha/clappr/clappr-styling.min.js"></script> <script type="text/javascript" src="//playercdn.cdnvideo.ru/aloha/clappr/clappr-poster.min.js"></script> <script type="text/javascript" src="//playercdn.cdnvideo.ru/aloha/clappr/clappr-logo-plugin.min.js"></script> <script type="text/javascript" src="//playercdn.cdnvideo.ru/aloha/clappr/clappr-error-handler.min.js"></script>
Пример инициализации плеера
<div id="player" class="player"></div> <script> var player = new Clappr.Player({ language: 'en-EN', parentId: "#player", source: "//live-streams.cdnvideo.ru/cdnvideo/caminandes/playlist.m3u8", width: '100%', height: '100%', plugins: [LevelSelector, ClapprLogoPlugin, ClapprErrorHandler], levelSelectorConfig: { labelCallback: function(playbackLevel) { return playbackLevel.level.height + 'p'; // Name from SMIL (external_playlist) } }, logoPlugin: { src: '//playercdn.cdnvideo.ru/aloha/cdn-demo/static/wildberries_logo.png', // url: '//cdnvideo.ru/?from=' + window.location.hostname, height: 30, marginTop: 3, }, hideMediaControl: false, clapprErrorHandler: { quiet: false, text: 'Трансляция сейчас не идёт. Подождите, пожалуйста, немного', retryDelay: 5, // onRetry: (err) => {console.log(err)} onRetry: function (e) { console.log(e) this.restart() } }, }); </script>
API плеера
Основные команды API плеера (ниже player
- название экземпляра плеера при встраивании на странице):
player.play()
- запустить воспроизведение.player.pause()
- приостановить воспроизведение VoD.player.stop()
- остановить воспроизведение Live-потока.player.volume(value)
- изменить громкость в плеере.player.seek(time)
- перемотать на нужное время.player.load('new-video-url')
- загрузить новый источник воспроизведения, не изменяя остальную конфигурацию.player.getDuration()
- получить продолжительность источника видео, в секундах.player.getCurrentTime()
- получить текущую позицию просмотра видео, в секундах.
Общее описание чата
Чат - сервис, полностью основанный на собственных разработках CDNvideo. На бекенде работают быстрые websocket-сервера. На фронтенде - модули для отображения интерфейса и дизайна чата.
Все фронтенд-модули размещены на нашем CDN и готовы к использованию сразу после того, как сервис оплачен и добавлен чат-рум.
Внимание
Чат не рассчитан на количество одновременных пользователей более трёх тысяч в одной комнате. По превышению трёх тысяч и людям будет неудобно переписываться в одном потоке, и технические сложности могут возникнуть. Для крупных трансляций не следует использовать опцию автоматического входа в чат по авторизационным данным клиента. Также иногда разумно создать сразу набор чат-румов для одного клиента и распределять зрителей по комнатам равномерно.
Тестовый стенд с чатом
Тестовый стенд: https://playercdn.cdnvideo.ru/aloha/cdn-demo/player_chat_stand.html
Аккаунты модераторов:
- admin1 (пароль - password1)
- admin2 (пароль - password2)
Обращаем внимание, что тестовый стенд нельзя встраивать на боевые пользовательские страницы, так как доступ к нему может быть закрыт.
Для размещения чата в продакшене у себя на сайте, нужно выбрать тариф и написать заявку менеджеру, после чего для вас будет заведён отдельный чат-рум и создан боевой чат с кодом встраивания на сайт.
После проведения тестов и использования аккаунта модератора, просьба разлогиниться или закрыть вкладку, чтобы не занимать тестовый сокет. Для тестирования чата без каких-либо ограничений и на собственной странице, необходимо получить боевой чат. Условия можно обсудить с менеджером.
Встраивание чата напрямую в страницу
Для тестовых экспериментов можно импортировать следующие файлы:
<!-- Chat --> <link href=//playercdn.cdnvideo.ru/aloha/chat/cdn-chat-app.css rel=stylesheet> <script type=text/javascript src=//playercdn.cdnvideo.ru/aloha/chat/cdn-chat-manifest.js></script> <script type=text/javascript src=//playercdn.cdnvideo.ru/aloha/chat/cdn-chat-vendor.js></script> <script type=text/javascript src=//playercdn.cdnvideo.ru/aloha/chat/cdn-chat-app.js></script>
Инициализация чата (frontend API)
<script> Chat.init({ el: '#app', width: '100%', height: '100%', language: 'RU', room: 'd11_test', // чат-рум service: 'wss://chat.cdnvideo.ru/chat', maxMessageLength: 255, maxMessagesCount: 50, timeBetweenMessages: 1, maxEqualMessages: 2, userName: 'username1', // автоматический вход по данным сайта (параметр необязательный) userIcon: 'avatar.jpg', // ссылка на аватар пользователя или переменная со ссылкой (параметр необязательный, используется обычно для входа по данным с сайта) joinBtnColor: '#007bff', // Цвет кнопки присоедениться (по умолчанию '#007bff') enableControls: true, // включение кнопок подсветки и поднятия комментариев у модератора (по умолчанию false) emojiBtn: false, // отключение смайликов (по умолчанию true) joinBtnText: 'Задать вопроc', // переименование кнопки Присоедениться (не указывается по умолчанию) hiddenMode: true, // скрывать ли имена пользователей в чате (параметр необязательный) enablePremoderate: true, // включение премодерации для администратора sendBtn: 'btn_url' // url кнопки отправки }); </script>
Прямые запросы по websocket к чату (backend API)
Установка соединения с чатом и websocket-сообщения
<script> // URL для подключения к вебсокету с учетными данными администратора const url = "wss://chat.cdnvideo.ru/chat?user=admin1&room=d11_test&password=password1"; // Создаем новое вебсокет-соединение const socket = new WebSocket(url); // Обработчик открытия соединения socket.onopen = function() { console.log("Соединение установлено"); // Создаем сообщение для сохранения переписки чата const saveMessage = { type: "Save" }; // Отправляем сообщение на сервер для сохранения переписки socket.send(JSON.stringify(saveMessage)); console.log("Сообщение для сохранения переписки отправлено"); // После отправки первого сообщения, отправляем сообщение для очистки чата const clearMessage = { type: "Clear" }; // Используем небольшой таймаут, чтобы быть уверенными, что первое сообщение доставлено setTimeout(() => { socket.send(JSON.stringify(clearMessage)); console.log("Сообщение для очистки чата отправлено"); }, 1000); // Задержка 1 секунда (можно настроить по необходимости) }; // Обработчик получения сообщений от сервера (необязательно) socket.onmessage = function(event) { console.log("Получено сообщение:", event.data); }; // Обработчик закрытия соединения socket.onclose = function(event) { if (event.wasClean) { console.log(`Соединение закрыто чисто, код=${event.code} причина=${event.reason}`); } else { console.log('Соединение прервано'); } }; // Обработчик ошибок socket.onerror = function(error) { console.log(`Ошибка: ${error.message}`); }; </script>
Описание скрипта с API
Сообщение для сохранения переписки чата: после установления соединения создается сообщение с типом "Save" и отправляется на сервер.
Сообщение для очистки чата: после отправки сообщения для сохранения чата создается сообщение с типом "Clear".
Используется setTimeout()
с задержкой в 1 секунду, чтобы убедиться, что первое сообщение доставлено, прежде чем отправлять второе. Время задержки можно изменить в зависимости от требований.
Обработчики событий:
onopen
: обрабатывает логику последовательной отправки сообщений.onmessage, onclose, onerror
: обрабатывают полученные сообщения, закрытие соединения и ошибки.
Этот скрипт отправит сначала сообщение для сохранения чата, а затем, спустя небольшую задержку, отправит сообщение для очистки чата.
Сообщения (команды чата)
- Сохранить переписку
{ "type": "Save" }
- Очистить переписку
{ "type": "Clear" }
Пример сообщения с командой очистки чата
После авторизации в чате можно очистить сообщения.
Для этого клиент (браузер или скрипт python) отправляет по вебсокету следующее сообщение: { "type": "Clear" }
.
Пример скрипта с сообщением на Python
import asyncio import websockets import json async def clear_chat(): # URL для подключения к вебсокету с учетными данными администратора url = "wss://chat.cdnvideo.ru/chat?user=admin1&room=d11_test&password=password1" # Заголовки, необходимые для подключения headers = { 'Origin': 'https://playercdn.cdnvideo.ru' } # Подключаемся к вебсокету async with websockets.connect(url, extra_headers=headers) as websocket: # Соединение установлено # Создаем сообщение для очистки чата clear_message = { "type": "Clear" } # Отправляем сообщение на сервер await websocket.send(json.dumps(clear_message)) print("Сообщение для очистки чата отправлено") # Ждем ответа от сервера (необязательно, зависит от логики работы чата) try: async for message in websocket: print(f"Получено сообщение: {message}") except websockets.ConnectionClosed as e: print(f"Соединение закрыто: {e}") # Запуск асинхронного процесса asyncio.get_event_loop().run_until_complete(clear_chat())
Описание скрипта очистки сообщения
URL: подключение осуществляется через вебсокет с учетными данными администратора (user=admin1, room=d11_test, password=password1
).
Заголовки: установлен заголовок Origin
на https://playercdn.cdnvideo.ru
.
Очистка чата:
- Создается сообщение с типом "Clear" и отправляется на сервер через вебсокет.
- Сообщение формируется как JSON-объект и сериализуется с помощью
json.dumps()
перед отправкой. - Прослушивание ответов (необязательно): после отправки команды можно слушать ответы от сервера, хотя это не всегда требуется.
Этот скрипт очистит все сообщения в чате, отправив соответствующую команду через вебсокет-соединение.
Пример скрипта с сообщением на JavaScript
<script> // URL для подключения к вебсокету с учетными данными администратора const url = "wss://chat.cdnvideo.ru/chat?user=admin1&room=d11_test&password=password1"; // Создаем новое вебсокет-соединение const socket = new WebSocket(url); // Обработчик открытия соединения socket.onopen = function() { console.log("Соединение установлено"); // Создаем сообщение для очистки чата const clearMessage = { type: "Clear" }; // Отправляем сообщение на сервер socket.send(JSON.stringify(clearMessage)); console.log("Сообщение для очистки чата отправлено"); }; // Обработчик получения сообщений от сервера (необязательно) socket.onmessage = function(event) { console.log("Получено сообщение:", event.data); }; // Обработчик закрытия соединения socket.onclose = function(event) { if (event.wasClean) { console.log(`Соединение закрыто чисто, код=${event.code} причина=${event.reason}`); } else { console.log('Соединение прервано'); } }; // Обработчик ошибок socket.onerror = function(error) { console.log(`Ошибка: ${error.message}`); }; </script>
Часто задаваемые вопросы
Переключение аудиодорожек
Как реализовать переключение между аудиодорожками в плеере? Почему оно не работает на iOS в полноэкранном режиме?
Есть два основных варианта реализации переключения языков в плеере:
- Отдельные потоки, между которыми в плеере происходит переключение. Этот вариант надёжнее и универсальнее, проще в настройке (функция “Плейлист” есть в веб-интерфейсе, транскодировать потоки не требуется). Но в iOS изменять поток для проигрывания можно только вне полноэкранного режима, когда используется наш интерфейс. В полноэкранном же режиме iOS не поддерживает переключение между потоками, а менять логику или интерфейс нативного плеера iOS извне - запрещено. Поэтому при использовании такого варианта приходится либо мириться с ограничениями iOS, либо запрещать в iOS переход в полноэкранный режим.
- Один HLS-поток с аудиодорожками в плейлисте. Такой вариант поддерживает не только наш плеер, но нативный плеер iOS, поэтому переключаться в полноэкранном режиме на iOS тоже будет возможно. Проблема лишь в создании такого потока. Его должен либо предоставить клиент, либо наша поддержка должна дать возможность преобразовать поток на бекенде в HLS с аудиодорожками. Это не всегда легко.
Если же требуется переключение между несколькими потоками, в каждом из которых несколько дорожек (языков), то нужно использовать второй способ совместно с первым. В соответствии с их предназначениями.
Фулскрин в iOS и YouTube
Плеер Ютуба отлично открывается на полный экран в мобильных устройствах. Почему ваш плеер так не может?
Проблема заключается в особенностях iOS: в браузере в полноэкранном режиме там всегда запускается нативный интерфейс, от плеера это не зависит. В том числе у YouTube, если открывать его в браузере. Правда, начиная с какого-то момента, Safari вообще перестал открывать видео Ютуба в браузере, автоматически перенаправляя всех в мобильное приложение YouTube.
Встраивание в соцсети
Зависит ли возможность встраивания вашего плеера в социальные сети от политики конкретной соцсети в отношении встраиваемого контента?
Да. Большинство социальных сетей не разрешают встраивать айфреймы и сторонние плееры, поэтому для проигрывания видеоконтента там нужно использовать местные стандартные плееры. Для решения этой задачи можно использовать функцию рестрима, доступную в личном кабинете. На своем сайте клиент может использовать наш плеер с полной функциональностью. Ссылку на эту основную страницу с плеером клиент может прикреплять к постам в соцсетях.
Атрибуты кода встраивания iframe с плеером
Где описано, за что отвечают те или иные атрибуты тэга iframe кода встраивания? Можно ли их изменять?
Да, изменять можно: эта часть является границей между нашей стороной и стороной клиента, а тэг iframe является стандартным интерфейсом, который известен фронтендеру, отвечающему за сайт клиента. Атрибуты описаны во всех руководствах по HTML: http://htmlbook.ru/html/iframe.
Свои собственные атрибуты мы не используем (и не можем по стандарту HTML), а набор стандартных указываем лишь в качестве рекомендации, например:
frameborder="0" width="640" height="360" scrolling="no" style="overflow:hidden;" allowfullscreen
.
Все свои настройки передаём не в атрибутах тэга, а в параметрах query string ссылки на исходный плеер (либо плеер получает их автоматически, с нашего бэкенда, из базы данных настроек конкретного клиента).
JS API для управления плеером
Имеется ли JS API для управления плеером: перемотка с помощью команды?
Да, имеется. Описание команд можно посмотреть в разделе по API плеера.
Как работает DRM
Как работает DRM в плеере? Можно ли встроить ваш плагин в свой плеер?
С работой нашего плагина можно ознакомиться на стенде: https://players-stand.cdnvideo.ru/clappr/DRM/.
Использовать наш плагин в стороннем плеере теоретически можно с некоторой адаптацией, но проще написать плагин с нуля. Для добавления поддержки DRM в собственный плеер первым делом необходимо решить вопрос поддержки WideWine и PlayReady. Мы для воспроизведения MPEG-DASH используем Shaka Player. Там реализована поддержка DRM.
Разрешение видео и постера
Как ведет себя плеер 640х360, если поток будет еще в 1080р, 720р, 480р? Какого размера присылать постер?
Каков бы ни был размер плеера, контент всегда будет натянут на этот размер. Если разрешение контента меньше физических размеров плеера, недостаток качества будет заметен в виде размытости изображения и “квадратиков”. При избыточном разрешении ничего заметного не произойдёт. Размер постера стоит подбирать исходя из предполагаемых габаритов плеера в момент отображения постера. Тут только компромисс между качеством картинки и её весом. При уменьшении размера плеера постер будет масштабироваться под его размер с сохранением пропорций.
Видеозаглушка при геоограничении
Можно ли реализовать показ видеозаглушки для зриетелей, которые не проходят по геоограничению? На уровне плеера или на уровне раздачи потока с CDN.
Возможны следующие варианты:
- Реализация в плеере. Раздающий сервер CDNvideo выдаёт код 403 в случае геоограничения (по стандарту), а плеер, используемый в данным момент, подставляет заглушку. В нашем плеере сейчас нет функции видеозаглушки, но есть функция статичной медиазаглушки: в случае геоограничения вместо потока показывается любая указанная картинка, а поверх неё - любой текст.
- Реализация на стороне CDNvideo, на уровне раздачи потока. Такой стандартной функции не имеется, но можем разработать кастомно прокси-сервер, который будет анализировать IP каждого зрителя, определять его географию и выдавать в зависимости от этого либо обычный поток, либо поток-заглушку. В таком случае заглушка может быть как статичной, так и видео. Заказать разработку такой функциональности можно через менеджера.
Таймкоды и функция “поделиться в соцсети”
В плеере появилась новая функция "поделиться видео". Если копировать URL ссылки, то можно отправить ссылку на видео, даже на каком-то моменте из видео? Если сразу нажать поделиться в соц. сетях или мессенджерах, то отправится ссылка на сайт, а не на видео?
Если копировать из URL, то скопируется просто URL: плеер, к сожалению, из соображений безопасности не имеет возможности знать, что за его пределами копируют зрители. А вот если нажать "Copy Link" в плеере, то скопируется ссылка на страницу с таймкодом, при открытии которой плеер автоматически перемотает видео на нужный момент.
Что касается функции "Поделиться в соцсети", то плеер сформирует и отправит ссылку на страницу с таймкодом. Само видео он не может отправить, потому что соцсети как правило не поддерживают встраивание сторонних видео (минуя интерфейс соцсети).
HTTP FLV для LL и мультибитрейт
Есть ли возможность настроить несколько качеств при раздаче LL FLV?
Нет, нормальный мультибитрейт протокол HTTP FLV не поддерживает. Можно, конечно, сделать несколько потоков с разными качествами и включить в плеере функцию для переключения потоков, но бесшовности и автоматического переключения в таком варианте не будет.
Для качественного переключения качеств нужно использовать LL HLS. Но он может нестабильно работать в некоторых браузерах.
Автовоспроизведение со звуком
Можно ли настроить автовоспроизведение видео, оставив звук в плеере включённым по умолчанию?
Автоплей с включённым звуком не зависит от плеера, а зависит только от политики браузера и пользовательских настроек. По умолчанию сейчас не работает ни в одном популярном браузере, если говорить о всех зрителях. Но у отдельных зрителей звук может быть включён либо из-за настроек браузера, либо если браузер запоминает, что на таком-то сайте пользователь взаимодействовал с медиа. Пользователь (зритель) может сам в настройках Chrome (и большинства других браузеров) разрешить воспроизведение на всех доменах или на определённых.
По современным нормам, автоплей как правило блокируется браузером, если звук не выключен. Есть исключения, но это скорее недоработки разработчиков браузеров, чем надёжные возможности.
Если требуется гарантированный автоплей или гарантированная громкость, стоит выбрать что-то одно.
YouTube автовоспроизводит со звуком
Большинство пользователей взаимодействовали ранее с YouTube (или даже разрешили автовоспроизведение со звуком для этого сайта), поэтому там видео со звуком в среднем по пользователям запускается чаще. Также автоплей с включенным звуком у YouTube в Chrome как раз может работать, потому что это два продукта одной компании - Google. При этом FireFox и большинство других браузеров будут блокировать автовоспроизведние в YouTube, если звук включён.