iOS AVPlayer视频播放器

article/2025/10/3 21:53:37

代码地址如下:
http://www.demodashi.com/demo/11168.html

一、运行效果

总效果.gif

二、实现过程

①、创建播放器avPlayer

       //创建播放器url = [url stringByAddingPercentEncodingWithAllowedCharacters:[NSCharacterSet URLQueryAllowedCharacterSet]];AVPlayer *player = [AVPlayer playerWithURL:[NSURL URLWithString:url]];self.avPlayer = player;

②、创建显示屏_videoLayer

- (void)createDisplay{// 显示图像的_videoLayer = [AVPlayerLayer playerLayerWithPlayer:self.avPlayer];//锚点的坐标_videoLayer.position = CGPointMake(KPLAYVIEWWIDTH/2, KPLAYVIEWHEIGHT/2);_videoLayer.bounds = CGRectMake(0, 0, KPLAYVIEWWIDTH, KPLAYVIEWHEIGHT);// 锚点,值只能是0,1之间_videoLayer.anchorPoint = CGPointMake(0.5, 0.5);//     AVLayerVideoGravityResizeAspect 按比例压缩,视频不会超出Layer的范围(默认)//     AVLayerVideoGravityResizeAspectFill 按比例填充Layer,不会有黑边//     AVLayerVideoGravityResize 填充整个Layer,视频会变形//     视频内容拉伸的选项_videoLayer.videoGravity = AVLayerVideoGravityResizeAspect;//    //播放时,视频实际占的区域//    NSLog(@"%@", NSStringFromCGRect(videoLayer.videoRect));//Layer只能添加到Layer上面[self.displayView.layer addSublayer:_videoLayer];
}

③、添加观察者和通知,用于监测更新视频播放的状态、进度、屏幕方向、状态栏属性、音量等等。

主要代码如下:

//监测屏幕旋转[[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(orientationChange:) name:UIDeviceOrientationDidChangeNotification object:nil];//添加AVPlayerItem播放结束通知[[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(playFinished:) name:AVPlayerItemDidPlayToEndTimeNotification object:self.avPlayer.currentItem];//添加AVPlayerItem开始缓冲通知[[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(bufferStart:) name:AVPlayerItemPlaybackStalledNotification object:self.avPlayer.currentItem];//KOV监控 播放器进度更新
- (void)addObserverForAVPlayer
{AVPlayerItem *playerItem = self.avPlayer.currentItem;// 给AVPlayer添加观察者 必须实现 - (void)observeValueForKeyPath:(NSString *)keyPath ofObject:(id)object change:(NSDictionary *)change context:(void *)context;//监控播放速率[self.avPlayer addObserver:self forKeyPath:@"rate" options:NSKeyValueObservingOptionNew context:nil];//监控状态属性(AVPlayer也有一个status属性,通过监控它的status也可以获得播放状态)[playerItem addObserver:self forKeyPath:@"status" options:NSKeyValueObservingOptionNew | NSKeyValueObservingOptionOld context:nil];//监控网络加载缓冲情况属性[playerItem addObserver:self forKeyPath:@"loadedTimeRanges" options:NSKeyValueObservingOptionNew context:nil];//监控是否可播放[playerItem addObserver:self forKeyPath:@"playbackLikelyToKeepUp" options:NSKeyValueObservingOptionNew context:nil];//播放进度观察者  //设置每0.1秒执行一次__weak GOVVideoView *weakSelf = self;_playerTimeObserver =  [self.avPlayer addPeriodicTimeObserverForInterval:CMTimeMake(1.0, 10.0) queue:dispatch_get_main_queue() usingBlock:^(CMTime time) {if (weakSelf.dragSlider) {return ;}CGFloat current = CMTimeGetSeconds(time);weakSelf.current = current;CMTime totalTime = weakSelf.avPlayer.currentItem.duration;CGFloat total = CMTimeGetSeconds(totalTime);weakSelf.total = total;weakSelf.slider.value = current/total;weakSelf.currentTimeLabel.text = [weakSelf timeFormatted:current];weakSelf.totalTimeLabel.text = [NSString stringWithFormat:@"/%@",[weakSelf timeFormatted:total]] ;}];
}//通过KVO监控回调
//keyPath 监控属性 object 监视器 change 状态改变 context 上下文
- (void)observeValueForKeyPath:(NSString *)keyPath ofObject:(id)object change:(NSDictionary *)change context:(void *)context{if ([keyPath isEqualToString:@"loadedTimeRanges"]) {//监控网络加载情况属性NSArray *array = self.avPlayer.currentItem.loadedTimeRanges;//本次缓冲时间范围CMTimeRange timeRange = [array.firstObject CMTimeRangeValue];CGFloat startSeconds = CMTimeGetSeconds(timeRange.start);CGFloat durationSeconds = CMTimeGetSeconds(timeRange.duration);//现有缓冲总长度CGFloat totalBuffer = startSeconds + durationSeconds;//视频总时长CMTime totalTime = self.avPlayer.currentItem.duration;CGFloat total = CMTimeGetSeconds(totalTime);if (totalBuffer/total <= 1.0 ) {[self.progressView setProgress:totalBuffer/total animated:YES];}}else if([keyPath isEqualToString:@"playbackLikelyToKeepUp"]){if (self.avPlayer.currentItem.playbackLikelyToKeepUp == YES) {if (_activityView != nil) {[self.activityView startAnimating];[self.activityView removeFromSuperview];_activityView = nil;}}}else if ([keyPath isEqualToString:@"status"]){//监控状态属性AVPlayerStatus status = [[change objectForKey:@"new"] intValue];switch ((status)) {case AVPlayerStatusReadyToPlay:break;case AVPlayerStatusUnknown:break;case AVPlayerStatusFailed:break;}}else if ([keyPath isEqualToString:@"rate"]){if (self.avPlayer.rate == 1) {}}}

隐藏/显示状态栏的方法:

[[UIApplication sharedApplication] setStatusBarHidden:NO withAnimation:UIStatusBarAnimationNone];这个方法在iOS9之后弃用了,并且需要
将View controller-based status bar appearance设置为NO;而下面的重写方法需要将View controller-based status bar appearance设置为YES,这个方法在iOS7之后就有了;
//刷新状态栏状态
[self setNeedsStatusBarAppearanceUpdate];

#pragma mark -- 隐藏/显示状态栏的方法
/*[[UIApplication sharedApplication] setStatusBarHidden:NO withAnimation:UIStatusBarAnimationNone];这个方法在iOS9之后弃用了,并且需要将View controller-based status bar appearance设置为NO;而下面的重写方法需要将View controller-based status bar appearance设置为YES,这个方法在iOS7之后就有了;
//刷新状态栏状态[self setNeedsStatusBarAppearanceUpdate];*/
//设置样式
- (UIStatusBarStyle)preferredStatusBarStyle {return UIStatusBarStyleLightContent;
}
//设置是否隐藏
- (BOOL)prefersStatusBarHidden {return self.isHiddenStatusBar;
}
//设置隐藏动画
- (UIStatusBarAnimation)preferredStatusBarUpdateAnimation {return UIStatusBarAnimationNone;
}

④、创建用于处理播放结束、关闭播放器、全屏/退出全屏、隐藏/展示footBar和topBar的Block回调方法和代理方法,方便用户做些自定义的操作。

//Block回调方法
typedef void(^FullScreenBlock)(BOOL isFull);typedef void(^ClosePLayerBlock)();typedef void(^ShowBarBlock)(BOOL isShow);typedef void(^PlayFinishedBlock)();@class GOVVideoPlayer;
//代理方法
@protocol GOVVideoPlayerDelegate  <NSObject>//播放结束
- (void)videoPlayerPlayFinished:(GOVVideoPlayer *)videoPlayer;//关闭播放器
- (void)videoPlayerClosePlayer:(GOVVideoPlayer *)videoPlayer;//全屏按钮
- (void)videoPlayerFullScreen:(GOVVideoPlayer *)videoPlayer withIsFull:(BOOL)isFull;//隐藏/展示footBar和topBar
- (void)videoPlayerShowBar:(GOVVideoPlayer *)videoPlayer withIsShow:(BOOL)isShow;

三、项目结构图

项目结构图

四、补充

GOVVideoPlayer是在继承于UIView的基础上封装的视频View;
GOVVideoController是在继承于UIViewController的基础上封装的视频视图控制器。
两者最大的不同是在全屏和取消全屏的处理上面:前者是一个视图View,可以直接加在父视图上面,全屏时是加在 [UIApplication sharedApplication].keyWindow上的,而后者,小屏时是取GOVVideoController的View加在父视图上,全屏和取消全屏时是采用present和dismiss模态化转场的方法 。

iOS AVPlayer视频播放器

代码地址如下:
http://www.demodashi.com/demo/11168.html

注:本文著作权归作者,由demo大师发表,拒绝转载,转载需要作者授权


http://chatgpt.dhexx.cn/article/hSCba4dJ.shtml

相关文章

打造高可用iOS进度条

前言 做全屏的需求时&#xff0c;因为进度条会从半屏背景下的「基本不可能曝光」&#xff0c;变成全屏场景下「高频曝光」&#xff0c;所以需要打造一个丝滑、高可用的进度条&#xff0c;想当初我Debug到凌晨4点&#xff0c;就是为了解决暂停后进度条的动画问题。 今天把这个…

html ios视频播放器,iOS 视频播放器(整理)

1、WMPlayer //WMPlayer视频播放器&#xff0c;AVPlayer的封装&#xff0c;继承UIView&#xff0c;想怎么玩就怎么玩。支持播放mp4、m3u8、3gp、mov&#xff0c;网络和本地视频同时支持。全屏和小屏播放同时支持。 cell中播放视频&#xff0c;全屏小屏切换自如。(推荐5颗&#…

android+仿ios+音乐播放器,iOS简单的音乐播放器(仿QQ音乐)

AVPlayer实现基本的播放,暂停,上一首,下一首,调节音量,调节进度等,正在学习的新人可以看下,有什么不足可以互相学习,谢谢支持 qq音乐.gif 这个是我写的一个简单的低仿QQ音乐, 如果你也喜欢听音乐的话, 快来自己制作一个吧! 下面我们来实现, 首先我们用单例写的音乐管理…

iOS 视频播放器开发

需求设计 做一个小学生教育辅导视频播放器。 参考小猿搜题视频播放器 [外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-L0GsyFSt-1675164972791)(https://tva1.sinaimg.cn/large/008vxvgGgy1h9xk4fm5xfj31sx0u0mz0.jpg)] [外链图片转存失败,源站可…

iOS播放器SDK-基于FFmpeg解码OpenGL渲染-CYPlayer

CYPlayer基于Objective-C编写&#xff0c;支持RTMP和HTTP协议的播放流&#xff0c;如果需要smb协议&#xff0c;可以自行修改CYFFmpeg兼容samba协议即可。 1.支持动态帧率控制&#xff0c;适配各种性能的机型&#xff0c;最高支持1080p60fps; 2.动态内存控制&#xff0c;防止…

iOS播放器常用功能

iOS播放器常用功能 强制横屏 在播放器中常见强制横屏&#xff0c;例如&#xff0c;如下这种&#xff1a; OC实现代码如下&#xff1a; if ([[UIDevice currentDevice] respondsToSelector:selector(setOrientation:)]) {SEL selector NSSelectorFromString(&…

IOS开发之——音乐播放器-播放器页面(05)

一 概述 播放器页面Storyboard点击列表Cell时&#xff0c;播放器页面show弹出播放器页面按钮对应的功能 二 播放器页面Storyboard 2.1 Storyboard界面 2.2 界面说明 界面分类&#xff1a;顶部View和底部View两部分顶部View&#xff1a;歌曲大图、名字背景(歌曲名和歌手名)、…

西瓜视频 iOS 播放器技术重构

动手点关注 干货不迷路 &#x1f446; 播放器简介 播放器是西瓜视频等视频类 App 最主要的业务场景&#xff0c;也是最主要的流量入口&#xff0c;其承载包括下层基础播放&#xff0c;上层的各种播放业务&#xff1a;状态栏、弹幕、音量、亮度、评论、点赞、进度、倍速、清晰度…

iOS系统自带的视频播放器

简述:MPMoviePlayerController,MPMoviePlayerViewController,AVPlayerViewController三种视频播放器的讲解1.MPMoviePlayerController效果:MPMoviePlayerController 密码: yam8MPMoviePlayerController&#xff0c;在MediaPlayer框架中 #import <MediaPlayer/MediaPlayer.h&…

iOS 超好用的本地视频播放器推荐!

本地播放器作为日常生活中不可或缺的一款工具类APP&#xff0c;Windows、Android等平台不乏一些功能与体验兼优的产品&#xff0c;但 iOS 平台的用户就没有那么幸运了&#xff0c;优秀的产品凤毛麟角&#xff0c;且多数收费。 这源于 iOS 平台的特殊性&#xff0c;完美支持各种…

iOS视频播放器之ZFPlayer剖析

1、引言 本文主要针对ZFPlayer的功能实现来剖析&#xff0c;以及总结一下大家遇到的问题和解决方案 首先ZFPlayer现在拥有的功能&#xff1a; 支持横、竖屏切换&#xff0c;在全屏播放模式下还可以锁定屏幕方向 支持本地视频、网络视频播放 支持在TableviewCell播放视频 左侧1/…

996程序员办公室猝死?公司:没死,继续上班了

程序员头条 报道 网传 996 程序员办公室猝死&#xff0c;公司回应&#xff1a;系因低血糖晕倒 日前&#xff0c;一则“996程序员办公室猝死”的视频在网络传播。根据视频显示&#xff0c;一名男子扶着办公桌栏短暂逗留之后&#xff0c;直挺挺的摔倒在地面。 事发后&#xff0c;…

网传京东37岁程序员在工位猝死。当事人:我还没死,还能加班!

编程牛人整理 近日微信群里疯传&#xff0c;一男子在工位突然倒地的图片与视频&#xff0c;随后&#xff0c;有自媒体称&#xff0c;这位倒地的员工系京东程序员疑似因常年夜班在工位猝死。 3月25日&#xff0c;网传消息称&#xff0c;该员工今年37岁&#xff0c;在加班过程中猝…

35岁程序员被公司辞退,生活压力太大痛哭,中年危机如何自救?

多数人都喜欢安逸的生活&#xff0c;尤其是随着年龄的增长&#xff0c;很多人都希望工作和生活趋于稳定&#xff0c;不愿意再让生活有很大的变动。可是&#xff0c;当达到一定的年龄时&#xff0c;危机还是存在的。 如今已经35岁的杰哥&#xff0c;是一个典型的理工男&#xf…

秒啊!程序员防猝死指南来了!

‍‍ 作者 | 咏春警告的胖虎 来源 | golang小白成长记&#xff08;ID&#xff1a;golangxbczj&#xff09; 过年之前&#xff0c;跟我可爱的小侄子通了个电话&#xff0c;上来就说&#xff0c;"叔叔你头发怎么变少了"&#xff0c;我很痛心&#xff0c;我的小侄子&…

程序员工作猝死给公司造成损失可以找其父母追讨吗?

从 996.icu 开始&#xff0c;996开始被热议&#xff0c;马巴巴说&#xff1a;“996 是福报”&#xff0c;东哥说&#xff1a;“81168”。然后 90 后乃至 00 后被推出来说&#xff1a;“这届真难带&#xff01;”。我一直认为网上有个段子说得好。  ☠ 月薪5W&#xff1a;996就…

程序员离职事件始末

吴小胖第10次推送 阅读时间预计3分钟~ 这是我毕业后的第一份工作... 面试时&#xff0c;HR小姐姐告诉我... 然鹅...我入职之后才发现&#xff1a; 对标阿里的只有加班强度 对标华为的只有狼性文化 对标百度的&#xff0c;额&#xff0c;没有对标百度 同事们有的住在海淀区、有的…

为什么程序猿996会猝死,而企业家007却不会?

想和吴小胖一起工作吗&#xff1f; 内推邮箱【shen_baili163.com】&#xff0c;响应P99非常小 其实&#xff0c;也可以关注公众号&#xff0c;不取关的那种哦 然后留言&#xff0c;我会主动联系你哟 后面还会继续更新Apache Dubbo源码分析和ElasticSearch的内容哦&#xff0c;大…

唉!一 28 岁程序员因新冠离世。。。

上一篇&#xff1a;为什么总是闹离职的员工没走&#xff0c;平时不吭声的员工却突然离职&#xff1f; 2022年12月19日&#xff0c;微信公众号万户楼台 发布《西安28岁程序员重症病危》的内容。 病人名字为郭晓桐&#xff08;94年生&#xff09;&#xff0c;年龄28岁。 其没有基…

成年人的崩溃只在一瞬间,程序员凌晨三点写的代码竟被女友删了...

对于恋爱中的情侣来说&#xff0c;吵架是很正常的事情&#xff0c;就算是再怎么亲密&#xff0c;也难免会出现意见不合的时候。 吵架不可怕&#xff0c;可怕的是&#xff0c;受吵架情绪的影响&#xff0c;做出一些比较“极端”的事情。 之前某社交平台上一位女生吐槽自己的男…