ios音视频及流媒体

swift 利用AVFoundation,SnapKit进行网络

2018-09-10  本文已影响77人  MrLSX
效果图: QQ20180912-143551.gif QQ20180912-143648.gif 1.创建视图需要的xib image.png

2.创建视图内控件的对应属性

//进度条
@IBOutlet weak var slider: UISlider!
//视频视图
@IBOutlet weak var videoBox: UIView!
//视频视图的长宽
@IBOutlet weak var videoHeight: NSLayoutConstraint!
@IBOutlet weak var videoBoxWeight: NSLayoutConstraint!
 //下边视图
@IBOutlet weak var bottonView: UIView!
//上边视图
@IBOutlet weak var topView: UIView!
//视频title
@IBOutlet weak var titleLabel: UILabel!
//时间进度
@IBOutlet weak var currentTimeLabel: UILabel!
@IBOutlet weak var totalTimeLabel: UILabel!

3.创建player对象

var player:AVPlayer?
var playeritem:AVPlayerItem?
var playerLayer:AVPlayerLayer!

4.初始化player对象以及设置player的一些属性

   //测试用的MP4对象
    let contentUrl = URL(fileURLWithPath: "本地路径.mp4")
    let url = URL.init(string: "网络路径.mp4")!
    playeritem = AVPlayerItem(url: url)
    // 监听状态改变
    playeritem?.addObserver(self, forKeyPath: "status", options: NSKeyValueObservingOptions.new, context: nil)
    // 将视频资源赋值给视频播放对象
    player = AVPlayer(playerItem: playeritem)
    // 初始化视频显示layer
    playerLayer = AVPlayerLayer(player: player)
    // 设置填充模式
    playerLayer.videoGravity = AVLayerVideoGravity.resizeAspect
   //给playerLayer添加到videoBox的Layer上
    videoBox.layer.addSublayer(playerLayer)
   //设置playerLayer的frame
    playerLayer.frame = videoBox.bounds
    // 位置放在最底下
    videoBox.layer.insertSublayer(playerLayer, at: 0)

5.播放视频资源

//如果资源正确自动播放,不正确打印“加载异常”
override func observeValue(forKeyPath keyPath: String?, of object: Any?, change: [NSKeyValueChangeKey : Any]?, context: UnsafeMutableRawPointer?) {
    if keyPath == "status"{
        if playeritem?.status == AVPlayerItemStatus.readyToPlay{
            self.player?.play()
        }else{
            print("加载异常")
        }
    }
}

现在就可以播放视频了
6.显示进读

var link:CADisplayLink!
//计时器 正常情况下每秒60帧
    link = CADisplayLink(target: self, selector: #selector(updata))
    link.add(to: RunLoop.main, forMode: RunLoopMode.defaultRunLoopMode)

@objc func updata(){
    //当前时间
    let currentTime = CMTimeGetSeconds((self.player?.currentTime())!)
    //总时间
    let totalTime = TimeInterval((playeritem?.duration.value)!) / TimeInterval((playeritem?.duration.timescale)!)
    
    totalTimeLabel.text = formatPlayTime(secounds: totalTime)
    currentTimeLabel.text = formatPlayTime(secounds: currentTime)
    }

//时间转换成秒
func formatPlayTime(secounds:TimeInterval)->String{
    if secounds.isNaN{
        return "00:00"
    }
    let Min = Int(secounds / 60)
    let Sec = Int(secounds.truncatingRemainder(dividingBy: 60))
    return String(format: "%02d:%02d", Min, Sec)
}
}

7.滑动进度条

