Objective-C下载流畅的流媒体视频

Agn*_*Dev 3 video objective-c nsinputstream smooth-streaming afnetworking

我想知道是否有一种方法可以使用Objective-C下载一个mp4视频,该视频设置为以流媒体格式流式传输.到目前为止,我已经尝试了AFNetworking,NSInputStream和MPMoviePlayerController来尝试访问原始视频数据,但每次尝试都空了.

我想把这个视频数据保存为mp4到磁盘,以便离线播放.URL看起来像这样:

     http://myurl.com/videoname.ism/manifest(format=m3u8-aapl)
Run Code Online (Sandbox Code Playgroud)

San*_*der 6

我将假设您正在询问HTTP直播视频,如示例网址所示,而不是平滑流媒体视频.如果不是这样,请发表评论,我将编辑答案,谈论Smooth Streaming.

HTTP直播视频的结构

HTTP Live Streaming(HLS)有多个版本,其中较新版本增加了对多语言音频和字幕的适当支持,这使得场景显着复杂化.我将假设您对此类功能不感兴趣,并将重点放在简单的案例上.

HLS具有三层结构:

  1. 在根目录,您有主播放列表.这是您在请求视频根URL时Web服务器提供的内容.它包含对一个或多个媒体播放列表的引用.
  2. 一个媒体播放列表表示一个特定的配置整个视频.例如,如果使用两个质量级别(例如720p和1080p)对媒体进行编码,则将有两个媒体播放列表,每个媒体播放列表一个.媒体播放列表包含对实际包含媒体数据的媒体段的引用列表.
  3. 媒体段是含有一块数据流的MPEG传输流中,每个文件通常约为10秒.

当多语言功能不在图片中时,将HLS视频视为分成10个第二个块的多个单独视频是有效的 - 所有视频包含相同的内容但使用不同的质量级别.

上述每个实体 - 主播放列表,媒体播放列表,每个媒体段 - 由播放器使用标准HTTP文件下载机制单独下载.

把碎片放回原处

媒体播放器所需的所有信息都存在于媒体片段中 - 您通常可以忽略主播放列表和媒体播放列表,因为它们的唯一目的是为您提供媒体片段的URL.

值得庆幸的是,MPEG传输流格式本质上非常简单.为了将媒体段重新组合在一起,您需要做的就是将它们连接在一起.就是这样,真的!

伪代码

我将假设您没有询问如何使用Objective-C执行HTTP请求,因为有关该主题的Stack Overflow上有许多其他答案.相反,我将专注于您需要实现的算法.

首先,您只需下载主播放列表即可.

masterPlaylist = download(rootUrl);
Run Code Online (Sandbox Code Playgroud)

主播放列表包含注释行和数据行.每个数据行都是对媒体播放列表的引用.请注意,HLS的最低质量级别通常只有音频流.让我们假设您关心文件中的第一个质量级别,为简单起见.

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

此数据行将包含媒体播放列表的相对URL.我们下载吧.URL附加代码应该是智能的,并且了解如何创建相对URL,而不仅仅是字符串连接.

mediaPlaylist = download(rootUrl + firstMasterPlaylistDataLine);
Run Code Online (Sandbox Code Playgroud)

反过来,媒体播放列表的格式相同,但包含对媒体片段的引用.让我们一起下载它们并将它们一起添加.

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);
}
Run Code Online (Sandbox Code Playgroud)

最终输出将是单个MPEG传输流文件,可在大多数现代媒体播放器上播放.如果要将其转换为其他格式,可以使用各种免费工具,如FFmpeg.