在exportAsynchronouslyWithCompletionHandler中创建AVPlayer时,在看到视频之前有很长的延迟

2023-11-29

播放从AVAssetExportSession,您在看到视频之前很久就能听到音频。音频会立即播放,但视频仅在录制循环几次(即开始和结束)后才会出现。换句话说,您在看到任何图像之前会多次听到视频中的音频。

我们在 iOS 8 上使用 AutoLayout。

使用以下测试,我们将问题隔离到exportAsynchronouslyWithCompletionHandler。在这两个代码块中,我们播放现有视频(与导出无关),因此导出过程已作为变量被消除。

Code 1在开始时同时播放视频和音频,而Code 2仅在开始时播放音频,并在延迟 10-60 秒后显示视频(在视频循环几次后)。

两个代码块之间的唯一区别是用途exportAsynchronouslyWithCompletionHandler播放该视频,而另一个则不播放。

帮助?是否可以先导出音频并在视频之前准备好播放?与在不同线程上发生的导出有关吗?

func initPlayer(videoURL: NSURL) {
    // Create player
    player = AVPlayer(URL: videoURL)
    let playerItem = player.currentItem
    let asset = playerItem.asset
    playerLayer = AVPlayerLayer(player: player)
    playerLayer.frame = videoView.frame
    view.layer.addSublayer(playerLayer)
    player.seekToTime(kCMTimeZero)
    player.actionAtItemEnd = .None
    player.play()

    // Get notified when video done for looping purposes
    NSNotificationCenter.defaultCenter().addObserver(self, selector: "playerItemDidReachEnd:", name: AVPlayerItemDidPlayToEndTimeNotification, object: playerItem)

    // Log status
    println("Initialized video player: \(CMTimeGetSeconds(asset.duration)) seconds & \(asset.tracks.count) tracks for \(videoURL)")
}

func playExistingVideo() {
    let filename = "/ChopsticksVideo.mp4"
    let allPaths = NSSearchPathForDirectoriesInDomains(.DocumentDirectory, .UserDomainMask, true)
    let docsPath = allPaths[0] as! NSString
    let exportPath = docsPath.stringByAppendingFormat(filename)
    let exportURL = NSURL.fileURLWithPath(exportPath as String)!

    initPlayer(exportURL)
}

Code 1:

    // Create exporter
    let exporter = AVAssetExportSession(asset: mainComposition, presetName: AVAssetExportPresetHighestQuality)
    exporter.videoComposition = videoComposition
    exporter.outputFileType = AVFileTypeMPEG4
    exporter.outputURL = exportURL
    exporter.shouldOptimizeForNetworkUse = true

    playExistingVideo()

Code 2:

    // Create exporter
    let exporter = AVAssetExportSession(asset: mainComposition, presetName: AVAssetExportPresetHighestQuality)
    exporter.videoComposition = videoComposition
    exporter.outputFileType = AVFileTypeMPEG4
    exporter.outputURL = exportURL
    exporter.shouldOptimizeForNetworkUse = true

    // -- Export video
    exporter.exportAsynchronouslyWithCompletionHandler({
        self.playExistingVideo()
    })

我会建议问题就在这里:

    // Create player
    player = AVPlayer(URL: videoURL)
    let playerItem = player.currentItem
    let asset = playerItem.asset
    playerLayer = AVPlayerLayer(player: player)
    playerLayer.frame = videoView.frame
    view.layer.addSublayer(playerLayer)
    player.seekToTime(kCMTimeZero)
    player.actionAtItemEnd = .None
    player.play()

你看,当你从视频 URL 创建一个 AVPlayer 时,它就出现了还没准备好玩。它通常可以很快开始播放音频,但视频需要更长的时间来准备。这可以解释为什么看东西会出现延迟。

好吧,你不用等待视频准备好,而是直接说play()立即地。这是我的建议。我建议你做的就是我做的在我的书中解释(这是实际代码的链接):创建播放器和图层,然后设置 KVO,以便在播放器准备好显示时通知您,以及then添加图层并开始播放。

另外,我还有一个建议。在我看来,您运行该代码、设置界面(使用该层)并说存在危险play(), 在后台线程上。这肯定会导致各种延误。您似乎假设完成处理程序来自exportAsynchronouslyWithCompletionHandler:正在主线程上调用 - 您将直接调用下一个方法,然后继续设置您的界面。这是一个非常危险的假设。根据我的经验,你永远不应该假设anyAVFoundation 完成处理程序位于主线程上。你应该使用以下命令进入主线程dispatch_async在您的完成处理程序中,并且仅从那里继续。如果您查看我链接到的代码,您会发现我这样做很小心。

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

在exportAsynchronouslyWithCompletionHandler中创建AVPlayer时,在看到视频之前有很长的延迟 的相关文章

随机推荐