我正在尝试使用Apple的HTTP Live Streaming协议将音频流式传输到iOS和Safari客户端。与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文件
我将带有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 draft specification:
中引出一段话基本音频流文件必须 发信号通知第一个的时间戳 通过预先添加一个文件中的样本 带有所有者的ID3 PRIV标签[ID3] 的标识符 “com.apple.streaming.transportStreamTimestamp”。 二进制数据必须是33位 MPEG-2节目基本流 时间戳表示为大端 八字节的数字,上面的31 位设置为零。
然后我就像方法1一样创建一个M3U文件。(注意,使用mediafilesegmenter我也可以使用预先创建的ID3标签文件和描述ID3时间偏移的元文件传递ID3信息。我在这里跳过这个因为我甚至无法正确播放这些文件。)
结果:第一首曲目就像接近1一样进行流式传输。曲目在末尾附近再次切断,第二首曲目不播放。没有元数据,但可以使用mediafilesegmenter的-M选项轻松添加。
方法3:使用ffmpeg创建MPEG传输流文件
使用这种最终方法,我通过ffmpeg传递源MP3文件以创建MPEG传输流数据:
ffmpeg -i "$INPUT_FILE" -f mpegts -acodec copy "$OUTPUT_FILE"
然后我就像前两种方法一样创建一个M3U。
结果:这种方法确实有效;所有文件在客户端上流畅地传输。但是,我无法将任何元数据传递给客户端。我试过把-metadata title="My Title"
这样的论点传递给ffmpeg而没有运气。
答案 0 :(得分: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;
答案 1 :(得分:0)
除非将片段准备为单个流,否则解码器不一定能够在它们之间无缝切换。
每当解码器需要重置时,您应该引入#EXT-X-DISCONTINUITY行。除非你是一个被分段的单个长mp3文件,否则你需要在每个新mp3之前标记不连续性。