Я пытаюсь транслировать аудио на клиенты iOS и Safari, используя протокол Apple HTTP Live Streaming . В отличие от многих распространенных реализаций HTTP Live Streaming, моя цель - использовать короткие аудиоклипы различной длины, в основном в диапазоне 10-30 секунд. В дополнение к потоковой передаче аудио из этих сегментов, я хотел бы получить доступ к метаданным для каждого сегмента, чтобы я мог обновить отображение и / или предоставить пользователю дополнительные параметры для получения дополнительной информации о конкретном сегменте аудио.
В настоящее время я настроил несколько тестовых случаев, которые преобразуют мой исходный звук (MP3) в различные форматы и создают потоковые файлы M3U для тестирования на устройствах iOS, но ни один из моих подходов не работал должным образом (потоковая передача и передача метаданных в клиент). Я использую AVPlayer
для загрузки и воспроизведения созданных файлов M3U:
_playerItem = [AVPlayerItem playerItemWithURL:[NSURL URLWithString:@"http://localhost/sample.m3u8"]]
_player = [[AVPlayer alloc] initWithPlayerItem:_playerItem];
[_playerItem addObserver:self forKeyPath:@"timedMetadata" options:NSKeyValueObservingOptionNew context:NULL];
// ... wait for user input
[_player play];
Подход 1: сырые MP3-файлы
Я взял исходные файлы MP3 с метаданными id3v2 (v2.3.0) и добавил их в список воспроизведения M3U.
#EXTM3U
#EXT-X-TARGETDURATION:23
#EXT-X-MEDIA-SEQUENCE:0
#EXTINF:14
http://localhost/trk_01.mp3
#EXTINF:22
http://localhost/trk_02.mp3
#EXTINF:16
http://localhost/trk_03.mp3
#EXT-X-ENDLIST
Результаты: свойство timedMetadata
обновляется, как только начинается воспроизведение с правильной информацией ID3 для первой дорожки. Первый трек воспроизводится, но обрывается ближе к концу. Данные ID3 для второй дорожки отображаются, но вторая дорожка не начинает воспроизводиться. Через несколько секунд я получаю сообщение об ошибке на консоли:
2011-04-26 07:04:52.668 TestClient[49756:601b] Prime: Exiting because mConverterError is '!buf' (0x800 req, 0x0 primed)
2011-04-26 07:04:52.668 TestClient[49756:601b] Prime failed ('!buf'); will stop (2048/0 frames)
Подход 2: Используйте медиа-файл Apple для создания отдельных файлов MP3
В этом подходе я использую mediafilesegmenter
для создания нового файла MP3 для каждого сегмента. Инструмент сегментации Apple обычно используется для сегментации, но поскольку мои аудиоклипы все короткие и различной длины, это не очень подходит для моего приложения. Я передаю целевую длительность в 999 секунд утилите, чтобы она создавала один выходной файл для каждого входного файла, который я ей предоставляю. Вот команда, которую я использую для создания каждого отдельного трека:
mediafilesegmenter -t 999 -f "$OUTPUT_DIR" "$INPUT_FILE" && cp $OUTPUT_DIR/fileSequence0.mp3 $OUTPUT_FILE
Полученный файл MP3, похоже, содержит некоторые временные метки, поскольку vbindiff показывает мне изменение в заголовке файла, а строка "com.apple.streaming.transportStreamTimestamp" отображается в первых нескольких байтах нового файла. Исследование этой строки приводит к отрывку в черновой спецификации HTTP Live Streaming :
Элементарные аудиопотоки ДОЛЖНЫ
сигнализировать метку времени первого
образец в файле, добавив
ID3 PRIV тег [ID3] с владельцем
идентификатор
"Com.apple.streaming.transportStreamTimestamp".
Двоичные данные ДОЛЖНЫ быть 33-разрядными
Программа MPEG-2 Элементарный поток
отметка времени, выраженная как big-endian
восьмеричное число, с верхним 31
биты установлены в ноль.
Затем я создаю файл M3U, как в подходе 1. (Обратите внимание, что с помощью mediafilesegmenter я также могу передавать информацию ID3 с помощью предварительно созданных файлов тегов ID3 и метафайла, описывающего смещения времени ID3. Я пропускаю это здесь, потому что Я даже не могу заставить эти файлы воспроизводиться правильно.)
Результаты: первая дорожка воспроизводится так же, как в подходе 1. Трек снова обрезается ближе к концу, а вторая дорожка не воспроизводится. Метаданные отсутствуют, но их можно легко добавить с помощью параметра -M mediafilesegmenter.
Подход 3. Использование ffmpeg для создания файлов транспортного потока MPEG
Используя этот последний подход, я передаю исходные MP3-файлы через ffmpeg для создания данных транспортного потока MPEG:
ffmpeg -i "$INPUT_FILE" -f mpegts -acodec copy "$OUTPUT_FILE"
Затем я создаю M3U так же, как в первых двух подходах.
Результаты: этот подход действительно работает; все файлы передаются на клиент без проблем. Однако я не могу передать какие-либо метаданные клиенту. Я попытался передать аргументы типа -metadata title="My Title"
в ffmpeg безуспешно.