//判断slider是否在移动,移动的时候不更新进度的值
var slidering = false
//给slider添加事件
//按下
    slider.addTarget(self, action: #selector(sliderTouchDown( _:)), for: .touchDown)
    //谈起
    slider.addTarget(self, action: #selector(sliderTouchUpOut( _:)), for: .touchUpInside)
    slider.addTarget(self, action: #selector(sliderTouchUpOut( _:)), for: .touchUpOutside)
    slider.addTarget(self, action: #selector(sliderTouchUpOut( _:)), for: .touchCancel)

@objc func sliderTouchUpOut(_ slider:UISlider){
    //当播放正常的时候才能滑动slider
    if player?.status == AVPlayerStatus.readyToPlay{
        let duration = slider.value * Float(TimeInterval((playeritem?.duration.value)!) / TimeInterval((playeritem?.duration.timescale)!))
        let seekTime = CMTimeMake(Int64(duration), 1)
        player?.seek(to: seekTime, completionHandler: { (_) in
            self.slidering = false
        })
    }
}
@objc func sliderTouchDown(_ slider:UISlider){
    slidering = true
}

在updata()内添加

//slider滑动时不更新slider
    if !slidering{
        slider.value = Float(currentTime/totalTime)
    }

8.button事件

//返回键
@IBAction func back(_ sender: UIButton) {
    if !isFullScreen {
        self.navigationController?.popViewController(animated: true)
    }else{
        //强制竖屏并且重新设置视图的Frame以及playerlayer的Frame
        isFullScreen = false
        UIDevice.current.setValue(UIInterfaceOrientation.portrait.rawValue, forKey: "orientation")
        videoBox.snp.removeConstraints()
        videoBox.snp.makeConstraints { (make) in
            make.top.equalTo(44)
            make.left.right.equalToSuperview()
            videoBox.frame.size = CGSize(width: UIScreen.main.bounds.width, height: UIScreen.main.bounds.width * 9 / 16)
        }
        playerLayer.frame = videoBox.bounds
    }
}

//播放暂停
@IBOutlet weak var playButton: UIButton!
@IBAction func play(_ sender: UIButton) {
    if !sender.isSelected {
        player?.pause()
    }else{
        if player?.status == AVPlayerStatus.readyToPlay{
            player?.play()
        }
    }
    sender.isSelected = !sender.isSelected
}

//全屏
var isFullScreen = false
var isleft = false
@IBAction func fullScreen(_ sender: UIButton) {
    if !isFullScreen{
        //强制横屏
        UIDevice.current.setValue(UIInterfaceOrientation.landscapeLeft.rawValue, forKey: "orientation")
        videoBox.snp.makeConstraints { (make) in
            make.edges.equalToSuperview()
        }
        playerLayer.frame = UIScreen.main.bounds
        isFullScreen = true
    }
    else{
        //强制横屏以及判断是否是横屏后再次点击横屏键
        if isleft{
            UIDevice.current.setValue(UIInterfaceOrientation.landscapeRight.rawValue, forKey: "orientation")
            isleft = false
        }else{
            UIDevice.current.setValue(UIInterfaceOrientation.landscapeLeft.rawValue, forKey: "orientation")
            isleft = true
        }
    }
}

9.双击暂停播放,单击隐藏上下视图

//给videoBox添加两个一个单击,一个双击事件
@IBOutlet var singleTouch: UITapGestureRecognizer!
@IBAction func singleTouch(_ sender: UITapGestureRecognizer) {
    topView.isHidden = !topView.isHidden
    bottonView.isHidden = !bottonView.isHidden
}
//双击
@IBOutlet var doubleTouch: UITapGestureRecognizer!
@IBAction func doubleTouch(_ sender: Any) {
   //给playButton发送一次点击信息,相当于点击一次BUtton
    playButton.sendActions(for: .touchUpInside)
}

10.其他

 //因为videoBox添加了单击双击事件,所以要在viewDidLoad()添加一行代码,从而让双击事件触发
 //单击事件必须在双击事件检测失败后才执行,这样单击事件会有点延迟
    singleTouch.require(toFail: doubleTouch)

 //移除监听事件
 playeritem?.removeObserver(self, forKeyPath: "status")

项目git地址:https://github.com/Liushaungxi/AVPlayer
参考文档:https://www.jianshu.com/p/d35980045c2b

上一篇 下一篇

猜你喜欢

热点阅读