如何减少iOS AVPlayer启动延迟 [英] How to reduce iOS AVPlayer start delay

查看:1703
本文介绍了如何减少iOS AVPlayer启动延迟的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

注意,对于以下问题:所有资产都是设备上的本地资产 - 没有网络流媒体正在发生。这些视频包含音轨。



我正在开发一个iOS应用程序,该应用程序需要播放视频文件,延迟时间最短才能启动相关视频片段。不幸的是,在我们真正需要启动之前,我们不知道下一个具体的视频剪辑。具体来说:当一个视频片段正在播放时,我们将知道下一组(大约)10个视频片段是什么,但我们不知道究竟是哪一个,直到立即播放下一个片段为止。



我看到的实际启动延迟是在视频播放器上调用 addBoundaryTimeObserverForTimes ,时间段看视频实际开始播放的时间是一毫秒,我在代码中的第一个位置加上时间戳的差异,表示开始播放哪个资产。



<从我迄今为止所看到的,我发现使用 AVAsset 的组合加载,然后创建 AVPlayerItem 一旦它准备就绪,然后在我打电话之前等待 AVPlayerStatusReadyToPlay ,往往需要1到3秒才能开始剪辑。



我已经切换到我认为大致相当的东西:调用 [AVPlayer项目playerItemWithURL:] 并等待 AVPlayerItemStatusReadyToPlay 进行播放。大致相同的性能。



