iOS 视频播放器开发
需求设计
做一个小学生教育辅导视频播放器。
参考小猿搜题视频播放器
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-L0GsyFSt-1675164972791)(https://tva1.sinaimg.cn/large/008vxvgGgy1h9xk4fm5xfj31sx0u0mz0.jpg)]
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-XZ7e0Z3Z-1675164972792)(https://tva1.sinaimg.cn/large/008vxvgGgy1h9xk4fm5xfj31sx0u0mz0.jpg)]
主要功能:
- 非VIP用户免费播放开头部分;
- 截屏;
- 倍速播放;
- 进度条快进快退;
实现原理
- 公开属性
#import "WMPlayer.h"
@property (nonatomic, retain) WMPlayerModel *playerModel;
@property (nonatomic, strong) WMPlayer *wmPlayer;
- 实例化播放器
//self.wmPlayer = [[WMPlayer alloc] initWithFrame:CGRectMake(0, [WMPlayer IsiPhoneX]?34:0, self.view.frame.size.width, self.view.frame.size.width*(9.0/16))];self.wmPlayer = [[WMPlayer alloc] initWithFrame:CGRectMake(0, 44, self.view.frame.size.width, self.view.frame.size.height-88)];self.wmPlayer.delegate = self;self.wmPlayer.playerModel = self.playerModel;[self.view addSubview:self.wmPlayer];[self.wmPlayer play];//旋转屏幕通知[[NSNotificationCenter defaultCenter] addObserver:selfselector:@selector(onDeviceOrientationChange:)name:UIDeviceOrientationDidChangeNotificationobject:nil];
- VC生命周期
#pragma mark - Life Cycle- (void)viewWillAppear:(BOOL)animated{[super viewWillAppear:animated];[self.navigationController setNavigationBarHidden:YES animated:NO];self.view.frame = UIScreen.mainScreen.bounds;self.wmPlayer.delegate = self;
}-(void)viewDidDisappear:(BOOL)animated{[super viewDidAppear:animated];[self.navigationController setNavigationBarHidden:NO animated:NO];
}- (void)dealloc{[self.wmPlayer pause];[self.wmPlayer removeFromSuperview];self.wmPlayer = nil;[[NSNotificationCenter defaultCenter] removeObserver:self];NSLog(@"DetailViewController dealloc");
}
- 播放器代理
#pragma mark - WMPlayerDelegate
///播放器CloseButton
-(void)wmplayer:(WMPlayer *)wmplayer clickedCloseButton:(UIButton *)closeBtn{if (wmplayer.isFullscreen) {[self exitFullScreen];}else{if (self.presentingViewController) {[self dismissViewControllerAnimated:YES completion:^{}];}else{[self.navigationController popViewControllerAnimated:YES];}}
}
///全屏按钮
-(void)wmplayer:(WMPlayer *)wmplayer clickedFullScreenButton:(UIButton *)fullScreenBtn{if (self.wmPlayer.viewState == PlayerViewStateSmall) {[self enterFullScreen];}
}-(void)enterFullScreen{if (self.wmPlayer.viewState != PlayerViewStateSmall) {return;}LandscapeRightViewController *rightVC = [[LandscapeRightViewController alloc] init];[self presentToVC:rightVC];
}-(void)exitFullScreen{if (self.wmPlayer.viewState!=PlayerViewStateFullScreen) {return;}self.wmPlayer.isFullscreen = NO;self.wmPlayer.viewState = PlayerViewStateAnimating;[self dismissViewControllerAnimated:YES completion:^{self.wmPlayer.viewState = PlayerViewStateSmall;}];
}
- 旋转屏幕通知
#pragma mark - NSNotificationCenter
/*** 旋转屏幕通知*/
- (void)onDeviceOrientationChange:(NSNotification *)notification{if (self.wmPlayer.viewState!=PlayerViewStateSmall) {return;}if (self.wmPlayer.isLockScreen){return;}UIDeviceOrientation orientation = [UIDevice currentDevice].orientation;UIInterfaceOrientation interfaceOrientation = (UIInterfaceOrientation)orientation;switch (interfaceOrientation) {case UIInterfaceOrientationPortraitUpsideDown:{}break;case UIInterfaceOrientationPortrait:{}break;case UIInterfaceOrientationLandscapeLeft:{[self presentToVC:[LandscapeLeftViewController new]];}break;case UIInterfaceOrientationLandscapeRight:{[self presentToVC:[LandscapeRightViewController new]];}break;default:break;}
}-(void)presentToVC:(FullScreenHelperViewController *)aHelperVC{self.wmPlayer.viewState = PlayerViewStateAnimating;self.wmPlayer.beforeBounds = self.wmPlayer.bounds;self.wmPlayer.beforeCenter = self.wmPlayer.center;self.wmPlayer.parentView = self.wmPlayer.superview;self.wmPlayer.isFullscreen = YES;aHelperVC.wmPlayer = self.wmPlayer;aHelperVC.modalPresentationStyle = UIModalPresentationFullScreen;aHelperVC.transitioningDelegate = self;[self presentViewController:aHelperVC animated:YES completion:^{self.wmPlayer.viewState = PlayerViewStateFullScreen;}];
}
- 调用播放器
VideoDataModel *videoModel = self.videoDataAry[indexPath.row];WMPlayerModel *playerModel = [WMPlayerModel new];playerModel.videoURL = [NSURL URLWithString:videoModel.video_url];//playerModel.videoURL = [NSURL URLWithString:@"http://static.tripbe.com/videofiles/20121214/9533522808.f4v.mp4"];//playerModel.videoURL = [NSURL URLWithString:@"http://img.zhuoqi.tech/test_h264_level30_480_360.mp4"];playerModel.title = videoModel.nickname;DetailViewController *detailVC = [DetailViewController new];detailVC.playerModel = playerModel;[self.navigationController pushViewController:detailVC animated:YES];
基本概念
一个在线视频能够播放,大致是经过了如下步骤:
HLS(Http Live Streaming)
HLS是苹果推出,实现的基于HTTP的流媒体传输协议:
优点:
1、通过m3u8索引文件可实现针对当前浏览设备的智能选择播放源
2、通过m3u8索引文件可实现添加备份索引文件,防止服务器崩溃视频播放失败
3、和http视频一样不需要太多服务器额外配置
缺点:
1、并非真正实时视频,30s左右时间差
2、需要视频处理
3、因为需要请求索引文件(ts视频文件)请求次数相对较多,对服务器负载较大
AVPlayer支持哪些视频格式
苹果设备支持音视频格式并不是就代表AVPlayer也支持那么多格式,确定AVPlayer的支持格式,我们可以查看AVKit中的一个API:
//展示当前支持的音视频格式
let asset = AVURLAsset.audiovisualTypes()
//打印asset可以得到(已经转过展示格式)
asset type ("audio/aacp","video/3gpp2","audio/mpeg3","audio/mp3","audio/x-caf","audio/mpeg","video/quicktime","audio/x-mpeg3","video/mp4","audio/wav","video/avi","audio/scpls","audio/mp4","audio/x-mpg","video/x-m4v","audio/x-wav","audio/x-aiff","application/vnd.apple.mpegurl","video/3gpp","text/vtt","audio/x-mpeg","audio/wave","audio/x-m4r","audio/x-mp3","audio/AMR","audio/aiff","audio/3gpp2","audio/aac","audio/mpg","audio/mpegurl","audio/x-m4b","application/mp4","audio/x-m4p","audio/x-scpls","audio/x-mpegurl","audio/x-aac","audio/3gpp","audio/basic","audio/x-m4a","application/x-mpegurl"
)
AVPlayer支持的
视频编码格式:H.264、HEVC(iPhone7及以后设备)、MPEG-4。
视频封装格式:.mp4、.mov、.m4v、.3gp、.avi等。
如果想支持更多的视频格式,可以使用使用第三方的框架,常用的视频编码和解码框架有VLC和ffmpeg。
AVPlayerItem的控制
AVPlayerItem
作为资源管理对象,它控制着视频从创建到销毁的诸多状态。
播放状态 status
typedef NS_ENUM(NSInteger,AVPlayerItemStatus) {AVPlayerItemStatusUnknown,//未知AVPlayerItemStatusReadyToPlay,//准备播放AVPlayerItemStatusFailed//播放失败
};
我们使用KVO监测playItem.status,可以获取播放状态的变化
[self.playerItem addObserver:selfforKeyPath:@"status"options:NSKeyValueObservingOptionNewcontext:nil];
在监听回调中:
- (void)observeValueForKeyPath:(NSString*)keyPath ofObject:(id)object change:(NSDictionary *)change context:(void*)context{if([object isKindOfClass:[AVPlayerItemclass]]) {if([keyPath isEqualToString:@"status"]) {switch(_playerItem.status) {caseAVPlayerItemStatusReadyToPlay://推荐将视频播放放这里[self play];break;caseAVPlayerItemStatusUnknown:NSLog(@"AVPlayerItemStatusUnknown");break;caseAVPlayerItemStatusFailed:NSLog(@"AVPlayerItemStatusFailed");break;default:break;}}}
}
虽然设置完播放配置我们可以直接调用[self.player play];
进行播放,但是更稳妥的方法是在回调收到AVPlayerItemStatusReadyToPlay
时进行播放。
参考文章
HTTP Streaming Architecture
HTTP Live Streaming
WMPlayer
SJVideoPlayer
DouYin
TBPlayer
iOS视频播放器开发
iOS视频播放的基本方法
上传到阿里云OSS的视频如何实现在线播放
ZFPlayer 3.0解析
AVPlayer支持的视频格式
iOS音视频播放指南(一)
iOS音视频开发学习指南
iOS视频开发(一):视频采集
iOS 视频播放器开发相关推荐
- iOS视频播放器,IJKMediaFramework开发环境和测试环境集合包
iOS视频播放器,IJKMediaFramework开发环境和测试环境集合包,支持https视频流播放,解压后大概160M多一点点.欢迎下载, 链接: https://pan.baidu.com/s/ ...
- Android进阶:自定义视频播放器开发(下)
上一篇文章我们主要讲了视频播放器开发之前需要准备的一个知识,TextureView,用于对图像流的处理.这篇文章开始构建一个基础的视频播放器. 一.准备工作 在之前的文章已经说过了,播放器也是一个vi ...
- 实现在Android本地视频播放器开发
在Android本地视频播放器开发中的搜索本地视频章节中,我们能够搜索本地视频并且显示每个视频的图片.标题.时间长度,当然如果需要添加其他的例如视频的长度和宽度可以使用Video类中的方法,既然我们获 ...
- Android本地视频播放器开发--视频解码
在上一章Android本地视频播放器开发--SDL编译编译中编译出sdl的支持库,当时我们使用的2.0,但是有些api被更改了,所以在以下的使用者中我们使用SDL1.3的库,这个库我会传上源码以及编译 ...
- android 编译 sdl,SDL编译 - Android本地视频播放器开发_Linux编程_Linux公社-Linux系统门户网站...
在上一章 Android本地视频播放器开发--ffmpeg解码视频文件中的音频(2)[http://www.linuxidc.com/Linux/2013-06/85955p5.htm]中使用Ope ...
- Android本地视频播放器开发--NDK编译FFmpeg
在Android本地视频播放器开发中的搜索本地视频章节中,我们能够搜索本地视频并且显示每个视频的图片.标题.时间长度,当然如果需要添加其他的例如视频的长度和宽度可以使用Video类中的方法,既然我们获 ...
- Android进阶:自定义视频播放器开发(上)
随着快手,抖音,西瓜视频等视频APP的崛起,视频播放已经成为主流,此时作为Android研发的你,想要提高自己的能力还不知道怎么开发视频播放器怎么行?所以今天就带着大家一起开发一个简易播放器:Smal ...
- Android本地视频播放器开发--SDL编译
在上一章 Android本地视频播放器开发--ffmpeg解码视频文件中的音频(2)中使用OpenSL ES来播放视频的声音,遗留的问题是声音的不同步,由于视频实现部分也要同步,而且音视频也要同步,所 ...
- Android本地视频播放器开发 - 搜索本地视频(1)
这一章的主要内容是搜索手机本地视频,添加到ListView列表里,每一个表项含有这个视频的缩略图,视频的播放时间,视频的标题,在搜索本地视频(1)中我们先制作搜索功能. Video.java--视 ...
最新文章
- 安装rational rose
- JFrame中使用jpanel来布局
- 史上最轻量​!阿里新型单元测试Mock工具开源了
- 【OpenJ_Bailian - 2299 】Ultra-QuickSort (归并排序 或 离散化 + 树状数组)
- 性能调优的方法及概念
- java 分词词频_利用word分词来对文本进行词频统计
- python特性描述_详解 Python 最优雅的特性之一 — 描述符
- 互联网上,极致才能成功
- maven gradle等三放jar包仓库
- 大学计算机专业分流考试,北京林业大学计算机类(入学一年后分流至计算机科学与技术、数字媒体技术、网络工程、计算机科学与技术(物联网))专业2016年在江苏理科高考录取最低分数线...
- 1.SpringDataJPA (查询:主键或其他字段、增加/修改、分页) 2021最新技术~方便快捷 博主可答疑
- 2021年下软考中级软件设计师经验分享通过技巧
- unix文件中i节点
- 空手套白狼的典型案例,不花一分钱,整合别家产品,赚自己的钱
- ava程序员职业生涯规划范文
- 规划Autovue的安装
- unzip 分包_劳务派遣第二讲一一劳务派遣和劳务分包有啥区别?
- consul服务注册中心
- Google Voice 虚拟号码
- QGIS 下载慢解决: