swift之IJKPlayer 的应用

 

前言:用IJKPlayer需要环境搭建,具体可以自行百度。下面是应用IJKPlayer的具体代码,代码中有详细备注。

 

import IJKMediaFramework

·初始化变量

let ViewForPlayer = UIView()
var player: IJKFFMoviePlayerController!
///保存视频流地址的字符串
var videoStreaming: String!
//提示播放器的状态,放在播放器正中央
var videoTip = UILabel()
//播放器加载或缓存的时候可见并转动
var indicator = UIActivityIndicatorView()
//要重启播放器时,把播放器的view存放起来,适当时候删掉
var oldPlayerView = UIView()

 

·初始化控件

func initView(cgRect: CGRect,url: String,text:String)
    {
        indicator.activityIndicatorViewStyle = UIActivityIndicatorViewStyle.white
        videoTip.text = text
        videoTip.textColor = UIColor.lightGray
        videoStreaming = url
        //添加ViewForPlayer到界面
        ViewForPlayer.frame = cgRect
        ViewForPlayer.backgroundColor = UIColor.darkText
//        controller.view.addSubview(ViewForPlayer)
        ViewController.playerContainer.addSubview(ViewForPlayer)
        //初始化播放器
        initPlayer(Url: url)
    }
func setLabelViewConstraints() {
        //系统默认会给autoresizing 约束,要关闭autoresizing才能让自定义的约束生效,否则程序崩溃
        videoTip.translatesAutoresizingMaskIntoConstraints = false
        //添加约束:"哪个控件" 的 “什么属性“ "等于/大于/小于" “另一个控件” 的 “什么属性” 乘以 "多少" 加上 "多少"
        let Constraint_centerX = NSLayoutConstraint(item: videoTip, attribute: .centerX, relatedBy: .equal, toItem: ViewForPlayer, attribute: .centerX, multiplier: 1, constant: 0)
        
        let Constraint_centerY = NSLayoutConstraint(item: videoTip, attribute: .centerY, relatedBy: .equal, toItem: ViewForPlayer, attribute: .centerY, multiplier: 1, constant: 0)
        
        let Constraint_width = NSLayoutConstraint(item: videoTip, attribute: .width, relatedBy: .lessThanOrEqual, toItem: ViewForPlayer, attribute: .width, multiplier: 1, constant: 0)
        
        let Constraint_height = NSLayoutConstraint(item: videoTip, attribute: .height, relatedBy: .lessThanOrEqual, toItem: nil, attribute: .height, multiplier: 1, constant: 20)
        NSLayoutConstraint.activate([Constraint_centerX,Constraint_centerY,Constraint_width,Constraint_height])
    }

    func setIndicatorViewConstraints() {
        //系统默认会给autoresizing 约束,要关闭autoresizing才能让自定义的约束生效,否则程序崩溃
        indicator.translatesAutoresizingMaskIntoConstraints = false
        //添加约束:"哪个控件" 的 “什么属性“ "等于/大于/小于" “另一个控件” 的 “什么属性” 乘以 "多少" 加上 "多少"
        let Constraint_centerX = NSLayoutConstraint(item: indicator, attribute: .centerX, relatedBy: .equal, toItem: ViewForPlayer, attribute: .centerX, multiplier: 1, constant: 0)
        
        let Constraint_centerY = NSLayoutConstraint(item: indicator, attribute: .centerY, relatedBy: .equal, toItem: ViewForPlayer, attribute: .centerY, multiplier: 1, constant: 0)
        
        let Constraint_width = NSLayoutConstraint(item: indicator, attribute: .width, relatedBy: .lessThanOrEqual, toItem: nil, attribute: .width, multiplier: 1, constant: 20)
        
        let Constraint_height = NSLayoutConstraint(item: indicator, attribute: .height, relatedBy: .lessThanOrEqual, toItem: nil, attribute: .height, multiplier: 1, constant: 20)
        NSLayoutConstraint.activate([Constraint_centerX,Constraint_centerY,Constraint_width,Constraint_height])
    }
    

 

·初始化并开启播放器

