AVFoundation播放连续的视频片段

时间:2015-02-22 15:10:38

标签: swift ios8 avfoundation avqueueplayer mpmediaplayercontroller

我正在开发一款iOS应用,它涉及从网络服务器中提取属于流的一部分的视频片段,并在应用内连续播放。 经过一番研究,我决定使用AVQueuePlayer。每次从服务器获取MP4文件并将其存储在NSData对象中时,我都会创建一个AVPlayerItem并将其附加到队列中。此外,我收听AVPlayerItemDidPlayToEndTimeNotification通知,我前进到下一个项目。 每次我从电影片段前进到另一个时,我面临的问题是一个恼人的小延迟。我尝试在iMovie上组合片段,并且无法判断片段何时结束而另一片段开始。 如何消除连续片段之间的小暂停/滞后?

这是我的代码:

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。滞后并没有消失。

有任何线索吗?

1 个答案:

答案 0 :(得分:2)

将AVMutableComposition与AVPlayer一起使用而不是AVQueuePlayer。 我使用Objective-C,所以我的样本不在Swift中,但Swift代码非常相似。

基本逻辑是:

  1. 创建AVMutableComposition

    composition = [AVMutableComposition new];

  2. 为其添加一条可变音轨

    AVMutableCompositionTrack * track = [_composition addMutableTrackWithMediaType:AVMediaTypeVideo in preferredTrackID:kCMPersistentTrackID_Invalid];

  3. 在循环中:为每个视频片段创建一个AVAssetTrack

    AVURLAsset * asset = ...;

    AVAssetTrack * assetTrack = [[asset tracksWithMediaType:AVMediaTypeVideo] objectAtIndex:0];

    CMTimeRange timeRange = assetTrack.timeRange;

  4. 将片段添加到您想要播放的确切时间

    [track insertTimeRange:timeRange ofTrack:assetTrack atTime:time error:& error];

    1. 播放你的作品
    2. AVPlayerItem * playerItem = [AVPlayerItem playerItemWithAsset:composition]; myPlayer = [[AVPlayer alloc] initWithPlayerItem:playerItem];

      ...