我观察到的一件事是第一个AVPlayer项目加载比其余项目慢。似乎有一个想法是在尝试播放第一个视频之前用短/空资产预先飞行AVPlayer可能是一个很好的通用做法。 [第一次AVAudioPlayer启动缓慢播放声音



我希望尽可能减少视频播放时间,并且有一些想法可以试验,但是像任何可能提供帮助的人的指导一样。



更新:想法7,如下所示,as-implemented产生大约500 ms的切换时间。这是一个改进,但它更好地让它更快。



想法1:使用N AVPlayers(不会工作)



使用~10 AVPPlayer 对象并启动和暂停所有~10个剪辑,一旦我们知道我们真正需要哪一个,切换到并取消暂停正确的 AVPlayer ,并在下一个周期重新开始。



我认为这不行,因为我已经读过iOS中大约有4个活跃 AVPlayer的的限制。这里有人在StackOverflow上询问此事,并发现了4个AVPlayer限制:快速-switching-between-videos-using-avfoundation



创意2:使用AVQueuePlayer(无效)



我不相信将10 AVPlayerItems 推入 AVQueuePlayer 会预先加载它们以便无缝启动。 AVQueuePlayer 是一个队列,我认为这只会使队列中的下一个视频准备好立即播放。我不知道我们想要播放的约10个视频中的哪一个,直到开始那个视频。 ios-avplayer-video-preloading



创意3:在后台加载,播放和保留 AVPlayerItems (不是100%肯定 - 但看起来不太好)



我正在研究在后台加载和播放每个视频片段的第一秒是否有任何好处(抑制视频和音频输出),并保留每个视频和音频输出的参考 AVPlayerItem ,当我们知道哪个项目需要真实播放时,将其中的一个交换掉,并将后台AVPlayer与活动的一个交换。冲洗并重复。



理论将是最近播放的 AVPlayer / AVPlayerItem 可能仍然保留一些准备好的资源这将使后续播放更快。到目前为止,我还没有看到这方面的好处,但我可能没有为背景正确设置 AVPlayerLayer 。我怀疑这会真正改善我所见过的东西。



想法4:使用不同的文件格式 - 也许加载速度更快?



我目前正在使用.m4v(视频-MPEG4)H.264格式。 H.264有很多不同的编解码器选项,因此有些选项可能比其他选项更快。我发现使用更高级的设置会缩短文件大小会增加搜索时间,但是找不到任何其他选项。



创意5:无损视频格式+ AVQueuePlayer的组合



如果有一种快速加载的视频格式,但也许文件大小是疯狂的,想法可能是预先准备每个视频片段的前10秒,其版本臃肿但加载速度更快,但用H.264编码的资产支持。使用AVQueuePlayer,并以未压缩文件格式添加前10秒,然后使用H.264中的一个,最多可达10秒的准备/预加载时间。因此,我将获得两个世界中最好的:快速的开始时间,也可以从更紧凑的格式中受益。



想法6:使用非-standard AVPlayer /自己编写/使用别人的



根据我的需要,也许我不能使用AVPlayer,但必须求助于AVAssetReader,解码前几秒(可能将原始文件写入磁盘),当涉及到播放时,请使用原始格式快速播放。对我来说似乎是一个巨大的项目,如果我以一种天真的方式去做,那就不清楚/不太可能更好地工作了。每个解码和未压缩的视频帧为2.25 MB。天真地说 - 如果我们以约30 fps的速度播放视频,我最终会得到~60 MB / s的磁盘读取要求,这可能是不可能的/推动它。显然我们必须进行一定程度的图像压缩(也许是通过PVRTC进行原生的openGL / es压缩格式)......但这有点疯狂。也许有一个我可以使用的图书馆?



想法7:将所有内容合并为一个电影资产,并且seekToTime



一个可能比上述更容易的想法是将所有内容组合成一个电影,并使用seekToTime。问题是我们会在这个地方跳来跳去。基本上随机访问电影。我认为这可能实际上没问题: avplayer-movie-playing-lag-in-ios5



您认为哪种方法最好?到目前为止,我在减少延迟方面没有取得太大进展。

解决方案

你应该先尝试#7选项,只是为了看看你能不能正常工作。我怀疑它实际上不能满足您的需求,因为搜索时间可能不够快,无法在剪辑之间无缝切换。如果您尝试了它并且它失败了,那么我建议您选择4/6选项并查看我专门为此目的设计的iOS库,只需在AVAnimator上进行快速谷歌搜索以了解更多信息。我的库可以实现无缝循环并从一个剪辑切换到另一个剪辑,它非常快,因为必须事先将视频解码为文件。在您的情况下,所有10个视频片段在开始之前都会被解码为文件,但之后在它们之间切换会很快。


Note, for the below question: All assets are local on the device -- no network streaming is taking place. The videos contain audio tracks.

I'm working on an iOS application that requires playing video files with minimum delay to start the video clip in question. Unfortunately we do not know what specific video clip is next until we actually need to start it up. Specifically: When one video clip is playing, we will know what the next set of (roughly) 10 video clips are, but we don't know which one exactly, until it comes time to 'immediately' play the next clip.

What I've done to look at actual start delays is to call addBoundaryTimeObserverForTimes on the video player, with a time period of one millisecond to see when the video actually started to play, and I take the difference of that time stamp with the first place in the code that indicates which asset to start playing.

From what I've seen thus-far, I have found that using the combination of AVAsset loading, and then creating an AVPlayerItem from that once it's ready, and then waiting for AVPlayerStatusReadyToPlay before I call play, tends to take between 1 and 3 seconds to start the clip.

I've since switched to what I think is roughly equivalent: calling [AVPlayerItem playerItemWithURL:] and waiting for AVPlayerItemStatusReadyToPlay to play. Roughly same performance.

One thing I'm observing is that the first AVPlayer item load is slower than the rest. Seems one idea is to pre-flight the AVPlayer with a short / empty asset before trying to play the first video might be of good general practice. [Slow start for AVAudioPlayer the first time a sound is played

I'd love to get the video start times down as much as possible, and have some ideas of things to experiment with, but would like some guidance from anyone that might be able to help.

Update: idea 7, below, as-implemented yields switching times of around 500 ms. This is an improvement, but it it'd be nice to get this even faster.

Idea 1: Use N AVPlayers (won't work)

Using ~ 10 AVPPlayer objects and start-and-pause all ~ 10 clips, and once we know which one we really need, switch to, and un-pause the correct AVPlayer, and start all over again for the next cycle.

I don't think this works, because I've read there is roughly a limit of 4 active AVPlayer's in iOS. There was someone asking about this on StackOverflow here, and found out about the 4 AVPlayer limit: fast-switching-between-videos-using-avfoundation

Idea 2: Use AVQueuePlayer (won't work)

I don't believe that shoving 10 AVPlayerItems into an AVQueuePlayer would pre-load them all for seamless start. AVQueuePlayer is a queue, and I think it really only makes the next video in the queue ready for immediate playback. I don't know which one out of ~10 videos we do want to play back, until it's time to start that one. ios-avplayer-video-preloading

Idea 3: Load, Play, and retain AVPlayerItems in background (not 100% sure yet -- but not looking good)

I'm looking at if there is any benefit to load and play the first second of each video clip in the background (suppress video and audio output), and keep a reference to each AVPlayerItem, and when we know which item needs to be played for real, swap that one in, and swap the background AVPlayer with the active one. Rinse and Repeat.

The theory would be that recently played AVPlayer/AVPlayerItem's may still hold some prepared resources which would make subsequent playback faster. So far, I have not seen benefits from this, but I might not have the AVPlayerLayer setup correctly for the background. I doubt this will really improve things from what I've seen.

Idea 4: Use a different file format -- maybe one that is faster to load?

I'm currently using .m4v's (video-MPEG4) H.264 format. H.264 has a lot of different codec options, so it's possible that some options are faster to seek than others. I have found that using more advanced settings that make the file size smaller increase the seek time, but have not found any options that go the other way.

Idea 5: Combination of lossless video format + AVQueuePlayer

If there is a video format that is fast to load, but maybe where the file size is insane, one idea might be to pre-prepare the first 10 seconds of each video clip with a version that is bloated but faster to load, but back that up with an asset that is encoded in H.264. Use an AVQueuePlayer, and add the first 10 seconds in the uncompressed file format, and follow that up with one that is in H.264 which gets up to 10 seconds of prepare/preload time. So I'd get 'the best' of both worlds: fast start times, but also benefits from a more compact format.

Idea 6: Use a non-standard AVPlayer / write my own / use someone else's

Given my needs, maybe I can't use AVPlayer, but have to resort to AVAssetReader, and decode the first few seconds (possibly write raw file to disk), and when it comes to playback, make use of the raw format to play it back fast. Seems like a huge project to me, and if I go about it in a naive way, it's unclear / unlikely to even work better. Each decoded and uncompressed video frame is 2.25 MB. Naively speaking -- if we go with ~ 30 fps for the video, I'd end up with ~60 MB/s read-from-disk requirement, which is probably impossible / pushing it. Obviously we'd have to do some level of image compression (perhaps native openGL/es compression formats via PVRTC)... but that's kind crazy. Maybe there is a library out there that I can use?

Idea 7: Combine everything into a single movie asset, and seekToTime

One idea that might be easier than some of the above, is to combine everything into a single movie, and use seekToTime. The thing is that we'd be jumping all around the place. Essentially random access into the movie. I think this may actually work out okay: avplayer-movie-playing-lag-in-ios5

Which approach do you think would be best? So far, I've not made that much progress in terms of reducing the lag.

解决方案

You should try option #7 first, just to see if you can get that working. I suspect that it will not actually work for your needs since the seek time will likely not be fast enough to give you seamless switching between clips. If you try that and it fails, then I would advise that you do option 4/6 and take a look at my iOS library designed specifically for this purpose, just do a quick google search on AVAnimator to find out more. My library makes it possible to implement seamless loops and switching from one clip to another, it is very fast because video has to be decoded into a file before hand. In your case, all 10 video clips would get decoded into files before you begin, but then switching between them would be fast.

这篇关于如何减少iOS AVPlayer启动延迟的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