首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >AVPlayerLoop非无缝循环- Swift 4

AVPlayerLoop非无缝循环- Swift 4
EN

Stack Overflow用户
提问于 2018-12-20 21:45:30
回答 3查看 3.1K关注 0票数 3

我的问题是:我试图做无缝循环(我打算使我的AVPlayer或AVPlayerQueue,循环没有任何延迟之间的回放)。因此,例如,如果我做了一个视频,并去回放,它应该是无休止的循环之间没有任何闪点或延迟的循环。

我编写了下面的代码(它也是从示例代码中直接编写的):

代码语言:javascript
复制
    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)。但什么也没起作用。

如能提供任何帮助,将不胜感激:)

EN

回答 3

Stack Overflow用户

回答已采纳

发布于 2018-12-24 00:47:29

当循环资产时要记住的一件事是,音频和视频轨道可以有不同的偏移量和不同的持续时间,在循环时会产生“闪烁”。这种微小的差异在记录的资产中是相当普遍的。

迭代轨道和打印时间范围可以帮助检测这样的情况:for track in asset.tracks { print( track.mediaType); CMTimeRangeShow( track.timeRange); }

若要将音频和视频轨道修剪为相同的开始时间和相同持续时间,请获取轨道的公共时间范围,然后将此时间范围从原始资产插入到新的AVMutableComposition中。通常,您还希望保留像视频轨道的方向这样的属性:

代码语言:javascript
复制
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命令行电影修整实用程序构建。

票数 1
EN

Stack Overflow用户

发布于 2018-12-20 23:25:56

如果在比赛结束时尝试

代码语言:javascript
复制
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秒或其他什么)来管理您自己的游戏,并设置为这样的游戏

代码语言:javascript
复制
    player.seekToTime(seekTimeInProgress, toleranceBefore: kCMTimeZero,
            toleranceAfter: kCMTimeZero, completionHandler: ...

kCMTimeZero非常重要,否则时间就不太准确了。最后,我发现在重新启动vids时有一个加载时间,这取决于iOS电话类型、视频长度和播放次数,所以如果在消除了时间问题之后仍然存在这种延迟,您可能不得不在UX中考虑。

票数 0
EN

Stack Overflow用户

发布于 2018-12-24 01:51:28

@NoHalfBits的答案很好,但我也找到了另一个解决方案。我基本上从播放者的资产中得到了视频和声音mediaTypes的交集时间范围。之后,在调用时,我在参数中添加了intersectionTimeRange作为timeRange:

代码语言:javascript
复制
playerLooper = AVPlayerLooper(playerQueue:_, playerItem:_, timeRange: intersectionTimeRange)

这会成功的!要获得每个元素的timeRanges,请为播放者的资产设置一个for循环。

票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/53876456

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档