需求设计

做一个小学生教育辅导视频播放器。

参考小猿搜题视频播放器

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-L0GsyFSt-1675164972791)(https://tva1.sinaimg.cn/large/008vxvgGgy1h9xk4fm5xfj31sx0u0mz0.jpg)]

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-XZ7e0Z3Z-1675164972792)(https://tva1.sinaimg.cn/large/008vxvgGgy1h9xk4fm5xfj31sx0u0mz0.jpg)]

主要功能

  • 非VIP用户免费播放开头部分;
  • 截屏;
  • 倍速播放;
  • 进度条快进快退;

实现原理

  1. 公开属性
#import "WMPlayer.h"
@property (nonatomic, retain) WMPlayerModel *playerModel;
@property (nonatomic, strong) WMPlayer  *wmPlayer;
  1. 实例化播放器
    //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];
  1. 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");
}
  1. 播放器代理
#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;}];
}
  1. 旋转屏幕通知
#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;}];
}
  1. 调用播放器
        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

WeChat

SJVideoPlayer

DouYin

TBPlayer

iOS视频播放器开发

iOS视频播放的基本方法

上传到阿里云OSS的视频如何实现在线播放

ZFPlayer 3.0解析

AVPlayer支持的视频格式

iOS音视频播放指南(一)

iOS音视频开发学习指南

iOS视频开发(一):视频采集

iOS 视频播放器开发相关推荐

  1. iOS视频播放器,IJKMediaFramework开发环境和测试环境集合包

    iOS视频播放器,IJKMediaFramework开发环境和测试环境集合包,支持https视频流播放,解压后大概160M多一点点.欢迎下载, 链接: https://pan.baidu.com/s/ ...

  2. Android进阶:自定义视频播放器开发(下)

    上一篇文章我们主要讲了视频播放器开发之前需要准备的一个知识,TextureView,用于对图像流的处理.这篇文章开始构建一个基础的视频播放器. 一.准备工作 在之前的文章已经说过了,播放器也是一个vi ...

  3. 实现在Android本地视频播放器开发

    在Android本地视频播放器开发中的搜索本地视频章节中,我们能够搜索本地视频并且显示每个视频的图片.标题.时间长度,当然如果需要添加其他的例如视频的长度和宽度可以使用Video类中的方法,既然我们获 ...

  4. Android本地视频播放器开发--视频解码

    在上一章Android本地视频播放器开发--SDL编译编译中编译出sdl的支持库,当时我们使用的2.0,但是有些api被更改了,所以在以下的使用者中我们使用SDL1.3的库,这个库我会传上源码以及编译 ...

  5. android 编译 sdl,SDL编译 - Android本地视频播放器开发_Linux编程_Linux公社-Linux系统门户网站...

    在上一章  Android本地视频播放器开发--ffmpeg解码视频文件中的音频(2)[http://www.linuxidc.com/Linux/2013-06/85955p5.htm]中使用Ope ...

  6. Android本地视频播放器开发--NDK编译FFmpeg

    在Android本地视频播放器开发中的搜索本地视频章节中,我们能够搜索本地视频并且显示每个视频的图片.标题.时间长度,当然如果需要添加其他的例如视频的长度和宽度可以使用Video类中的方法,既然我们获 ...

  7. Android进阶:自定义视频播放器开发(上)

    随着快手,抖音,西瓜视频等视频APP的崛起,视频播放已经成为主流,此时作为Android研发的你,想要提高自己的能力还不知道怎么开发视频播放器怎么行?所以今天就带着大家一起开发一个简易播放器:Smal ...

  8. Android本地视频播放器开发--SDL编译

    在上一章 Android本地视频播放器开发--ffmpeg解码视频文件中的音频(2)中使用OpenSL ES来播放视频的声音,遗留的问题是声音的不同步,由于视频实现部分也要同步,而且音视频也要同步,所 ...

  9. Android本地视频播放器开发 - 搜索本地视频(1)

    这一章的主要内容是搜索手机本地视频,添加到ListView列表里,每一个表项含有这个视频的缩略图,视频的播放时间,视频的标题,在搜索本地视频(1)中我们先制作搜索功能.   Video.java--视 ...

最新文章

  1. 安装rational rose
  2. JFrame中使用jpanel来布局
  3. 史上最轻量​!阿里新型单元测试Mock工具开源了
  4. 【OpenJ_Bailian - 2299 】Ultra-QuickSort (归并排序 或 离散化 + 树状数组)
  5. 性能调优的方法及概念
  6. java 分词词频_利用word分词来对文本进行词频统计
  7. python特性描述_详解 Python 最优雅的特性之一 — 描述符
  8. 互联网上,极致才能成功
  9. maven gradle等三放jar包仓库
  10. 大学计算机专业分流考试,北京林业大学计算机类(入学一年后分流至计算机科学与技术、数字媒体技术、网络工程、计算机科学与技术(物联网))专业2016年在江苏理科高考录取最低分数线...
  11. 1.SpringDataJPA (查询:主键或其他字段、增加/修改、分页) 2021最新技术~方便快捷 博主可答疑
  12. 2021年下软考中级软件设计师经验分享通过技巧
  13. unix文件中i节点
  14. 空手套白狼的典型案例,不花一分钱,整合别家产品,赚自己的钱
  15. ava程序员职业生涯规划范文
  16. 规划Autovue的安装
  17. unzip 分包_劳务派遣第二讲一一劳务派遣和劳务分包有啥区别?
  18. consul服务注册中心
  19. Google Voice 虚拟号码
  20. QGIS 下载慢解决:

热门文章

  1. python机器学习常用模型
  2. Python如何将多张照片制作成视频
  3. 电脑为啥老是黑屏?只因为你不知道这9种方法
  4. 将循迹小车改为蓝牙控制自动避障小车#arduino
  5. 基于51单片机的电子钟设计[本科自动化毕业设计论文,源码,实物]
  6. 隐藏在QQ2000当中的大秘密 !!!
  7. 五一后“实在高校行”紧锣密鼓走进四所高校,校企合作硕果累累!
  8. 通信运营商在信息化路上举步维艰
  9. 二叉树的创建和遍历(查找key,返回二叉树的层数)
  10. (CMake) 从下载到构建第一个CMake应用