[英]AVPlayerLoop not seamlessly looping - Swift 4
我的問題是:我正在嘗試進行無縫循環(我打算讓我的 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: zero) 。 但根本沒有任何效果。
任何幫助,將不勝感激:)
貌似是.mp4文件問題,把.mp4文件轉成.mov文件。 帶有 .mp4 文件的 AVPlayer 或 AVQueuePlayer 都可以正常工作。 這是我的代碼:
NotificationCenter.default.addObserver(forName: NSNotification.Name.AVPlayerItemDidPlayToEndTime, object: nil, queue: nil) { [weak self] (noty) in
self?.player?.seek(to: CMTime.zero)
self?.player?.play() }
要么
let asset = AVAsset(url: URL(fileURLWithPath: movPath))
let playerItem = AVPlayerItem(asset: asset)
let player = AVQueuePlayer(playerItem: playerItem)
playerLooper = AVPlayerLooper(player: player, templateItem: playerItem)
plyerLayer.frame = CGRect(x: 0, y: 88, width: kWidth, height: kWidth * 0.75)
plyerLayer.videoGravity = .resizeAspectFill
plyerLayer.player = player
view.layer.addSublayer(plyerLayer)
player.play()
循環資產時要記住的一件事是音頻和視頻軌道可以具有不同的偏移量和不同的持續時間,從而導致循環時出現“信號”。 這種微小的差異在記錄的資產中很常見。
遍歷軌道並打印時間范圍有助於檢測此類情況: for track in asset.tracks { print( track.mediaType); CMTimeRangeShow( track.timeRange); }
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
的循環播放,或使用AVAssetExportSession
導出。
我在 github 上放了一個更完整的修剪實現: https ://github.com/fluthaus/NHBAVAssetTrimming。 它更強大,可以處理多個軌道,保留更多屬性,並且可以輕松集成到項目中或構建為獨立的 macOS 命令行電影剪輯實用程序。
如果最后玩試試
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 非常重要,否則時間將不准確。 最后,我發現重新啟動視頻時有一個加載時間,具體取決於 iOS 手機類型和視頻的長度以及播放的次數,所以如果在消除時間問題后您仍然遇到這種延遲,您可能會被迫考慮您的用戶體驗。
@NoHalfBits 的回答很好,但我也找到了另一個解決方案。 我基本上從 playerItem 的資產中獲得了視頻和聲音媒體類型的交集時間范圍。 之后,我在調用時將 intersectionTimeRange 添加為參數中的 timeRange:
playerLooper = AVPlayerLooper(playerQueue:_, playerItem:_, timeRange: intersectionTimeRange)
這會起作用。 要獲取每個的 timeRanges,請為 playerItem 的資產設置一個 for 循環。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.