美文网首页
AVPlayer代码解析

AVPlayer代码解析

作者: 写啥呢 | 来源:发表于2016-10-20 20:23 被阅读0次
    
    import UIKit
    import AVFoundation
    
    class PlayerViewController: UIViewController {
        
        @IBOutlet weak var playButton: UIButton!
        
        @IBOutlet weak var finishView: UIView!
        
        @IBOutlet weak var backButton: UIButton!
        
        @IBOutlet weak var bottomView: UIView!
        
        @IBOutlet weak var slider: UISlider!
        
        @IBOutlet weak var timeLabel: UILabel!
        
        @IBOutlet weak var bottomConatraint: NSLayoutConstraint!
        
        @IBOutlet weak var topConatraint: NSLayoutConstraint!
        //MARK: - 属性
        //播放路径
        var playUrlStr = ""
        //播放状态
        var isPlaying = true
        //是否已经加载成功
        var isLoadFinish = false
        
        
        //播放器
        lazy var player:AVPlayer = {
        
            //创建播放源
            let item = AVPlayerItem.init(URL: NSURL.init(string: self.playUrlStr)!)
            //print("播放源\(self.playUrlStr)")
            //创建播放器
            let tplayer = AVPlayer.init(playerItem: item)
            
            //添加观察者观察播放源中loadedTimeRanges属性的值的改变
            //给指定对象的指定属性添加观察者,观察对象属性的值的改变
            //(想要观察哪个对象的属性,就用哪个对象去调用addObserver方法),所有继承自NSOject的类都有addObserver方法
            //参数1:观察者(谁去观察对象的属性的改变)
            //参数2:对象的属性地址 person.name -> name对应的keyPath就是("name"),person.car.color,->color对应keypath就是("car.color")
            //参数3:当值发生改变的时候,观察者需要获取的值的类型(旧值/新值)
            //参数4:上下文(nil)
            item.addObserver(self, forKeyPath: "loadedTimeRanges", options: .New, context: nil)
        
            //获取播放结束的时刻
            NSNotificationCenter.defaultCenter().addObserver(self, selector: "endPlayAction", name: AVPlayerItemDidPlayToEndTimeNotification, object: nil)
        
            return tplayer
        }()
        
        
        //MARK: - 生命周期
        override func viewDidLoad() {
            super.viewDidLoad()
    
            //创建播放界面
            self.creatPlayerLayer()
            //开始播放
            self.player.play()
            
            
            //获取播放进度
            self.getPlayProgress()
            
        }//函数结束
    
    }
    
    //MARK: - 观察者
    extension PlayerViewController{
    
        //当观察者观察的对象的属性的值发生改变后会自动调用的方法
        //参数1:被观察的属性的路径
        //参数2:被观察的对象
        //参数3:变化的值(旧值/新值)
        override func observeValueForKeyPath(keyPath: String?, ofObject object: AnyObject?, change: [String : AnyObject]?, context: UnsafeMutablePointer<Void>) {
            
            //获取当前播放源的总时间
            let duraction = self.player.currentItem?.duration
            let totalTime = Float(duraction!.value) / Float(duraction!.timescale)
            
            //获取当前的缓存时间
            //1.获取播放源对象
            let item = object as! AVPlayerItem
            //2.获取缓存进度对象
            let value = item.loadedTimeRanges.first
            let timeRange = value?.CMTimeRangeValue
            //3.获取当前缓存到的时间
            let current = timeRange?.duration
            let currentTime = Float((current?.value)!) / Float((current?.timescale)!)
            print(currentTime)
            if currentTime > 1 {
                self.isLoadFinish = true
            }
            
        }
    }
    
    //MARK: - 播放功能相关
    extension PlayerViewController{
        
        func endPlayAction() {
            
            //1.改变按钮的显示状态
            self.playButton.setImage(UIImage.init(named: "page_play_normal.png"), forState: .Normal)
            self.isPlaying = false
            //2.显示提示信息
            self.finishView.hidden = false
        }
    
        func getPlayProgress(){
            
            //获取播放进度
            self.player.addPeriodicTimeObserverForInterval(CMTimeMake(1, 1), queue: dispatch_get_global_queue(0, 0)) { (currentTime) in
                
                //1.计算时间(秒)
                //当前时间
                let current = CGFloat(currentTime.value) / CGFloat(currentTime.timescale)
                let currentStr = ToolManager.transformTime(current)
                //总时间
                let duraction = CGFloat((self.player.currentItem?.duration.value)!) / CGFloat((self.player.currentItem?.duration.timescale)!)
                let duractionStr = ToolManager.transformTime(duraction)
                //2.计算进度
                let progress = current/duraction
                //回到主线程刷新数据
                dispatch_async(dispatch_get_main_queue(), {
                    
                    self.timeLabel.text = "\(currentStr) / \(duractionStr)"
                    self.slider.value = Float(progress)
                })
                
            }
        }
    }
    
    //MARK: - 界面相关
    extension PlayerViewController{
    
        func creatPlayerLayer(){
            
            //创建layer
            let playLayer = AVPlayerLayer.init(player: self.player)
            playLayer.frame = self.view.bounds
            self.view.layer.addSublayer(playLayer)
            
            //改变层次
            self.view.bringSubviewToFront(self.backButton)
            self.view.bringSubviewToFront(self.bottomView)
            self.view.bringSubviewToFront(self.finishView)
            
        }
    }
    
    //MARK: - 按钮点击
    extension PlayerViewController{
        
        override func touchesBegan(touches: Set<UITouch>, withEvent event: UIEvent?) {
            if bottomConatraint.constant == 0 {
                
                UIView.animateWithDuration(0.3, animations: { 
                    
                    self.bottomConatraint.constant = -50
                    self.topConatraint.constant = -50
                    self.view.layoutIfNeeded()
                })
            }else{
            
                UIView.animateWithDuration(0.3, animations: {
                    
                    self.bottomConatraint.constant = 0
                    self.topConatraint.constant = 10
                    self.view.layoutIfNeeded()
                })
            }
        }
        
        
        @IBAction func playAction2(sender: AnyObject) {
            
            //重新播放
            self.slider.value = 0
            self.playButton.setImage(UIImage.init(named: "pauseBtn.png"), forState: .Normal)
            self.isPlaying = true
            self.finishView.hidden = true
            
            self.player.seekToTime(CMTimeMake(0, 10))
            self.player.play()
        }
        
        @IBAction func sliderAction(sender: UISlider) {
            
            //先判断当前视频是否已经加载成功
            if self.isLoadFinish == false {
                
                sender.value = 0
                return
            }
            
            //拿到进度值
            let progress = slider.value
            
            //获取总的时间(秒)
            let time = Float((self.player.currentItem?.duration.value)!) / Float((self.player.currentItem?.duration.timescale)!)
            //计算当前时间
            let current = Int64(time*progress)
            
            //设置进度
            self.player.seekToTime(CMTimeMake(current, 1))
            
            
        }
        //播放/暂停
        @IBAction func playAction(sender: UIButton) {
            
            //如果正在播放
            if self.isPlaying{
                //暂停播放
                self.player.pause()
                self.isPlaying = false
                //改变按钮的显示状态
                sender.setImage(UIImage.init(named: "page_play_normal.png"), forState: .Normal)
            }else{
            
                //开始播放
                self.player.play()
                self.isPlaying = true
                //改变按钮的显示状态
                sender.setImage(UIImage.init(named: "pauseBtn.png"), forState: .Normal)
            }
        }
        
        //返回
        @IBAction func backAction(sender: UIButton) {
            
            //1.停止播放
            self.player.pause()
            //2.移除观察者
            //移除self对播放源中loadedTimeRanges的观察
            self.player.currentItem?.removeObserver(self, forKeyPath: "loadedTimeRanges")
            
            
            self.dismissViewControllerAnimated(true, completion: nil)
        }
        
    }
    
    //MARK: - 横屏相关
    extension PlayerViewController{
    
        //是否支持屏幕旋转
        override func shouldAutorotate() -> Bool {
            return true
        }
        
        //设置屏幕的方向
        override func supportedInterfaceOrientations() -> UIInterfaceOrientationMask {
            
            //横屏,home键在右
            return .LandscapeRight
        }
        
    }
    

    相关文章

      网友评论

          本文标题:AVPlayer代码解析

          本文链接:https://www.haomeiwen.com/subject/dbfquttx.html