Objective-C Скачать гладкое потоковое видео

Мне интересно, есть ли способ с Objective-C скачать MP4-видео, которое настроено для потоковой передачи в формате Smooth Streaming. До сих пор я пробовал AFNetworking, NSInputStream и MPMoviePlayerController, чтобы попытаться получить доступ к необработанным видеоданным, но при каждой попытке получалось пустым.

Я хотел бы затем взять эти видео данные и сохранить их в виде mp4 на диск для воспроизведения в автономном режиме. URL выглядит примерно так:

     http://myurl.com/videoname.ism/manifest(format=m3u8-aapl)

1 ответ

Решение

Я предполагаю, что вы спрашиваете о HTTP Live Streaming видео, как указано в вашем примере URL, вместо Smooth Streaming video. Если это не так, пожалуйста, оставьте комментарий, и я отредактирую ответ, чтобы говорить о Smooth Streaming.

Структура HTTP потокового видео

Существует несколько версий HTTP Live Streaming (HLS), в новой из которых добавлена ​​надлежащая поддержка мультиязычного звука и титров, что значительно усложняет сценарий. Я предполагаю, что вы не заинтересованы в таких функциях и остановитесь на простом случае.

HLS имеет трехслойную структуру:

  1. В корне у вас есть мастер-плейлист. Это то, что предоставляет веб-сервер при запросе корневого URL-адреса видео. Он содержит ссылки на один или несколько списков воспроизведения мультимедиа.
  2. Список воспроизведения мультимедиа представляет все видео для одной конкретной конфигурации. Например, если мультимедиа кодируется с использованием двух уровней качества (таких как 720p и 1080p), будет два списка воспроизведения мультимедиа, по одному для каждого. Список воспроизведения мультимедиа содержит список ссылок на сегменты мультимедиа, которые фактически содержат данные мультимедиа.
  3. Сегменты мультимедиа являются транспортными потоками MPEG, которые содержат часть потоков данных, обычно около 10 секунд на файл.

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

Каждый из вышеперечисленных объектов - основной список воспроизведения, список воспроизведения мультимедиа, каждый сегмент мультимедиа - загружается проигрывателем отдельно с использованием стандартных механизмов загрузки файлов HTTP.

Собираем кусочки

Вся информация, которая требуется медиапроигрывателю, присутствует в медиа-сегментах - вы можете в основном игнорировать главный плейлист и медиа-плейлист, поскольку их единственная цель - дать вам URL-адреса медиа-сегментов.

К счастью, формат MPEG Transport Stream очень прост по своей природе. Все, что вам нужно сделать для того, чтобы соединить сегменты медиа вместе, это соединить их вместе. Вот и все, правда!

ПСЕВДОКОД

Я собираюсь предположить, что вы не спрашиваете о том, как выполнять HTTP-запросы, используя Objective-C, поскольку есть много других ответов о переполнении стека на эту тему. Вместо этого я остановлюсь на алгоритме, который вам нужно реализовать.

Во-первых, вам просто нужно скачать Master Playlist.

masterPlaylist = download(rootUrl);

Главный плейлист содержит как строки комментариев, так и строки данных. Каждая строка данных является ссылкой на список воспроизведения мультимедиа. Обратите внимание, что самый низкий уровень качества для HLS, как правило, будет иметь только аудиопоток. Предположим здесь, что для простоты вы заботитесь о том, какой первый уровень качества в файле.

masterPlaylistLines = masterPlaylist.split('\n');
masterPlaylistDataLines = filter(masterPlaylistLines, x => !x.startsWith("#"));
firstMasterPlaylistDataLine = masterPlaylistDataLines[0];

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

mediaPlaylist = download(rootUrl + firstMasterPlaylistDataLine);

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

mediaPlaylistLines = mediaPlaylist.split('\n');
mediaPlaylistDataLines = filter(mediaPlaylistLines, x => !x.startsWith("#"));

foreach (dataLine : mediaPlaylistDataLines)
{
    // URL concatenation code is assumed to be smart, not just string concatenation.
    mediaSegment = download(rootUrl + firstMasterPlaylistDataLine + dataLine);
    appendToFile("Output.ts", mediaSegment);
}

Окончательный вывод будет одним файлом MPEG Transport Stream, который можно будет воспроизводить на большинстве современных медиаплееров. Вы можете использовать различные бесплатные инструменты, такие как FFmpeg, если вы хотите конвертировать его в другой формат.

Другие вопросы по тегам