ios - 循环播放 swift video avplayer swift

标签 ios swift

我试过这个:How do you loop AVPlayer in Swift?但是当视频结束时崩溃

我的代码:

 super.viewDidLoad()
    var moviePlayer : MPMoviePlayerController?
    let myPlayerView = UIView(frame: self.view.bounds)
    myPlayerView.backgroundColor = UIColor.blackColor()
    view.addSubview(myPlayerView)

    var urlpath = NSBundle.mainBundle().pathForResource("bgivd", ofType: "mp4")
    let url:NSURL = NSURL.fileURLWithPath(urlpath!)!

    // Make a player
    let myPlayer = AVPlayer(URL: url)
    myPlayer.play()


    let avLayer = AVPlayerLayer(player: myPlayer)
    avLayer.frame = myPlayerView.bounds
    myPlayerView.layer.addSublayer(avLayer)
    myPlayerView.superview?.sendSubviewToBack(myPlayerView)

我的循环代码

NSNotificationCenter.defaultCenter().addObserver(self,
    selector: "playerItemDidReachEnd:",
    name: AVPlayerItemDidPlayToEndTimeNotification,
    object: myPlayer.currentItem)

    func playerItemDidReachEnd(notification: NSNotification) {
        myPlayer.seekToTime(kCMTimeZero)
        myPlayer.play()
    }

错误日志: http://pastebin.com/bN2fc29G

出于某种原因,stackoverflow 中的代码出现故障,所以我将其放入了 pastebin

最佳答案

不久前我给自己做了一个自定义的 Looping AVPlayer,欢迎使用/评论!

protocol LoopingPlayerProgressDelegate: class {
    func loopingPlayer(loopingPlayer: LoopingPlayer, didLoad percentage: Float)
    func loopingPlayer(loopingPlayer: LoopingPlayer, didFinishLoading succeeded: Bool)
}

class LoopingPlayer: AVPlayer {

    weak var progressDelegate: LoopingPlayerProgressDelegate?

    var loopCount: Double = 0
    var timer: NSTimer?

    override init() {
        super.init()
        self.commonInit()
    }

    override init(URL url: NSURL!) {
        super.init(URL: url)
        self.commonInit()
    }

    override init(playerItem item: AVPlayerItem!) {
        super.init(playerItem: item)
        self.commonInit()
    }

    func commonInit() {
        self.addObserver(self, forKeyPath: "currentItem", options: .New, context: nil)
        self.actionAtItemEnd = .None
        NSNotificationCenter.defaultCenter().addObserver(self, selector:"playerDidPlayToEndTimeNotification:", name:AVPlayerItemDidPlayToEndTimeNotification, object:nil)
        if mutePlayers == true {
            self.volume = 0.0
        }
        NSNotificationCenter.defaultCenter().addObserver(self, selector:"mute", name:"MutePlayers", object:nil)
        NSNotificationCenter.defaultCenter().addObserver(self, selector:"unmute", name:"UnmutePlayers", object:nil)
    }

    deinit {
        self.timer?.invalidate()
        self.removeObserver(self, forKeyPath: "currentItem")
        NSNotificationCenter.defaultCenter().removeObserver(self)
    }

    func mute() {
        self.volume = 0.0
    }

    func unmute() {
        self.volume = 1.0
    }

    var playableDuration: CMTime {
        get {
            if let item: AnyObject = self.currentItem?.loadedTimeRanges?.first {
                if let timeRange = item.CMTimeRangeValue {
                    let playableDuration = CMTimeAdd(timeRange.start, timeRange.duration)
                    return playableDuration
                }
            }
            return kCMTimeZero
        }
    }

    var loadingProgress: Float {
        get {
            if (self.currentItem == nil) {
                self.timer?.invalidate()
                self.progressDelegate?.loopingPlayer(self, didFinishLoading: false)
                return 0
            }
            let playableDurationInSeconds = CMTimeGetSeconds(self.playableDuration)
            let totalDurationInSeconds = CMTimeGetSeconds(self.currentItem.duration)
            if (totalDurationInSeconds.isNormal) {
                var progress = Float(playableDurationInSeconds / totalDurationInSeconds)
                self.progressDelegate?.loopingPlayer(self, didLoad: progress)
                if (progress > 0.90) {
                    self.progressDelegate?.loopingPlayer(self, didFinishLoading: true)
                    self.timer?.invalidate()
                }
                return progress
            }
            return 0
        }
    }

    func playerDidPlayToEndTimeNotification(notification: NSNotification) {
        let playerItem: AVPlayerItem = notification.object as! AVPlayerItem
        if (playerItem != self.currentItem) {
            return
        }
        self.seekToTime(kCMTimeZero)
        self.play()
        loopCount += 1
    }

    override func observeValueForKeyPath(keyPath: String, ofObject object: AnyObject, change: [NSObject : AnyObject], context: UnsafeMutablePointer<Void>) {
        if keyPath == "currentItem" {
            self.timer?.invalidate()
            self.timer = NSTimer.scheduledTimerWithTimeInterval(0.1, target: self, selector: "loadingProgress", userInfo: nil, repeats: true)
        }
    }
}

我制作它已经有一段时间了,因此它可能有点灰尘。对此感到抱歉!

它也适用于 HLS 文件 ;)

希望这会有所帮助!

关于ios - 循环播放 swift video avplayer swift,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/31519732/

相关文章:

ios - 如何以编程方式关闭铃声?

ios - 尝试使用依赖注入(inject)设置核心数据堆栈

ios - AWS S3 : file not uploading in folder in ios

ios - 具有多重验证的对象数组过滤器

Swift - 验证 UITextField

ios - 利用 MapKit 呈现自定义图像 - iOS

php - 如何使用 Swift 将字符串加密为 base64 中的 sha1?

ios - 为什么点击 UICollectionViewCell 上的文本会消失?

ios - swift NSURL, "cell.itemImageView.setImageWithURL"进入数组

ios - iOS Objective-C阻止警告:控件到达非空函数的末尾