我正在尝试使用 Apple 的HTTP Live Streaming协议将音频流式传输到 iOS 和 Safari 客户端。与 HTTP 实时流的许多常见实现不同,我的目标是使用本质上具有不同长度的短音频剪辑,主要在 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 文件
我将带有 id3v2 (v2.3.0) 元数据的原始源 MP3 文件添加到 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 的 mediafilesegmenter 创建单独的 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 节目基本流时间戳,表示为大端八位字节数,高 31 位设置为零。
然后我像方法 1 一样创建一个 M3U 文件。(请注意,使用 mediafilesegmenter 我还可以使用预先创建的 ID3 标记文件和描述 ID3 时间偏移的元文件传递 ID3 信息。我在这里跳过它,因为我可以甚至无法正确播放这些文件。)
结果:第一首曲目与方法 1 一样流式传输。曲目在接近尾声时再次中断,第二首曲目不播放。不存在元数据,但可以使用 mediafilesegmenter 的 -M 选项轻松添加。
方法三:使用ffmpeg创建MPEG传输流文件
使用最后一种方法,我通过 ffmpeg 传递我的源 MP3 文件以创建 MPEG 传输流数据:
ffmpeg -i "$INPUT_FILE" -f mpegts -acodec copy "$OUTPUT_FILE"
然后我像前两种方法一样创建一个 M3U。
结果:这种方法确实有效;所有文件都在客户端流畅地传输。但是,我无法将任何元数据传递给客户端。我试过将参数传递-metadata title="My Title"
给 ffmpeg,但没有运气。