func initPlayer(Url: String) {
        //防止重复打开播放器导致内存溢出
        if player != nil {
            player.shutdown()//关闭播放器
            oldPlayerView = player.view
            indicator.removeFromSuperview()
            videoTip.removeFromSuperview()
            player = nil
            print("++++++++重启播放器+++++++")
        }
        
        videoStreaming = Url
        let url = NSURL(string: Url)
        //options是对数据的处理,videotoolbox解码,设置音频视频等属性,都要有这个数据
        let options = IJKFFOptions.byDefault()
        //设置解码方式: 0-软解码;1-硬解码
//        options?.setPlayerOptionIntValue(1, forKey: "videotoolbox")
        //开启硬解码
//        options?.setPlayerOptionValue("1", forKey: "videotoolbox")
        //设置播放器缓冲: 0-关闭缓冲;1-开启缓冲;默认是1
//        options?.setPlayerOptionIntValue(1, forKey: "packet-buffering")
        // 最大缓存是3000(3s),可以依据自己的需求修改
//        options?.setPlayerOptionIntValue(1000, forKey: "max_cached_duration")
        //设置自动转屏
//        options?.setFormatOptionIntValue(0, forKey: "auto_convert")
        //设置重连:0-关闭重连;1-开启重连;
//        options?.setFormatOptionIntValue(1, forKey: "reconnect")
        //如果使用rtsp协议,可以优先用tcp(默认udp)
//        options?.setPlayerOptionValue("tcp", forKey: "rtsp_transport")
        //开启环路滤波IJK_AVDISCARD(0比48清楚,但解码开销大,48基本没有开启环路滤波,清晰度低,解码开销小)
//        options?.setCodecOptionIntValue(48, forKey: "skip_loop_filter")
        //帧速率(fps)-可以改,确认非标准桢率会导致音画不同步,所以只能设定为15或者29.97
//        options?.setPlayerOptionIntValue(29.97, forKey: "r")
        
//        //设置音量大小,256为标准音量。要设置成两倍音量时则输入512,依此类推
//        options?.setPlayerOptionIntValue(256, forKey: "vol")
        //设置静音
        options?.setPlayerOptionValue("1", forKey: "an")
//        IJKFFMoviePlayerController.setLogLevel(IJKLogLevel(rawValue: 3))
//        IJKFFMoviePlayerController.setLogReport(false)
        //默认是false
//        player.shouldShowHudView = true
 
        //初始化播放器,播放在线视频或直播
        player = IJKFFMoviePlayerController(contentURL: url as URL?, with: options)
        //播放页面视图宽高自适应
        let autoresize = UIViewAutoresizing.flexibleWidth.rawValue | UIViewAutoresizing.flexibleHeight.rawValue
        player.view.autoresizingMask = UIViewAutoresizing(rawValue: autoresize)
        //设置视频缓存大小,缓存大延迟大,缓存小延迟小
        player.setPlayerOptionIntValue(100, forKey: "framedrop")
        
        player.view.frame = self.ViewForPlayer.bounds
        player.scalingMode = .aspectFit//缩放模式
        player.shouldAutoplay = true //开启自动播放
//        player.allowsMediaAirPlay = true
        
        //player.view的父控件设置自动适应
        //fatherView.autoresizesSubviews = true
        
        self.ViewForPlayer.addSubview(player.view)
        //添加indicatorView到ViewForPlayer
        ViewForPlayer.addSubview(indicator)
        setIndicatorViewConstraints()
        //添加label到ViewForPlayer
        ViewForPlayer.addSubview(videoTip)
        setLabelViewConstraints()
        /
        self.player.currentPlaybackTime = 1
        //self.player.playbackState
        DispatchQueue.main.async {
            //开启播放器
            self.player.prepareToPlay()
        }

        videoTip.text = " "
        indicator.startAnimating()
        //注册ijk播放器的通知
        initIJKNoti()
    }

 

·注册ijk播放器的通知

