阿里云点播SDK集成(二)封装篇
1.上篇说到阿里云的文件上传以及注意的一些事项,今天就来说说简单的封装一下阿里云的播放器,简单说下思路(ps:在tableView或collectionView上用。为了节省资源以及滚动的流畅度,我们全局只用到1个播放器,提前加载视频并缓存本地,在滚动到当前视频的时候才去将播放器添加到cell上进行播放,滚动到下一个视频的时候会删除上一个播放器,网速好的情况下很流畅,其次也是看阿里云的视频解码速度 )
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 | class PlayerManager : NSObject { /// 播放器superview let playSuperView = UIView () /// 播放器view let playView = UIView () /// 进度view fileprivate let progressView = UIProgressView () /// 播放器状态view fileprivate let playStatusImgView = UIImageView ( image : UIImage ( named : "icon_search_play" )) /// 播放器 let player = AliPlayer () /// 代理 fileprivate weak var vc : PlayerListDelete ! /// 当前正在播放视频的索引 var currentIndex : Int = - 1 { didSet { print ( "current index =>:\( currentIndex )" ) } } /// 播放状态 用来控制播放器播放状态 fileprivate var playerStatus_ : AVPStatus = AVPStatusIdle { didSet {< br > //监听播放器状态,暂停就显示播放按钮,播放就隐藏播放按钮 playStatusImgView . isHidden = playerStatus_ == AVPStatusStarted } } weak var delegate : PlayerManagerDelegate ? /// 实际播放状态 给外部使用 var playerStatus : AVPStatus = AVPStatusIdle /// 是否能够播放 var canPlay = true { didSet { if canPlay & & isShow & & playerStatus_ != AVPStatusPaused & & playerStatus_ != AVPStatusStopped & & playerStatus_ != AVPStatusError { resume () playStatusImgView . isHidden = true } else { player ?. pause () playStatusImgView . isHidden = false } } } /// 构造函数 init ( vc : VVPlayerListDelete ) { super . init () self . vc = vc initPlayer () initUI () } fileprivate func initPlayer () { AliPrivateService . initLicense () player ?. isLoop = false player ?. isAutoPlay = true player ?. scalingMode = AVP_SCALINGMODE_SCALEASPECTFIT let playConfig = player ?. getConfig () playConfig ?. clearShowWhenStop = true player ?. setConfig ( playConfig ) player ?. delegate = self AliListPlayer . setEnableLog ( true ) } fileprivate func initUI () { player ?. playerView = playView playSuperView . backgroundColor = . black playSuperView . addSubview ( playView ) playSuperView . isHidden = true playStatusImgView . contentMode = . scaleAspectFit playStatusImgView . isHidden = true playSuperView . addSubview ( playStatusImgView ) playStatusImgView . snp . makeConstraints { ( make ) in make . center . equalToSuperview () } progressView . progressTintColor = . white progressView . backgroundColor = UIColor ( white : 1 , alpha : 0.2 ) progressView . isHidden = true playSuperView . addSubview ( progressView ) progressView . snp . makeConstraints { ( make ) in make . left . right . equalToSuperview () make . bottom . equalToSuperview (). offset ( 0 ) make . height . equalTo ( 20 ) } } < br > //适配大小 fileprivate func setPlayerscalingMode () { if let trackInfo = player ?. getMediaInfo ()?. tracks . first { if trackInfo . videoWidth < trackInfo . videoHeight { player ?. scalingMode = AVP_SCALINGMODE_SCALEASPECTFILL } else { player ?. scalingMode = AVP_SCALINGMODE_SCALEASPECTFIT } let width = SCREEN_WIDTH var height = playSuperView . frame . height let scaleX = ( CGFloat )( trackInfo . videoHeight ) / ( CGFloat )( trackInfo . videoWidth ) height = scaleX * width height = height > playSuperView . frame . height ? height : playSuperView . frame . height let criticalScale = height / playSuperView . frame . height if criticalScale > = 0.8 { height = playSuperView . frame . height } playView . frame = CGRect ( x : 0 , y : 0 , width : width , height : height ) } } } |
2.封装播放组件api
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 | // MARK:- 外部使用api extension PlayerManager { /// 停止播放 func stop () { player ?. stop () playerStatus_ = AVPStatusStopped delegate ?. playStatusChange ( isPause : false ) } /// 暂停 func pause () { player ?. pause () playerStatus_ = AVPStatusPaused delegate ?. playStatusChange ( isPause : true ) } /// 恢复播放 func resume () { player ?. start () playerStatus_ = AVPStatusStarted delegate ?. playStatusChange ( isPause : false ) } /// 播放指定索引的视频 func playAtIndex ( index : Int , vid : String ) { progressView . setProgress ( 0 , animated : false ) currentIndex = index playSuperView . frame = vc . playerList ( playerManager : self , frameForIndexAt : index ) player ?. playerView . frame = playSuperView . bounds let source = AVPVidStsSource () source . vid = vid source . region = STSManager . shared . region source . securityToken = STSManager . shared . securityToken source . accessKeySecret = STSManager . shared . accessKeySecret source . accessKeyId = STSManager . shared . accessKeyId self . player ?. setStsSource ( source ) self . player ?. prepare () if canPlay { resume () } else { player ?. pause () } } /// 单击暂停或者播放 func singleTap () { switch playerStatus_ { case AVPStatusStarted : pause () default : resume () } } func removePlayView () { playSuperView . removeFromSuperview () playSuperView . isHidden = true player ?. stop () currentIndex = - 1 } /// 移除某个video func removeVideo ( index : Int ) { currentIndex = - 1 } func updatePlayerStatus ( withControllerStatus status : PlayerListControllerStatus ) { if status == . active { canPlay = true } else { canPlay = false } } } |
3.根据代理设置监听,涉及到播放进度或者播放完成等一些事件可以在这里监听
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 | extension VVPlayerManager : AVPDelegate { func onError ( _ player : AliPlayer !, errorModel : AVPErrorModel !) { playerStatus_ = AVPStatusStopped if errorModel . code . rawValue == 537198597 || errorModel . code . rawValue == 537067523 { delegate ?. playerManage ( AuthorityExpired : self ) } print ( "________playermanager________ 播放失败 => \( String ( describing : errorModel . message ) )" ) VVSTSManager . shared . updateSts () } func onPlayerEvent ( _ player : AliPlayer !, eventType : AVPEventType ) { print ( "________playermanager________ \( eventType )" ) switch eventType { case AVPEventPrepareDone : setPlayerscalingMode () case AVPEventFirstRenderedStart : playSuperView . isHidden = false case AVPEventLoopingStart : //一次完整视频播放完成 self . delegate ?. aCompletePlaybackIsCompleted () case AVPEventCompletion : self . delegate ?. playbackCompleted () default : break } } func onPlayerStatusChanged ( _ player : AliPlayer !, oldStatus : AVPStatus , newStatus : AVPStatus ) { playerStatus = newStatus } func onLoadingProgress ( _ player : AliPlayer !, progress : Float ) { } func onCurrentPositionUpdate ( _ player : AliPlayer !, position : Int64 ) { let duration : Float = Float ( player . duration ) let position : Float = Float ( position ) let current : Float = position / duration self . delegate ?. playChange ( progressVaues : current , totalProgress : duration , currentProgress : position ) } } |
以上就是阿里云播放器的简单封装,有问题的请在下方评论,看到后第1时间回复
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· winform 绘制太阳,地球,月球 运作规律
· 震惊!C++程序真的从main开始吗?99%的程序员都答错了
· AI与.NET技术实操系列(五):向量存储与相似性搜索在 .NET 中的实现
· 超详细:普通电脑也行Windows部署deepseek R1训练数据并当服务器共享给他人
· 【硬核科普】Trae如何「偷看」你的代码?零基础破解AI编程运行原理