9

我正在尝试使用 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,但没有运气。

4

2 回答 2

1

只是一个建议..你试过这个项目吗 - https://github.com/DigitalDJ/AudioStreamer我在我的项目中使用它并且它很好

更新 1 -

您可以使用 FFMPEG 的参数“-map_meta_data”将元数据信息传输到一个文件到另一个文件

这是一个例子 -

ffmpeg -i /root/Desktop/new_tracks/02-drug-raps.mp3 -ab 24k /root/Desktop/new_tracks/converted/2.mp3 -map_meta_data /root/Desktop/new_tracks/02-drug-raps.mp3:/root/Desktop/new_tracks/converted/2.mp3;
于 2011-04-29T07:44:22.657 回答
0

除非将片段准备为单个流,否则解码器不一定能够在它们之间无缝切换。

每当解码器需要重置时,您应该引入#EXT-X-DISCONTINUITY行。除非您正在分割一个单独的长 mp3 文件,否则您需要在每个新 mp3 之前标记不连续性。

于 2012-04-17T08:32:34.753 回答