Live Streaming on iOS

В нашей работе нередко возникает необходимость реализовать отправку видеопотока с iOS-устройства в реальном – или близком к реальному – времени. Самый частый пример — использование iOS-устройства в качестве камеры слежения или создание стриминговых приложений наподобие Periscope. Как правило, при возникновении подобной задачи ставятся дополнительные условия — например, возможность проигрывания потока на другом устройстве (или в другом приложении) без возникновения лишних проблем в браузере или VLC-плеере, малые задержки (видеопоток должен транслироваться практически в режиме реального времени), низкая нагрузка на устройство (возможность длительной работы от батареи), отсутствие необходимости в специализированном медиасервере для обслуживания передачи потока, и т.п.

Подобная задача сама по себе не нова, но до сих пор не имеет однозначного решения. Точнее, она имеет целый спектр возможных решений:

  • HTTP Live Streaming (HLS)
  • HTTP Dynamic Streaming (HDS)
  • MPEG-DASH
  • fragmented MP4 (fMP4)
  • RTSP
  • WebRTC
  • и т.д.

Каждый подход обладает со своими плюсами и минусами. Например, в одной из наших прошлых, но не потерявшей актуальность, статье Реализация лайв-стриминга снимаемого видео в приложении для iOS, мы рассмотрели возможность генерации на устройстве готового HLS-потока. Это позволяет в принципе избавиться от необходимости в медиасервере, и сразу загружать контент в CDN (например, Amazon S3 + CloudFront). Однако такой, основанный на HLS, подход изначально имеет недостатки (о которых мы расскажем ниже), поэтому в этот раз мы предлагаем вам два новых варианта – генерацию на устройстве готового FMP4-потока и генерацию RTP-стрима с поддержкой локального RTSP-сервера.

HTTP Live Streaming

Протокол HLS появился в 2009 году и довольно быстро добился неплохой популярности. Этому способствовала его полная поддержка в экосистеме Apple и довольно понятная структура – есть текстовый мастер-файл, содержащий список ссылок на кусочки видеопотока, которые постоянно добавляются (в случае online-трансляции). В HLS также была предусмотрена возможность определять сразу несколько потоков для клиентов с разными требованиями к видео (быстрый канал/медленный канал и т.п.). Однако на практике такая двухступенчатая система и необходимость обновлять «мастер-файл» ограничивает сферу применения HLS. Как показывает практика, HLS слабо приспособлен для трансляций в режиме реального времени из-за следующих проблем:

  1. Трансляция нарезается на отдельные файлы небольшой длины (рекомендуется несколько секунд), в результате чего отставание трансляции от режима реального времени заложено в самой идее подобной «нарезки».
  2. При этом стандартная рекомендация по буферизации в видеоплеерах – наличие, как минимум, трех буферизованных сегментов, то есть на уровне плеера задержка из пункта 1 будет утроена;
  3. Кроме того, чтобы плеер узнал о появлении новых сегментов трансляции, ему необходимо регулярно перезапрашивать мастер-файл, что создает еще один фактор задержки (не обновив мастер-файл, плеер попросту не знает, что воспроизводить дальше).
  4. Каждый сегмент (chunk) образован как MPEG-TS файл, что означает существенный оверхед к основному медиаконтенту.

Для уменьшения задержек в HLS вполне естественно уменьшать размеры сегментов до минимума (1 секунда). Однако с такими маленькими размерами файлов на первый план выходят естественные нестабильности в работе сети. И в средних, «естественных» условиях добиться плавности воспроизведения практически невозможно — плеер больше оказывается занят перезапросами мастер-файла и очередного сегмента, чем показом видеопотока.

В попытке решить эти проблемы в 2011-2012 годах были предложены аналогичные подходы – MPEG-DASH от MPEG, Smooth Streaming от Microsoft и HDS от Adobe. Но ни одно из них не стало «стандартом де-факто» (хотя из этих трех MPEG-DASH является полноценным стандартом ISO) и на детальном уровне эти решения страдали теми же недостатками, а решения Adobe и Microsoft требовали, к тому же, особой поддержки на стороне сервера. Тут можно посмотреть таблицу сравнения между этими форматами.

Fragmented MP4

Время шло, и в итоге для простой организации трансляций приобрел популярность несколько другой подход – fMP4 (fragmented MP4). Это было небольшое (но существенное) расширение известного и хорошо поддерживаемого формата MP4, который уже тогда воспроизводился практически везде, поэтому широкая поддержка fMP4 тоже не заставила себя ждать.

Вся разница между обычным файлом MP4 и fMP4 заключается в расположении элементов, описывающих видео- и аудиостримы. В обычном MP4-файле подобные элементы расположены в конце, а в fMP4 – в начале. И так как MP4 изначально мог содержать несколько стримов, поделенных на отдельные блоки данных, – то это несложное изменение позволило создать “бесконечный файл” с точки зрения плеера.

