swift 如何从S3流式传输MP4视频,而无需AVPlayer在播放之前下载文件?

fae0ux8s  于 2023-01-29  发布在  Swift
关注(0)|答案(2)|浏览(150)

我有很多长(45分钟- 90分钟)的MP4视频在一个公共S3桶,我想在我的iOS应用程序中使用AVPlayer播放它们。
我正在使用AVPlayerViewController播放它们,但我需要等待几分钟才能开始播放,因为它下载了整个视频,而不是流媒体。
我在本地缓存它,所以这只发生在第一次,但我想流的视频,使用户不必等待整个视频下载。
有些人指出我需要Cloudfront来播放视频,但在文档中,我读到只有当你有很多人在播放同一个文件时才有必要这样做。我正在构建一个MVP,所以我只需要一个简单的解决方案。
有没有什么方法可以从AVPlayerViewController的S3存储桶中流式传输MP4视频,而无需在播放给用户之前完全下载文件?

g52tjvyc

g52tjvyc1#

TLDR

AVPlayer不支持您定义的"流"(HTTP范围请求),因此,请使用支持的替代视频播放器或使用AVPlayer支持的真正的媒体流协议(如HLS),并在下载所有视频之前启动视频。
CloudFront一般来说非常适合交付,但并不是真正需要的--您可能已经看到过由于CloudFront RTMP发行版而提到它,但它们现在已经是discontinued了。

详细答案

S3使用HTTP range requests支持一个称为byte-range fetches的概念-您可以通过对视频文件执行HEAD请求来验证这一点&查看Accept-Ranges头是否存在,其值设置为bytes(或非'none')。
在浏览器中加载您的MP4文件,注意,只要您单击播放,它就可以开始播放。您还可以移动到视频文件的结尾,但是,你还没有真正下载整个视频文件。HTTP范围请求是允许这个机制工作的。当用户到达视频的那个部分时,视频的小块可以被下载。这节省了文件服务器&用户带宽,同时提供比客户端下载整个文件好得多的用户体验。
服务器需要首先支持字节范围获取,然后客户端才能决定是否发出范围请求(* 或不 *)。关键是,一旦服务器支持它,就由HTTP客户端决定是要分块获取数据还是一次获取所有数据。
这并不是你所知道的"流媒体",也不是你问题中提到的,而是使用HTTP 206部分内容响应从服务器下载视频并播放。
在视频中查找时,您可以在浏览器的"网络"选项卡中看到这一点,即一系列多个206响应。不会下载整个视频,但会从您跳到的任何位置流式传输视频。

AVPlayer的问题

不幸的是,**AVPlayer不支持使用HTTP范围请求和HTTP 206部分内容响应的"流媒体"。**我已经通过在Xcode中创建一个演示iOS应用手动验证了这一点。

    • 这与S3无关**-如果您将这些文件存储在任何其他云提供商或文件服务器上,您会看到文件在播放前仍然完全加载。
可能的解决方案

现在问题已经很清楚了,有两种解决方案。

使用备用视频播放器

最简单的解决方案是使用另一个支持字节范围提取的视频播放器。我不是iOS开发的Maven,所以很遗憾我不能不推荐一个替代品,但我相信会有一个流行的库,行业更喜欢内置的AVPlayer。这将为您提供您的(非常常见的)定义'流媒体'。

使用视频流协议

然而,如果您必须使用AVPlayer,解决方案是使用视频流协议实现真正的媒体流-真正的流还允许您利用自适应比特率切换、实时音频切换、许可等功能。
有相当多的这些协议可用,如DASH(动态自适应流HTTP),SRT(安全可靠传输)和最后但并非最不重要的,HLS(HTTP直播流)。
今天,互联网上使用最广泛的流媒体协议是HLS,由苹果自己创建(嘿,也许不支持范围请求的原因是为了强迫你使用该协议)。Apple's own documentation真的很适合深入研究,如果你有兴趣。
没有得到太多的协议细节,HLS将允许播放开始更快,一般来说,快进可以更快,并提供视频,因为它是真正的流体验观看。
要继续HLS:
1.使用AWS Elemental MediaConvert将MP4文件转换为HLS格式-结果输出将是1个(或更多).M3U8清单文件以及.ts媒体段文件
1.将结果输出上传到S3
1.将AVPlayer指向.M3U8文件

let asset = AVURLAsset(url: "https://ermiya.s3.eu-west-1.amazonaws.com/videos/video1playlist.m3u8")
let item = AVPlayerItem(asset: asset)
...

1.享受近乎即时的视频加载

云锋

至于Amazon CloudFront,它本身并不是必需的& S3在这种情况下就足够了,但是快速的谷歌搜索会提到它提供的很多好处,特别是缓存,它可以帮助你节省以后的S3成本。

结论

如果可以的话,我会选择转换到HLS,因为它会产生更多的可能性,总体来说是一种更好的真正的流媒体体验,但由于iOS AVPlayer的限制,使用其他视频播放器也会同样有效。
是否使用CloudFront,将取决于您的用户群,S3的使用和其他因素。
当你创建MVP时,我建议你只做一个MP4文件到HLS格式的批量转换,而不要使用CloudFront,这会给你的云配置增加额外的复杂性。

8i9zcol2

8i9zcol22#

就像@ErmiyaEskandary说的,你可以直接用HLS来解决你的问题,这可能是个好主意,但是你不应该等到整个MP4文件下载完才用AVPlayer播放。这个问题实际上根本不是AVPlayer或字节范围请求的问题,而是你的MP4文件是如何格式化的。
你可能有你的MP4文件配置错误的流。MP4的有一个元数据部分称为MOOV原子。默认情况下,许多编码器把它放在文件的后面。在这种情况下,播放器将不得不下载整个文件之前,它可以开始播放。
对于流式用例,这需要放在文件的前面,播放器只需要缓冲MOOV原子,就可以在加载数据时开始播放视频。
您可以在启用快速启动标志的情况下使用ffmpeg将MOOV原子移动到文件的开头。

相关问题