AVFoundation 播放连续的视频片段
AVFoundation play consecutive video fragments
我正在开发一个 iOS 应用程序,该应用程序涉及从 Web 服务器获取属于流的一部分的视频片段,并在应用程序内连续播放它们。
经过一些研究,我决定使用 AVQueuePlayer。每次我从服务器获取 MP4 文件并将其存储在 NSData 对象中时,我都会创建一个 AVPlayerItem 并将其附加到队列中。此外,我会在前进到下一个项目时收听 AVPlayerItemDidPlayToEndTimeNotification 通知。
我面临的问题是每次从一个电影片段前进到另一个片段时都会出现恼人的小延迟。我尝试在 iMovie 上组合这些片段,但无法分辨一个片段何时结束而另一个片段何时开始。
如何去除连续片段之间的小 pause/lag?
这是我的代码:
import UIKit
import MediaPlayer
import AVFoundation
class WatchStream: UIViewController, StreamManagerDelegate {
var subscriber : Subscriber!
//Model object responsible for fetching mp4 fragments
var streamManager = StreamManager()
var queue : AVQueuePlayer!
override func viewDidLoad() {
super.viewDidLoad()
//Set up the manager
streamManager.streamID = subscriber.streamid
streamManager.delegate = self
//Register for notification once movie player finished
NSNotificationCenter.defaultCenter().addObserver(self, selector: "AVPlayerFinishedPlaying:", name:AVPlayerItemDidPlayToEndTimeNotification, object: nil)
queue = AVQueuePlayer()
var playerLayer = AVPlayerLayer(player: queue)
playerLayer.frame = self.view.bounds
self.view.layer.insertSublayer(playerLayer, below: self.navigationController!.navigationBar.layer)
}
//Delegate method notifying that a new fragment is ready to be watched
func streamManagerLoadedStream(fragment: Int, manager: StreamManager) {
var url = streamManager.fetchFragmentToPlay()
if url == nil {return}
var playerItem = AVPlayerItem(URL: url!)
queue.insertItem(playerItem, afterItem: nil)
queue.play()
}
//Method called once name:AVPlayerItemDidPlayToEndTimeNotification fires
func AVPlayerFinishedPlaying(notification : NSNotification) {
//We need to switch to second one
queue.advanceToNextItem()
if queue.status == AVPlayerStatus.ReadyToPlay {
queue.play()
}
}
}
同样,我的问题是在推进 AVQueuePlayer 时。它导致了这种不可能存在的滞后。电影片段很小(每个 1-2 秒)并且应该是连续的,因为作为一个流。
我尝试使用 2 个 AVQueuePlayers 和 2 个 AVPlayerLayers,但没有解决问题。
我还尝试使用 MPMoviePlayerController 并在每次播放结束时更新其 contentURL。延迟并没有消失。
有线索吗?
将 AVMutableComposition 与 AVPlayer 一起使用,而不是 AVQueuePlayer。
我使用Objective-C,所以我的示例不在Swift,但是Swift代码会很相似。
基本逻辑是这样的:
创建一个 AVMutableComposition
组合 = [AVMutableComposition 新];
向其中添加一个可变轨道
AVMutableCompositionTrack *track = [_composition addMutableTrackWithMediaType:AVMediaTypeVideo 在 preferredTrackID:kCMPersistentTrackID_Invalid];
在循环中:为每个视频片段创建一个 AVAssetTrack
AVURLAsset* 资产 = ...;
AVAssetTrack *assetTrack = [[资产 tracksWithMediaType:AVMediaTypeVideo] objectAtIndex:0];
CMTimeRange timeRange = assetTrack.timeRange;
将片段添加到您的曲目中,以达到您想要播放的确切时间
[轨道insertTimeRange:timeRangeofTrack:assetTrackatTime:time错误:&error];
- 演奏你的作品
AVPlayerItem *playerItem = [AVPlayerItem playerItemWithAsset:composition];
myPlayer = [[AVPlayer alloc] initWithPlayerItem:playerItem];
...
我正在开发一个 iOS 应用程序,该应用程序涉及从 Web 服务器获取属于流的一部分的视频片段,并在应用程序内连续播放它们。 经过一些研究,我决定使用 AVQueuePlayer。每次我从服务器获取 MP4 文件并将其存储在 NSData 对象中时,我都会创建一个 AVPlayerItem 并将其附加到队列中。此外,我会在前进到下一个项目时收听 AVPlayerItemDidPlayToEndTimeNotification 通知。 我面临的问题是每次从一个电影片段前进到另一个片段时都会出现恼人的小延迟。我尝试在 iMovie 上组合这些片段,但无法分辨一个片段何时结束而另一个片段何时开始。 如何去除连续片段之间的小 pause/lag?
这是我的代码:
import UIKit
import MediaPlayer
import AVFoundation
class WatchStream: UIViewController, StreamManagerDelegate {
var subscriber : Subscriber!
//Model object responsible for fetching mp4 fragments
var streamManager = StreamManager()
var queue : AVQueuePlayer!
override func viewDidLoad() {
super.viewDidLoad()
//Set up the manager
streamManager.streamID = subscriber.streamid
streamManager.delegate = self
//Register for notification once movie player finished
NSNotificationCenter.defaultCenter().addObserver(self, selector: "AVPlayerFinishedPlaying:", name:AVPlayerItemDidPlayToEndTimeNotification, object: nil)
queue = AVQueuePlayer()
var playerLayer = AVPlayerLayer(player: queue)
playerLayer.frame = self.view.bounds
self.view.layer.insertSublayer(playerLayer, below: self.navigationController!.navigationBar.layer)
}
//Delegate method notifying that a new fragment is ready to be watched
func streamManagerLoadedStream(fragment: Int, manager: StreamManager) {
var url = streamManager.fetchFragmentToPlay()
if url == nil {return}
var playerItem = AVPlayerItem(URL: url!)
queue.insertItem(playerItem, afterItem: nil)
queue.play()
}
//Method called once name:AVPlayerItemDidPlayToEndTimeNotification fires
func AVPlayerFinishedPlaying(notification : NSNotification) {
//We need to switch to second one
queue.advanceToNextItem()
if queue.status == AVPlayerStatus.ReadyToPlay {
queue.play()
}
}
}
同样,我的问题是在推进 AVQueuePlayer 时。它导致了这种不可能存在的滞后。电影片段很小(每个 1-2 秒)并且应该是连续的,因为作为一个流。 我尝试使用 2 个 AVQueuePlayers 和 2 个 AVPlayerLayers,但没有解决问题。
我还尝试使用 MPMoviePlayerController 并在每次播放结束时更新其 contentURL。延迟并没有消失。
有线索吗?
将 AVMutableComposition 与 AVPlayer 一起使用,而不是 AVQueuePlayer。 我使用Objective-C,所以我的示例不在Swift,但是Swift代码会很相似。
基本逻辑是这样的:
创建一个 AVMutableComposition
组合 = [AVMutableComposition 新];
向其中添加一个可变轨道
AVMutableCompositionTrack *track = [_composition addMutableTrackWithMediaType:AVMediaTypeVideo 在 preferredTrackID:kCMPersistentTrackID_Invalid];
在循环中:为每个视频片段创建一个 AVAssetTrack
AVURLAsset* 资产 = ...;
AVAssetTrack *assetTrack = [[资产 tracksWithMediaType:AVMediaTypeVideo] objectAtIndex:0];
CMTimeRange timeRange = assetTrack.timeRange;
将片段添加到您的曲目中,以达到您想要播放的确切时间
[轨道insertTimeRange:timeRangeofTrack:assetTrackatTime:time错误:&error];
- 演奏你的作品
AVPlayerItem *playerItem = [AVPlayerItem playerItemWithAsset:composition]; myPlayer = [[AVPlayer alloc] initWithPlayerItem:playerItem];
...