Именно этим свойством fMP4 и пользуются при лайв-стриминге. Плеер, прочитав описание видео- или аудиопотока, начинает ждать данные и показывать (проигрывать) их по мере поступления. И если блоки с кадрами генерировать на лету, плеер автоматически будет проигрывать realtime-стрим без дополнительных усилий.

И это действительно работает! Конечно, при реализации генератора fMP4 могут возникнуть некоторые проблемы. Давайте рассмотрим их на конкретном примере – приложении DemoFMP4.

fMP4 Live Streaming on iOS

Это демонстрационное приложение берет кадры с камеры и отправляет в виде fMP4 любому зрителю, подключившемуся к устройству. Для подключения достаточно запросить у устройства виртуальный файл “MP4”, который устройство будет автоматически генерировать по адресу: http://<ip-адрес>:7000/index.mp4.
Для этого приложение запускает небольшой web-сервер на базе GCDWebServer, который слушает порт 7000 и отвечает на запросы на загрузку файла index.mp4.

Здесь есть ряд проблем, с которыми можно столкнуться.

  1. Во-первых, видеокамера выдает “сырые” кадры, которые нельзя просто так отправить плееру — они должны быть сжаты и собраны в правильном формате. К счастью, начиная с версии iOS 8.0, компания Apple открыла программный доступ к аппаратному сжатию видео, которое умеет генерировать H.264-блоки на лету. Для этого используются семейства функций VTCompressionSessionCreate и VTCompressionSessionEncodeFrame из фреймворка VideoToolbox.
    1. Аналогично сжимается и аудио   функциями семейства AudioConverterNewSpecific / AudioConverterFillComplexBuffer из фреймворка AudoToolbox — в результате чего мы
      получаем блоки данных в формате AAC.
  2. Во-вторых, камера выдает кадры с довольно высокой скоростью. Чтобы не терять их, мы сохраняем кадры в кольцевых буферах (CBCircularData), из которых блоки кадров по мере заполнения отправляются на сжатие. Эти же кольцевые буфера используются для генерации chunked-ответа, поэтому приложение не хранит в памяти больше наперед заданного числа кадров (иначе для бесконечной трансляции потребовался бы бесконечный объем памяти).
  3. В третьих, для корректной работы fMP4 необходимо правильно устанавливать начальные данные потока (включая Sps/Pps) в блоке moov MP4-файла. Для этого приложение просматривает H.264-блоки, которые генерирует hardware-кодировщик, находит очередной ключевой кадр и вытаскивает значения Sps/Pps. А при генерации moov-заголовка использует их, чтобы заставить плеер отсчитывать поток от правильного момента во времени. Таким образом, с точки зрения плеера файл всегда показывается “с самого начала”.
  4. Есть еще одна проблема — формат MP4 имеет свои требования к данным, и не может включать в себя блоки H.264 без правильного оформления. Мы решили эту проблему, подключив замечательную библиотеку Bento4, которая позволяет перепаковывать блоки H.264 в корректные MP4-atoms на лету.

flowchart-livestreaming-ru
Таким образом у нас получилось приложение, способное транслировать стрим с видеокамеры устройства практически без задержек, в реальном времени, отправляя “бесконечный MP4 файл” любому стандартному HTTP-клиенту. Такой подход дает довольно небольшое отставание: 1-2 секунды. В сочетании с широкой поддержкой fMP4 и простотой организации подобной трансляции (не требуется отдельный сервер) – генерация fMP4 на клиенте становится простым и надежным решением.

True Real-Time Live Streaming

Однако как быть, если нам нужен “настоящий реалтайм”, как в Skype? Для таких ситуаций fMP4, увы, уже не очень подходит. Несмотря на отсутствие мастер-файла (как в HLS) и небольшие размеры блоков, на которые делится видеопоток, эти блоки все еще присутствуют внутри MP4-файла. И пока такой блок не будет собран целиком, клиент никак не сможет получить кадры, что неизбежно создаст небольшую задержку при воспроизведении.

RTSP Live Streaming on iOS

Поэтому для полноценного реалтайма – когда плеер получает кадр практически сразу после его генерации в камере – больше подходит другой формат, изначально разработанный для стриминга. Речь идет о RTSP, который также обладает хорошей поддержкой среди плееров (к примеру, легко проигрывается популярным плеером VLC) и относительно не сложен в реализации. Рассмотрим пример приложения, которое обеспечивает трансляцию по стандарту RTSP – DemoRTSP.