func initIJKNoti() {
        //注册ijk播放器的通知
        NotificationCenter.default.addObserver(self, selector: #selector(moviePlayBackFinish), name: NSNotification.Name.IJKMPMoviePlayerPlaybackDidFinish, object: player)

        NotificationCenter.default.addObserver(self, selector: #selector(loadStateDidChange), name: NSNotification.Name.IJKMPMoviePlayerLoadStateDidChange, object: player)

        NotificationCenter.default.addObserver(self, selector: #selector(moviePlayBackStateDidChange), name: NSNotification.Name.IJKMPMoviePlayerPlaybackStateDidChange, object: player)

        NotificationCenter.default.addObserver(self, selector: #selector(mediaIsPreparedToPlayDidChange), name: NSNotification.Name.IJKMPMediaPlaybackIsPreparedToPlayDidChange, object: player)
}

 

接收播放器状态改变的通知

    //视频播放结束
    @objc func moviePlayBackFinish(notifycation:Notification)  {
        let playerN = notifycation.object as! IJKFFMoviePlayerController

        if playerN.bufferingProgress == 0 {
            print("视频加载失败")
        }
        let reason = notifycation.userInfo?[IJKMPMoviePlayerPlaybackDidFinishReasonUserInfoKey] as! Int
        NSLog("--------------moviePlayBackFinish:\(reason)")
        
        switch (reason) {
        case 0://playbackEnded
            indicator.startAnimating()
            if !videoStreaming.isEmpty {
                initPlayer(Url: videoStreaming)
            }
            
            break
            
        case 2://userExited
            
            break
            
        case 1://playbackError
            print("播放错误,需要重新播放:\(reason)")
            videoTip.text = "获取视频失败"
            indicator.stopAnimating()
            break
        default:
            break
        }
    }
    
    ///加载状态改变了
    @objc func loadStateDidChange(notifycation:Notification)  {
        let playerN = notifycation.object as! IJKFFMoviePlayerController
        let loadState = player?.loadState.rawValue
        
        NSLog("--------------加载状态loadStateDidChange:\(loadState!)")
        //        IJKMPMovieLoadState
        if loadState == 3 {//开始播放视频
            indicator.stopAnimating()
            self.oldPlayerView.removeFromSuperview()
        }else if loadState == 4 {//网络不好导致了暂停
            indicator.startAnimating()
            if !videoStreaming.isEmpty {
                initPlayer(Url: videoStreaming)
            }
        }
        switch self.player.loadState {
        // 状态为缓冲几乎完成,可以连续播放
        case IJKMPMovieLoadState.playthroughOK:
            
//            videoTip.text = "加载状态为缓冲几乎完成,可以连续播放"
            break
        // 可以播放状态
        case IJKMPMovieLoadState.playable:
//            videoTip.text = "加载状态为可以播放状态"
            
            break
        // 缓冲中
        case IJKMPMovieLoadState.stalled:
            
            videoTip.text = "网络不好导致了暂停"
            indicator.startAnimating()
            break
        default:
            print("加载状态-loadStateDidChange: \(loadState!)")//加载状态未知
        }
  
    }
    
    ///准备播放的媒体改变了
    @objc func mediaIsPreparedToPlayDidChange(notifycation:Notification)  {
        _ = notifycation.object as! IJKFFMoviePlayerController
        NSLog("--------------mediaIsPreparedToPlayDidChange")
        videoTip.text = "mediaIsPreparedToPlayDidChange"
        
    }
    ///视频播放状态改变了
    @objc func moviePlayBackStateDidChange(notifycation:Notification)  {
        let playerN = notifycation.object as! IJKFFMoviePlayerController

        //播放 1  暂停2  播放完成 0
        NSLog("--------------播放状态改变了:\(player?.playbackState.rawValue ?? 9)")
//        videoTip.text = "播放状态改变了:\(player?.playbackState.rawValue ?? 9)"
        switch player?.playbackState.rawValue ?? 9 {
        case 0://停止
//            initPlayer(Url: videoStreaming)
            break
            
        case 1://播放

            break
            
        case 2://暂停
//            initPlayer(Url: videoStreaming)

            break
        case 4://播放
            
            break
        default:
            break
            
        }
        
    }

    

  • 1
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值