【发布时间】:2015-07-04 22:28:12
【问题描述】:
播放从AVAssetExportSession 导出的视频时,您会在看到视频之前很久就听到音频。音频立即播放,但视频仅在录制循环数次(即开始和结束)后出现。换句话说,在看到任何图像之前,您会多次听到视频中的音频。
我们在 iOS 8 上使用 AutoLayout。
使用以下测试,我们将问题隔离到exportAsynchronouslyWithCompletionHandler。在这两个代码块中,我们播放一个现有的视频——与导出无关——因此导出过程已作为一个变量被消除。
代码 1 在开始时同时播放视频和音频,而 代码 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)
}
代码 1:
// Create exporter
let exporter = AVAssetExportSession(asset: mainComposition, presetName: AVAssetExportPresetHighestQuality)
exporter.videoComposition = videoComposition
exporter.outputFileType = AVFileTypeMPEG4
exporter.outputURL = exportURL
exporter.shouldOptimizeForNetworkUse = true
playExistingVideo()
代码 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()
})
【问题讨论】:
-
@matt 感谢您的评论。是的,异步很好理解,但你能解释为什么音频在视频之前播放得很好吗?如果你仔细阅读这个问题,那就是问题的症结所在,消极性是不受欢迎的。如果这仅仅是一个异步延迟的问题,人们会期望音频和视频都会延迟。在这种情况下,只有视频会延迟,而音频会立即播放......
-
@matt 恕我直言,如果您拒绝仔细阅读问题,那么挑战某人并留下刻薄的话似乎是不合理的。关于“docsPath.stringByAppendingFormat”,这是在多个 SO 帖子中发现的文件名构造方法。由于我通常是 Swift 和 iOS 的新手,并且在早期使用文件 URL 时遇到了麻烦,所以我使用这种方法,因为有几个 SO 答案使用了这种格式。同样,如果您阅读了这个问题,“exportURL”是不相关的,因为我们在完成处理程序期间所做的只是调用 playExistingVideo。
-
@matt 虽然感谢您抽出宝贵时间发表评论,但我不欣赏这种消极情绪。即使假设我不理解异步的含义,我相信可能会有更具建设性的回应。不可否认,你是 SO 的支柱,比我重要得多,但也因为你的地位和频繁的贡献,我认为你承担了额外的负担来促进像我这样不那么重要的成员会努力效仿的尊重、文明的文化.无论如何,感谢您的其他贡献并帮助我们变得如此出色。
-
@matt 这些都是很好的问题。对困惑感到抱歉。这段代码是从一个更大的功能中提取的,在将事情归结为一个问题时,我一定是过于简单化了。目标:让用户录制一段 10 秒的视频并在视频上叠加文字。为此,我使用
AVAssetExportSession,但在播放视频供用户查看时,音频在图像出现之前很久就播放了。经过数小时的调试,我发现即使使用现有视频,问题仍然存在,并且似乎与使用exportAsynchronouslyWithCompletionHandler.有关 -
@matt 希望这能解释两个代码块:它将问题隔离到
exportAsynchronouslyWithCompletionHandler,,这意味着我可以通过调用playExistingVideo到@987654331 来重现播放问题(即,音频早于视频) @ 如果有帮助,这里是完整的功能(它提供了更多的上下文,但代码似乎不会直接导致问题,只会使问题更长的阅读时间而不增加太多):
标签: ios video autolayout avplayer avassetexportsession