В отличии от HLS и fMP4, которые полагаются для обмена данными на HTTP-протокол, – RTSP изначально использует свой собственный формат поверх “голых сокетов”. Кроме этого, для работы RTSP требуется два канала — один сигнальный, по которому клиент и сервер обмениваются управляющей информацией, а второй “для данных”, по которому сервер отправляет исключительно сжатые данные. Это немного усложняет схему обмена, однако позволяет добиться минимальных задержек – клиент по определению получает данные сразу после того, как сервер отправляет их по сети. В RTSP просто не предусмотрено никаких промежуточных звеньев!

DemoRTSP реализует минимальный набор для такого обмена. При запуске приложение начинает слушать сервисный порт (554) на предмет обращений от клиентов-плееров. При получении обращения, DemoRTSP отправляет в ответ простую строчку с указанием кодека, который будет использован для сжатия видео и аудио (для iOS это стандартная пара H.264/AAC) и номера порта данных, по которому сервер будет отправлять сжатые кадры. После этого клиент-плеер подключается к “порту данных” и проигрывает все, что получает от сервера. В этой схеме сервер никогда ничего не ждет и все сжатые кадры сразу уходят плееру, гарантируя минимальную задержку из возможных.

Надо сказать, что на современных iOS-устройствах сжатие и работа с сетью уже не отнимают много ресурсов. Поэтому, кроме простой трансляции, вполне возможна любого рода дополнительная обработка потока перед отправкой. Например, несложно организовать поверх видео дополнительные оверлеи с информацией, наложить на видео эффект или возможность автоматически менять видео в соответствии с нуждами приложения. Для этого можно использовать как постобработку буфера от камеры, так и более эффективный подход с использованием OpenGL. Остановимся на этом поподробнее.

Live Video Effects on iOS

В нашем демо-приложении DemoRTSP использован весьма простой подход на базе PBVision, но в ваших приложениях вы можете использовать существенно более продвинутые решения на базе фреймворка GPUImage, который позволяет применять к видеопотоку целую цепочку OpenGL эффектов, при этом сведя задержку практически к нулю.
В DemoRTSP можно увидеть пример наложения на стрим простого Blur-эффекта.
Кто сказал, что делать Prisma-like video на лету невозможно!?

Можно пойти еще дальше, и использовать наиболее “быстрый” способ работы с изображениями в iOS на текущий момент — Metal, пришедший на смену OpenGL (в последних версиях iOS). Для примера можно посмотреть в MetalVideoCapture, где показано, как с помощью API-интерфейса CVMetalTextureCache передать результат захвата камеры в Metal Render Pass.

Кроме Metal, iOS последних версий появилась еще несколько интересных возможностей. Одна из них — ReplayKit, позволяющий в несколько строчек организовать трансляцию экрана устройства. Это довольно интересная платформа, однако на текущий момент она не позволяет “вмешиваться” в процесс создания кадра, не позволяет записывать изображение с камеры (только с экрана!), а получение записи ограничено штатными средствами. На текущий момент этот фреймворк не предназначен для полноценного создания управляемых трансляций, и больше похож на “задел на будущее”. Аналогично можно сказать и про другую популярную “новинку”, iOS-поддержку нового языка программирования Swift. К сожалению, он недостаточно хорошо интегрируется с низкоуровневыми возможностями, требуемыми для работы с видео и данными, поэтому в ближайшей перспективе его вряд ли можно будет использовать в подобных задачах (исключая интерфейс).

Ссылки

  1. iOS Live Streaming
  2. HLS
  3. HDS
  4. MPEG-DASH
  5. MP4/fMP4
  6. RTSP
  7. WebRTC
  8. Сравнение HLS и MPEG-DASH
  9. Metal app
  10. ReplayKit
  11. DemoFMP4 и DemoRTSP
  12. VideoToolbox
  13. AudioToolbox
  14. Bento4
  15. GCDWebServer
  16. PBJVision

Плеер плейлистов для iOS

DVPlaylistPlayer Title

Одной из основных частей приложения, так или иначе работающего с видео, является видеоплеер. Если вы хотя бы раз имели дело с интеграцией плеера в своё приложение, то наверняка знаете, что его настройка и кастомизация занимает определённое время. Также мы готовы поспорить, что чаще всего вам не нужен был плеер, который играл бы только одно видео за всё время работы с приложением. В большинстве случаев вы бы хотели использовать плейлисты. В этой статье мы хотим рассказать вам о разработанном нами открытом компоненте, который мы используем для воспроизведения видео в нашем проекте Together. Речь пойдёт о плеере плейлистов DVPlaylistPlayer.
Continue reading

AirPlay и HDMI

Если вы разработчик игровых или мультимедиа-приложений для iOS, тогда вы просто не сможете обойтись без технологии AirPlay, которая в данной области стала уже почти стандартом. В самом деле, что может быть лучше для пользователя, чем наблюдать любимые видео или фотографии на большом экране плазменного ТВ или играть на нем в современные игры, при этом держа iPhone/iPad/iPod в руках в качестве мультитач-джойстика? AirPlay предназначен именно для этого. Continue reading

Возможности Screen Capture в iOS

Функция Screen Capture, или, попросту говоря, «снятие изображения экрана», в мобильном приложении представляет собой мощный вспомогательный инструмент и может использоваться в самых разнообразных задачах. В этой статье мы подробно рассмотрим механизмы, доступные для реализации данного функционала. Continue reading

Плеер для iOS с видеорекламой в стандарте VAST

apple-advertising
Модель монетизации, основанная на демонстрации рекламы, очень широко используется разработчиками бесплатных приложений для iOS. Для поддержки в приложениях баннерной рекламы Apple предлагает уже готовое решение. Но если в вашем приложении центральное место занимает видеоплеер, вас может заинтересовать показ видеорекламы в паузах при воспроизведении основного видеоконтента. Насколько нам известно, для этой цели пока не существует готовых бесплатных и широко используемых решений. В этой статье мы расскажем, как вы можете легко добавить функциональность показа видеорекламы в свое приложение. Для этого нужно будет подключить к рекламному серверу OpenX нашу бесплатную библиотеку iOS VAST Player. Continue reading

Воспроизведение видео в iOS приложениях

iOS video player

Мобильные устройства Apple на операционной системе iOS заслуженно снискали всеобщую популярность среди покупателей. За каждым событием компании следят с большим интересом, ожидая появления новых и улучшения существующих функций. Но обычные пользователи могут лишь поверхностно оценивать внешнюю составляющую продукта. Взгляду разработчиков же открывается гораздо больше. Из всей четырехдневной конференции WWDC публично освещается обычно всего один доклад — keynote, кратко рассказывающий об основных нововведениях. Все остальные доклады, а всего их около ста, посвящены разработчикам. Это соотношение позволяет оценить скрытую часть айсберга, которая не менее интересна, чем то, что видно на поверхности. Начиная цикл статей о разработке под iOS, мы расскажем о функциональности встроенных в устройства Apple фреймворков для работы с онлайн-видео. Continue reading

Дизайн видео плеера

Видео плеер дизайн
Дизайн современного видео плеера (PC версия), который  Вы можете использовать в своих проектах. Это работа нашего дизайнера, в ближайшее время будут опубликованы Flash и HTML5 исходники. Дизайн видео плеера Flash/HTML5 в PSD.

HTML5 <video> аналитика

Если Вы работаете в области online-video сервисов, то наверняка задумывались об аналитике просмотров видео пользователями. Для платформы OSMF (фреймворк, написанный на Flash технологии) существует плагин GTrackPlugin осуществляющий сборку статистики по просмотру контента пользователем. Также можно использовать нашу собственную разработку OSMF Video Analytics.

Однако если сервис основан на HTML5 видео, то необходимо решение, реализующее аналитику просмотров видео для данной технологии. Реализация данного плагина основана на работе с HTML5 Media API. (Подробнее о работе с данным API Вы моете прочитать в статье о реализации HTML5 плеера). Continue reading

Разработка HTML5 плеера

HTML5 JS Player

С каждым годом медиа технологии все больше http://tutbelgorod.ru/  и больше входят в жизнь каждого человека. Глобальная сеть также подвержена данной тенденции, о чем свидетельствуют  успех и популярность таких сервисов как YouTube. Но работа подобных систем невозможна без технологий, позволяющих реализовать воспроизведение видео контента для пользователя.

Классическим подходом для реализации проигрывателя видео является использование технологии Flash.  Пожалуй, сложно найти более распространенный плагин для веб-браузера, чем Flash Player. Однако стоит заметить, что слабым местом подобного подхода является необходимость установки Flash plugin’а. А для многих устройств он вообще отсутствует. К примеру, настолько популярные iPhone и  iPad не имеют возможности запускать Flash-приложения в браузере. Выходом из подобной ситуации является использование HTML5. Continue reading

Разработка видеоплеера для Android

Android Video Player

Одна из задач, с которой вы можете столкнуться http://kakielekarstva.ru/  при разработке приложения для Android — это встраивание видео плеера в приложение, для воспроизведения видео контента. Стандартный SDK предоставляет два пути решения этой проблемы: использовать низкоуровневый класс MediaPlayer или готовый визуальный компонент VideoView совместно со стандартной панелью управления воспроизведением MediaController. Оба эти подхода обладают своими недостатками, поэтому мы решили разработать собственный видеокомпонент AVideo. В этой статье мы расскажем о том как его использовать в своем приложении и какие преимущества он дает. Continue reading