我的问题是:我试图做无缝循环(我打算使我的AVPlayer或AVPlayerQueue,循环没有任何延迟之间的回放)。因此,例如,如果我做了一个视频,并去回放,它应该是无休止的循环之间没有任何闪点或延迟的循环。
我编写了下面的代码(它也是从示例代码中直接编写的):
var playerQQ: AVQueuePlayer!
var playerLayur: AVPlayerLayer!
var playerEyetem: AVPlayerItem!
var playerLooper: AVPlayerLooper!
func playRecordedVideo(videoURL: URL) {
playerQQ = AVQueuePlayer()
playerLayur = AVPlayerLayer(player: playerQQ)
playerLayur.frame = (camBaseLayer?.bounds)!
camBaseLayer?.layer.insertSublayer(playerLayur, above: previewLayer)
playerEyetem = AVPlayerItem(url: videoURL)
playerLooper = AVPlayerLooper(player: playerQQ, templateItem: playerEyetem)
playerQQ.play()
}上面的代码并不是无缝循环的;它在当前播放器的末尾和下一个播放器之间有闪烁点。我已经尝试了很多找到这个问题,并在网上搜索,但没有找到解决办法。此外,我一直在尝试NSNotifications和其他方法,包括在播放器完成播放时设置Player.seek(to: 0)。但什么也没起作用。
如能提供任何帮助,将不胜感激:)
发布于 2018-12-24 00:47:29
当循环资产时要记住的一件事是,音频和视频轨道可以有不同的偏移量和不同的持续时间,在循环时会产生“闪烁”。这种微小的差异在记录的资产中是相当普遍的。
迭代轨道和打印时间范围可以帮助检测这样的情况:for track in asset.tracks { print( track.mediaType); CMTimeRangeShow( track.timeRange); }
若要将音频和视频轨道修剪为相同的开始时间和相同持续时间,请获取轨道的公共时间范围,然后将此时间范围从原始资产插入到新的AVMutableComposition中。通常,您还希望保留像视频轨道的方向这样的属性:
let asset: AVAsset = (your asset initialization here)
let videoTrack: AVAssetTrack = asset.tracks(withMediaType: .video).first!
let audioTrack: AVAssetTrack = asset.tracks(withMediaType: .audio).first!
// calculate common time range of audio and video track
let timeRange: CMTimeRange = CMTimeRangeGetIntersection( (videoTrack.timeRange), (audioTrack.timeRange))
let composition: AVMutableComposition = AVMutableComposition()
try composition.insertTimeRange(timeRange, of: asset, at: kCMTimeZero)
// preserve orientation
composition.tracks(withMediaType: .video).first!.preferredTransform = videoTrack.preferredTransform因为AVMutableComposition是AVAsset的子类,所以它可以用于AVPlayerLooper-based循环回放或使用AVAssetExportSession导出。
我在github上放置了一个更完整的微调实现:https://github.com/fluthaus/NHBAVAssetTrimming。它更健壮,处理多个音轨,保留更多的属性,既可以轻松集成到项目中,也可以作为独立的macOS命令行电影修整实用程序构建。
发布于 2018-12-20 23:25:56
如果在比赛结束时尝试
NotificationCenter.default.addObserver(self,
selector: #selector(playerItemDidReachEnd(notification:)),
name: Notification.Name.AVPlayerItemDidPlayToEndTime,
object: avPlayer?.currentItem)
@objc func playerItemDidReachEnd(notification: Notification) {
if let playerItem: AVPlayerItem = notification.object as? AVPlayerItem {
playerItem.seek(to: kCMTimeZero, completionHandler: nil)
}
}如果不是,我建议使用dTime (触发NSTimer 1/30秒或其他什么)来管理您自己的游戏,并设置为这样的游戏
player.seekToTime(seekTimeInProgress, toleranceBefore: kCMTimeZero,
toleranceAfter: kCMTimeZero, completionHandler: ...kCMTimeZero非常重要,否则时间就不太准确了。最后,我发现在重新启动vids时有一个加载时间,这取决于iOS电话类型、视频长度和播放次数,所以如果在消除了时间问题之后仍然存在这种延迟,您可能不得不在UX中考虑。
发布于 2018-12-24 01:51:28
@NoHalfBits的答案很好,但我也找到了另一个解决方案。我基本上从播放者的资产中得到了视频和声音mediaTypes的交集时间范围。之后,在调用时,我在参数中添加了intersectionTimeRange作为timeRange:
playerLooper = AVPlayerLooper(playerQueue:_, playerItem:_, timeRange: intersectionTimeRange)这会成功的!要获得每个元素的timeRanges,请为播放者的资产设置一个for循环。
https://stackoverflow.com/questions/53876456
复制相似问题