Онлайн-видео с Wowza и Amazon Elastic Transcoder
Опубликовано: 2022-03-11Успех и внедрение любого веб-приложения сегодня во многом зависит от его производительности, гибкости и простоты использования.
Особенно в современном мире СДВГ пользователи быстро теряют терпение к приложению, если его страница загружается слишком долго. Для веб-приложений, которым необходимо поддерживать обработку видео, которая по своей природе требует больших вычислительных ресурсов и операций ввода-вывода, эта проблема стоит особенно остро. Тем не менее пользователи становятся все более требовательными, желая, чтобы их видео были высокого качества и быстро загружались, даже если они работают на смартфоне или планшете.
Пользователи также теряют терпимость к веб-приложениям, которые не работают в предпочитаемом ими браузере или устройстве или не поддерживают формат данных, необходимый для загрузки или экспорта. Поэтому разнообразие форматов видео, которые необходимо поддерживать, также делает включение поддержки видео в веб-приложение особенно сложной задачей.
В этом посте описывается, как я эффективно использовал технологии с открытым исходным кодом и облачные сервисы для включения возможностей видео в веб-приложение на основе PHP.
Пример использования
Я был частью команды, которой нужно было разработать веб-сайт, похожий на YouTube, где зарегистрированные пользователи могли загружать и делиться своими видео.
Система должна была позволить зарегистрированным пользователям загружать свои видео в различных поддерживаемых форматах, которые затем конвертировались в общий формат (MP4). Нам также нужно было сгенерировать набор миниатюр и коллаж изображений, которые будут использоваться в видеоплеере для показа кадров на полосе прогресса видео.
Все усложнялось еще и тем, что требования клиента не позволяли нам использовать какие-либо доступные CDN или API транскодирования, поэтому нам нужно было разрабатывать наше решение с нуля.
Загрузка видео
Поскольку сам процесс загрузки не обязательно должен быть привязан к видео (нам просто нужна была простая в использовании возможность загрузки файлов), имело смысл использовать существующее решение с открытым исходным кодом, а не развертывать собственное. Мы выбрали jQuery-File-Upload прежде всего потому, что он поддерживал две функции, которые были необходимы в нашем случае; а именно, индикатор выполнения загрузки и загрузка по частям.
Фрагментарная загрузка позволила нам разрешить пользователю загружать видеофайлы практически любого размера (особенно важно для поддержки видеофайлов в разрешении HD). При таком подходе файл делится на несколько «фрагментов» на внешнем интерфейсе, что вызывает действие загрузки с каждым фрагментом данных (вместе с метаданными для каждого фрагмента, такими как номер фрагмента и общий размер файла). Полный видеофайл затем собирается на серверной части. Кстати, включение номера фрагмента в метаданные оказалось особенно важным, поскольку некоторые браузеры (такие как Mobile Safari) склонны передавать фрагменты в случайном порядке.
Онлайн-обработка видео
Обработка видео может быть такой же простой, как захват кадров в виде неподвижных изображений, или может включать более сложные операции, такие как улучшение изображения, стабилизация видеопотока и т. д. В нашем случае единственными требованиями к обработке видео были (а) извлечение видеокодеков и других ключевых метаданных и (б) создание набора эскизов и коллажа изображений (для использования в видеоплеере для показа кадров в процессе видео). бар).
FFmpeg — широко используемая свободно распространяемая библиотека с открытым исходным кодом — чрезвычайно помогла в выполнении этих требований. FFmpeg предоставляет комплексное кроссплатформенное решение для записи, преобразования и потоковой передачи аудио- и видеофайлов. Его также можно использовать для преобразования видео и выполнения простого редактирования (например, обрезки, обрезки, добавления водяного знака и т. д.).
Для наших целей мы смогли использовать FFmpeg, чтобы разделить видео на десять частей, а затем сделать миниатюру для каждой части, чтобы обеспечить необходимую функциональность.
К сожалению, для библиотеки FFmpeg нет языковых привязок PHP. В результате единственный способ использовать FFmpeg из PHP — это вызвать двоичный файл из командной строки с помощью системных команд. Есть два основных способа использования FFmpeg в PHP:
- либав. Libav — это проект бесплатного программного обеспечения, созданный на основе FFmpeg в 2011 году и создающий библиотеки и программы для обработки мультимедийных данных. Например, в Ubuntu это можно установить с помощью команды
sudo apt-get install libav-tools
. Команды libav совместимы с FFmpeg и avconv. PHP должен иметь доступ из командной строки кffmpeg/avconv
, чтобы использовать это программно. - PHP-FFMpeg. PHP-FFMpeg — это объектно-ориентированный PHP-драйвер для бинарного файла FFMpeg. Доступ к нему можно получить, просто выполнив
composer update "php-ffmpeg/php-ffmpeg"
.
Мы использовали PHP-FFMpeg, так как он обеспечивает легкий доступ к интересующей нас функциональности FFmpeg. Например, класс FFProbe
из этого пакета позволяет получить информацию о кодеках или длине конкретного видеофайла следующим образом:
$ffprobe = FFMpeg\FFProbe::create(); $ffprobe ->format('/path/to/video/mp4') // extracts file informations ->get('duration');
FFmpeg также позволяет легко сохранять любой видеокадр:
$ffmpeg = FFMpeg\FFMpeg::create(); $video = $ffmpeg->open('video.mpg'); $video ->frame(FFMpeg\Coordinate\TimeCode::fromSeconds(10)) ->save('frame.jpg');
Более подробный пример кода доступен здесь.
Одно предостережение: из-за некоторых патентных законов не все кодеки могут обрабатываться FFmpeg, а некоторые форматы не поддерживаются должным образом (или полностью). Я помню, как пару лет назад у меня были проблемы, например, с форматом .3gp
, когда поддержка обычных телефонов была обязательной.
очередь
После получения кодеков видео и других метаданных мы помещаем видео в очередь преобразования FIFO (первым пришел — первым обслужен). Очередь была реализована с помощью простого сценария cron, который выбирает заданное количество необработанных видео при каждом запуске и передает их утилите преобразования (пример исходного кода доступен здесь).
Утилита преобразования вызывает FFMpeg для выполнения преобразования и помечает каждое видео как обработанное.
Мы также разработали простой механизм оценки времени ожидания, который вычисляет среднее время конвертации 1 минуты видео. Используя это среднее значение, мы можем рассчитать и отобразить для пользователя предполагаемое оставшееся время обработки после завершения загрузки видео, исходя из того, сколько минут видео осталось для обработки.
Преобразование видеоформата
Некоторые общепризнанные форматы (например, JPEG и GIF) появились для неподвижных изображений, которые в основном поддерживаются всеми устройствами и программами обработки изображений. Хотя некоторые форматы видео более распространены, чем другие, такого универсально поддерживаемого формата для видео еще не появилось.
В нашем случае, помимо необходимости конвертировать из различных форматов в один общий формат (MPEG-4), нам нужно было оптимизировать конвертированные видео для потоковой передачи на мобильные устройства.
Для преобразования видеоформата (по крайней мере, для наших краткосрочных потребностей) использование облачного Amazon Elastic Transcoder было лучшим доступным вариантом. Помимо общей простоты использования, сервис транскодера заботится об оптимизации и всех настройках кодирования. К счастью, доступен AWS SDK для PHP, который упрощает вызов сервиса из нашего PHP-кода.
Примечание. Использование облачного сервиса, такого как Amazon Elastic Transcoder, отлично подходит, если вы хотите быстро приступить к работе. Однако имейте в виду, что этот вариант может дорого обойтись вашему клиенту, особенно если его бизнес-модель, вероятно, потребует широкого использования больших видео. Еще один фактор, который следует учитывать, заключается в том, что вам не обязательно предполагать, что видео или бизнес-модель вашего клиента будут совместимы с Условиями предоставления услуг.

Amazon использует свои базовые элементы хранения и вычислений, S3 (Simple Storage Service) и EC2 (Elastic Compute Cloud) в сочетании с Auto Scaling и SNS (Simple Notification Service), чтобы обеспечить возможность масштабирования практически мгновенно.
Установка aws-sdk проста, поскольку Amazon поддерживает версию пакета, которую можно установить для Composer. Просто добавьте ”aws/aws-sdk-php": "2.*"
в ваш файл composer.json
и выполните composer update
.
Очевидно, что для доступа к Amazon Elastic Transcoder требуется учетная запись Amazon, поэтому вам также необходимо настроить ее, если у вас (или вашего клиента) ее еще нет.
Наше использование службы Amazon Elastic Transcoder повлекло за собой первую загрузку видеофайлов в соответствующую корзину на S3. Затем мы сделали задание транскодера ответственным за декодирование и создание эскиза, который по завершении отправляет HTTP-запрос на указанный адрес. Это требует некоторой настройки на панели AWS, но это довольно просто, и Amazon предоставляет хорошую документацию о том, как это сделать.
Не стесняйтесь использовать наш пакет транскодера, который помогает упростить интеграцию с Symfony 2. Он включает описание использования и предлагает контроллер для быстрой реализации службы уведомлений, отправляемой Amazon для сбора информации об обработанном видео. Пример использования доступен здесь.
Кроме того, здесь доступен пример контроллера, который обрабатывает уведомления Amazon, который также реализует подтверждение адреса подписки. Служба сначала опубликует URL-адрес для посещения, чтобы подтвердить, что это действительный получатель уведомлений. Все, что действительно требуется, это пометить видео как обработанное. С этого момента мы можем использовать перекодированное видео, хранящееся в облаке.
Потоковое
Потоковое видео — это возможность, которая требует высокой производительности: ожидания пользователей в отношении непрерывной потоковой передачи высоки, а терпимость к задержке крайне мала. Эта проблема часто усугубляется необходимостью одновременной потоковой передачи видео нескольким клиентам в режиме реального времени.
В нашем случае нам нужно было сделать так, чтобы каждый пользователь мог создать свой собственный видеоканал и начать трансляцию. Наше решение состояло из трех компонентов:
- Панель приборов. Приложение, которое служит приборной панелью стримера, предоставляя возможность обслуживать видео.
- Зритель. Видеоклиент, который потребляет и отображает видеопоток.
- Потоковый движок. Облачный сервис потокового видео.
В дополнение к тому факту, что технология видео по запросу (VOD) все еще развивается, еще одна проблема, с которой мы столкнулись, заключалась в том, что доступ к камерам плохо поддерживался и предлагался только соединение P2P. Также нашей целью было обеспечить онлайн-трансляцию для нескольких одновременных пользователей. Кроме того, поддержка API getUserMedia/Stream
(ранее предусмотренного как элемент <device>
) пока не согласована в современных браузерах. Основываясь на этих факторах, я решил использовать технологию Flash, так как это был действительно единственный разумный выбор. Поэтому оба приложения (Dashboard и Viewer) были реализованы с использованием Flex и ActionScript .
В качестве потокового движка мы использовали Wowza . Хотя есть и другие, некоммерческие решения (например, Red5, который позиционируется как замена Wowza), в нашем случае важным фактором была поддержка коммерческого продукта. Кроме того, по крайней мере, в то время, когда мы создавали систему, Wowza предлагала лучшую документацию, что было дополнительным преимуществом. (Обратите внимание, что вы можете получить пробную версию Wowza бесплатно на 30 дней, а также есть пробная версия для разработчиков, которую вы можете использовать до 180 дней. Но есть некоторые ограничения: потоковая передача может работать только для двух клиентов, и существует ограничение на максимальное количество подключений.)
Потоковый движок Wowza
Мы использовали приложение LiveStream, поставляемое с Wowza. Для его настройки оставьте applications/app_name
пустым и в conf/app_name
скопируйте файл Application.xml
из каталога conf
. Отредактируйте файл, чтобы настроить раздел <Streams>
следующим образом:
<Streams> <StreamType>live</StreamType> <StorageDir>${com.wowza.wms.context.VHostConfigHome}/content</StorageDir> <KeyDir>${com.wowza.wms.context.VHostConfigHome}/keys</KeyDir> <LiveStreamPacketizers></LiveStreamPacketizers> <Properties></Properties> </Streams>
Ключевым параметром является <StreamType>live</StreamType>
, который определяет, что это будет поток из живого видеопотока (например, с камеры). Обратите внимание, что после редактирования и сохранения этого файла вам потребуется перезапустить Wowza.
Приложения Flash (Flex/ActionScript)
Flash предоставляет полностью интегрированную систему для подключения камеры и микрофона к потоковому серверу Wowza. Это особенно полезно, если ваш опыт работы с ActionScript ограничен.
Все приложение по существу основано на взаимодействии между следующими объектами:
- Сетевое соединение. Класс NetConnection создает двустороннее соединение между клиентом и сервером. Клиентом может быть Flash Player или приложение AIR. Сервер может быть веб-сервером, сервером Flash Media Server, сервером приложений с Flash Remoting или службой Adobe Stratus.
- Камера. Класс Camera используется для захвата видео с клиентской системы или камеры устройства.
- Микрофон. Класс Microphone используется для мониторинга или захвата звука с микрофона.
- Нетстрим. Класс NetStream открывает односторонний канал потоковой передачи через NetConnection.
Сначала мы подключаемся к потоковому серверу Wowza с помощью экземпляра NetConnection, а затем подключаем прослушиватель событий, который будет отслеживать изменения состояния сетевого подключения:
nc = new NetConnection(); nc.connect(serverAddress:string); nc.addEventListener( NetStatusEvent.NET_STATUS, // event type eNetStatus, // listener function false, // use capture? 0, // priority true // use weak reference? );
Вот минималистичный пример прослушивателя событий, который подключает камеру и микрофон к потоковому серверу:
private function eNetStatus(e:NetStatusEvent):void { switch (e.info.code) { case "NetConnection.Connect.Success": camera = Camera.getCamera(); mic = Microphone.getMicrophone(); ns = new NetStream(nc); ns.publish(streamName, "live"); ns.attachCamera(camera); ns.attachAudio(mic); break; case "NetConnection.Connect.Closed": // debug trace... display user message break; }
Код клиента очень похож, за исключением того, что мы просто отображаем ввод видео на стороне пользователя. Это делается путем подключения потока к объекту Video
, как показано в этом простом примере:
if(event.info.code == "NetConnection.Connect.Success") { ns = new NetStream(nc); ns.client = nsClient; ns.addEventListener(NetStatusEvent.NET_STATUS, nsClient.onNetStatus); ns.play(streamName); video = new Video(); addChild(video); // this will display video video.attachNetStream(ns); // connect NetStream to video }
Заворачивать
Можно ожидать, что прямая трансляция и видео будут играть все более важную роль в мобильных и веб-приложениях. Поэтому для веб-разработчиков важно ознакомиться с транскодированием, обработкой и потоковой передачей видео. Сегодня существует множество инструментов, библиотек и сервисов для включения этих возможностей в веб-приложения. В этой статье показано, как мы использовали и интегрировали ряд этих технологий, чтобы с относительной легкостью успешно создать базовый сайт, похожий на YouTube.