今天看到有许多问道有关视频播放器的问题,那么现在就来写个自定义视频播放器的 Demo 吧

     首先,自定义视频播放器是基于系统

#import <AVFoundation/AVFoundation.h>,#import <MediaPlayer/MediaPlayer.h>来实现的

所以,需要引用系统库文件:MediaPlayer.framework.

实现代码如下:

#import "MoviePlayerViewController.h"

#import <AVFoundation/AVFoundation.h>

#import <MediaPlayer/MediaPlayer.h>

@interface MoviePlayerViewController ()

@property(nonatomic,strong)AVPlayer *player; // 播放属性

@property(nonatomic,strong)AVPlayerItem *playerItem; // 播放属性

@property(nonatomic,assign)CGFloat width; // 坐标

@property(nonatomic,assign)CGFloat height; // 坐标

@property(nonatomic,strong)UISlider *slider; // 进度条

@property(nonatomic,strong)UILabel *currentTimeLabel; // 当前播放时间

@property(nonatomic,strong)UILabel *systemTimeLabel; // 系统时间

@property(nonatomic,strong)UIView *backView; // 上面一层Viewd

@property(nonatomic,assign)CGPoint startPoint;

@property(nonatomic,assign)CGFloat systemVolume;

@property(nonatomic,strong)UISlider *volumeViewSlider;

@property(nonatomic,strong)UIActivityIndicatorView *activity; // 系统菊花

@property(nonatomic,strong)UIProgressView *progress; // 缓冲条

@property(nonatomic,strong)UIView *topView;

@end

@implementation MoviePlayerViewController

- (void)dealloc

{

[[NSNotificationCenter defaultCenter] removeObserver:self name:AVPlayerItemDidPlayToEndTimeNotification object:_player.currentItem];

}

- (void)viewDidLoad {

[super viewDidLoad];

self.view.backgroundColor = [UIColor blackColor];

_width = [[UIScreen mainScreen]bounds].size.height;

_height = [[UIScreen mainScreen]bounds].size.width;

// 创建AVPlayer

self.playerItem = [AVPlayerItem playerItemWithURL:[NSURL URLWithString:@"http://baobab.cdn.wandoujia.com/14468618701471.mp4"]];

self.player = [AVPlayer playerWithPlayerItem:_playerItem];

AVPlayerLayer *playerLayer = [AVPlayerLayer playerLayerWithPlayer:_player];

playerLayer.frame = CGRectMake(0, 0, _width, _height);

playerLayer.videoGravity = AVLayerVideoGravityResize;

[self.view.layer addSublayer:playerLayer];

[_player play];

//AVPlayer播放完成通知

[[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(moviePlayDidEnd:) name:AVPlayerItemDidPlayToEndTimeNotification object:_player.currentItem];

self.backView = [[UIView alloc]initWithFrame:CGRectMake(0, 0, _width, _height)];

[self.view addSubview:_backView];

_backView.backgroundColor = [UIColor clearColor];

self.topView = [[UIView alloc]initWithFrame:CGRectMake(0, 0, _width, _height * 0.15)];

_topView.backgroundColor = [UIColor blackColor];

_topView.alpha = 0.5;

[_backView addSubview:_topView];

[self.playerItem addObserver:self forKeyPath:@"loadedTimeRanges" options:NSKeyValueObservingOptionNew context:nil];// 监听loadedTimeRanges属性

[self createProgress];

[self createSlider];

[self createCurrentTimeLabel];

[self createButton];

[self backButton];

[self createTitle];

[self createGesture];

[self customVideoSlider];

self.activity = [[UIActivityIndicatorView alloc]initWithActivityIndicatorStyle:UIActivityIndicatorViewStyleWhite];

_activity.center = _backView.center;

[self.view addSubview:_activity];

[_activity startAnimating];

//    //延迟线程

dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(7 * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{

[UIView animateWithDuration:0.5 animations:^{

_backView.alpha = 0;

}];

});

//计时器

[NSTimer scheduledTimerWithTimeInterval:1.f target:self selector:@selector(Stack) userInfo:nil repeats:YES];

//    self.modalPresentationCapturesStatusBarAppearance = YES;

}

#pragma mark - 横屏代码

- (BOOL)shouldAutorotate{

return NO;

} //NS_AVAILABLE_IOS(6_0);当前viewcontroller是否支持转屏

- (UIInterfaceOrientationMask)supportedInterfaceOrientations{

return UIInterfaceOrientationMaskLandscape;

} //当前viewcontroller支持哪些转屏方向

-(UIInterfaceOrientation)preferredInterfaceOrientationForPresentation {

return UIInterfaceOrientationLandscapeRight;

}

- (BOOL)prefersStatusBarHidden

{

return NO; // 返回NO表示要显示,返回YES将hiden

}

#pragma mark - 创建UISlider

- (void)createSlider

{

self.slider = [[UISlider alloc]initWithFrame:CGRectMake(100, 345, _width * 0.7, 15)];

[self.backView addSubview:_slider];

[_slider setThumbImage:[UIImage imageNamed:@"iconfont-yuan.png"] forState:UIControlStateNormal];

[_slider addTarget:self action:@selector(progressSlider:) forControlEvents:UIControlEventValueChanged];

_slider.minimumTrackTintColor = [UIColor colorWithRed:30 / 255.0 green:80 / 255.0 blue:100 / 255.0 alpha:1];

}

#pragma mark - slider滑动事件

- (void)progressSlider:(UISlider *)slider

{

//拖动改变视频播放进度

if (_player.status == AVPlayerStatusReadyToPlay) {

//    //计算出拖动的当前秒数

CGFloat total = (CGFloat)_playerItem.duration.value / _playerItem.duration.timescale;

//    NSLog(@"%f", total);

NSInteger dragedSeconds = floorf(total * slider.value);

//    NSLog(@"dragedSeconds:%ld",dragedSeconds);

//转换成CMTime才能给player来控制播放进度

CMTime dragedCMTime = CMTimeMake(dragedSeconds, 1);

[_player pause];

[_player seekToTime:dragedCMTime completionHandler:^(BOOL finish){

[_player play];

}];

}

}

#pragma mark - 创建UIProgressView

- (void)createProgress

{

self.progress = [[UIProgressView alloc]initWithFrame:CGRectMake(102, 352, _width * 0.69, 15)];

[_backView addSubview:_progress];

}

#pragma mark -

- (void)observeValueForKeyPath:(NSString *)keyPath ofObject:(id)object change:(NSDictionary<NSString *,id> *)change context:(void *)context

{

if ([keyPath isEqualToString:@"loadedTimeRanges"]) {

NSTimeInterval timeInterval = [self availableDuration];// 计算缓冲进度

//        NSLog(@"Time Interval:%f",timeInterval);

CMTime duration = self.playerItem.duration;

CGFloat totalDuration = CMTimeGetSeconds(duration);

[self.progress setProgress:timeInterval / totalDuration animated:NO];

}

}

- (NSTimeInterval)availableDuration {

NSArray *loadedTimeRanges = [[_player currentItem] loadedTimeRanges];

CMTimeRange timeRange = [loadedTimeRanges.firstObject CMTimeRangeValue];// 获取缓冲区域

float startSeconds = CMTimeGetSeconds(timeRange.start);

float durationSeconds = CMTimeGetSeconds(timeRange.duration);

NSTimeInterval result = startSeconds + durationSeconds;// 计算缓冲总进度

return result;

}

- (void)customVideoSlider {

UIGraphicsBeginImageContextWithOptions((CGSize){ 1, 1 }, NO, 0.0f);

UIImage *transparentImage = UIGraphicsGetImageFromCurrentImageContext();

UIGraphicsEndImageContext();

//    [self.slider setMinimumTrackImage:transparentImage forState:UIControlStateNormal];

[self.slider setMaximumTrackImage:transparentImage forState:UIControlStateNormal];

}

#pragma mark - 创建播放时间

- (void)createCurrentTimeLabel

{

self.currentTimeLabel = [[UILabel alloc]initWithFrame:CGRectMake(_width *0.86, 342, 100, 20)];

[self.backView addSubview:_currentTimeLabel];

_currentTimeLabel.textColor = [UIColor whiteColor];

//    _currentTimeLabel.backgroundColor = [UIColor blueColor];

_currentTimeLabel.font = [UIFont systemFontOfSize:12];

_currentTimeLabel.text = @"00:00/00:00";

}

#pragma mark - 计时器事件

- (void)Stack

{

if (_playerItem.duration.timescale != 0) {

_slider.maximumValue = 1;//音乐总共时长

_slider.value = CMTimeGetSeconds([_playerItem currentTime]) / (_playerItem.duration.value / _playerItem.duration.timescale);//当前进度

//当前时长进度progress

NSInteger proMin = (NSInteger)CMTimeGetSeconds([_player currentTime]) / 60;//当前秒

NSInteger proSec = (NSInteger)CMTimeGetSeconds([_player currentTime]) % 60;//当前分钟

//    NSLog(@"%d",_playerItem.duration.timescale);

//    NSLog(@"%lld",_playerItem.duration.value/1000 / 60);

//duration 总时长

NSInteger durMin = (NSInteger)_playerItem.duration.value / _playerItem.duration.timescale / 60;//总秒

NSInteger durSec = (NSInteger)_playerItem.duration.value / _playerItem.duration.timescale % 60;//总分钟

self.currentTimeLabel.text = [NSString stringWithFormat:@"%02ld:%02ld / %02ld:%02ld", proMin, proSec, durMin, durSec];

}

if (_player.status == AVPlayerStatusReadyToPlay) {

[_activity stopAnimating];

} else {

[_activity startAnimating];

}

}

#pragma mark - 播放和下一首按钮

- (void)createButton

{

UIButton *startButton = [UIButton buttonWithType:UIButtonTypeCustom];

startButton.frame = CGRectMake(15, 337, 30, 30);

[self.backView addSubview:startButton];

if (_player.rate == 1.0) {

[startButton setBackgroundImage:[UIImage imageNamed:@"pauseBtn@2x.png"] forState:UIControlStateNormal];

} else {

[startButton setBackgroundImage:[UIImage imageNamed:@"playBtn@2x.png"] forState:UIControlStateNormal];

}

[startButton addTarget:self action:@selector(startAction:) forControlEvents:UIControlEventTouchUpInside];

UIButton *nextButton = [UIButton buttonWithType:UIButtonTypeCustom];

nextButton.frame = CGRectMake(60, 340, 25, 25);

[self.backView addSubview:nextButton];

[nextButton setBackgroundImage:[UIImage imageNamed:@"nextPlayer@3x.png"] forState:UIControlStateNormal];

}

#pragma mark - 播放暂停按钮方法

- (void)startAction:(UIButton *)button

{

if (button.selected) {

[_player play];

[button setBackgroundImage:[UIImage imageNamed:@"pauseBtn@2x.png"] forState:UIControlStateNormal];

} else {

[_player pause];

[button setBackgroundImage:[UIImage imageNamed:@"playBtn@2x.png"] forState:UIControlStateNormal];

}

button.selected =!button.selected;

}

#pragma mark - 返回按钮方法

- (void)backButton

{

UIButton *button = [UIButton buttonWithType:UIButtonTypeCustom];

button.frame = CGRectMake(15, 20, 30, 30);

[button setBackgroundImage:[UIImage imageNamed:@"iconfont-back.png"] forState:UIControlStateNormal];

[_topView addSubview:button];

[button addTarget:self action:@selector(backButtonAction) forControlEvents:UIControlEventTouchUpInside];

}

#pragma mark - 创建标题

- (void)createTitle

{

UILabel *label = [[UILabel alloc]initWithFrame:CGRectMake(80, 20, 250, 30)];

[_backView addSubview:label];

label.textColor = [UIColor whiteColor];

label.textAlignment = NSTextAlignmentCenter;

}

#pragma mark - 创建手势

- (void)createGesture

{

UITapGestureRecognizer *tap = [[UITapGestureRecognizer alloc]initWithTarget:self action:@selector(tapAction:)];

[self.view addGestureRecognizer:tap];

//获取系统音量

MPVolumeView *volumeView = [[MPVolumeView alloc] init];

_volumeViewSlider = nil;

for (UIView *view in [volumeView subviews]){

if ([view.class.description isEqualToString:@"MPVolumeSlider"]){

_volumeViewSlider = (UISlider *)view;

break;

}

}

_systemVolume = _volumeViewSlider.value;

}

#pragma mark - 轻拍方法

- (void)tapAction:(UITapGestureRecognizer *)tap

{

if (_backView.alpha == 1) {

[UIView animateWithDuration:0.5 animations:^{

_backView.alpha = 0;

}];

} else if (_backView.alpha == 0){

[UIView animateWithDuration:0.5 animations:^{

_backView.alpha = 1;

}];

}

if (_backView.alpha == 1) {

dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(7 * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{

[UIView animateWithDuration:0.5 animations:^{

_backView.alpha = 0;

}];

});

}

}

#pragma mark - 滑动调整音量大小

- (void)touchesBegan:(NSSet<UITouch *> *)touches withEvent:(UIEvent *)event

{

if(event.allTouches.count == 1){

//保存当前触摸的位置

CGPoint point = [[touches anyObject] locationInView:self.view];

_startPoint = point;

}

}

-(void)touchesMoved:(NSSet *)touches withEvent:(UIEvent *)event{

if(event.allTouches.count == 1){

//计算位移

CGPoint point = [[touches anyObject] locationInView:self.view];

//        float dx = point.x - startPoint.x;

float dy = point.y - _startPoint.y;

int index = (int)dy;

if(index>0){

if(index%5==0){//每10个像素声音减一格

NSLog(@"%.2f",_systemVolume);

if(_systemVolume>0.1){

_systemVolume = _systemVolume-0.05;

[_volumeViewSlider setValue:_systemVolume animated:YES];

[_volumeViewSlider sendActionsForControlEvents:UIControlEventTouchUpInside];

}

}

}else{

if(index%5==0){//每10个像素声音增加一格

NSLog(@"+x ==%d",index);

NSLog(@"%.2f",_systemVolume);

if(_systemVolume>=0 && _systemVolume<1){

_systemVolume = _systemVolume+0.05;

[_volumeViewSlider setValue:_systemVolume animated:YES];

[_volumeViewSlider sendActionsForControlEvents:UIControlEventTouchUpInside];

}

}

}

//亮度调节

//        [UIScreen mainScreen].brightness = (float) dx/self.view.bounds.size.width;

}

}

- (void)moviePlayDidEnd:(id)sender

{

//    [_player pause];

[self dismissViewControllerAnimated:YES completion:^{

}];

}

- (void)backButtonAction

{

[_player pause];

[self dismissViewControllerAnimated:YES completion:^{

}];

}

- (void)didReceiveMemoryWarning {

[super didReceiveMemoryWarning];

// Dispose of any resources that can be recreated.

}

iOS 自定义视频播放器相关推荐

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

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

  2. iOS AVPlayer视频播放器

    代码地址如下: http://www.demodashi.com/demo/11168.html 一.运行效果 二.实现过程 ①.创建播放器avPlayer //创建播放器url = [url str ...

  3. Android开发笔记(一百二十五)自定义视频播放器

    视频播放方式 在Android中播放视频的方式有两种: 1.使用MediaPlayer结合SurfaceView进行播放.其中通过SurfaceView显示视频的画面,通过MediaPlayer来设置 ...

  4. 一步步自定义视频播放器——TextureView+MediaPlayer自定义视频播放器

    本篇参考封装一个视频播放器,原文已经写的非常棒了,本篇加入了个人对其内容的理解.秉承不重复造轮子的良好理念,接下来开始拆解轮子.内容非常多,我都差点放弃写,有耐心的请往下看 github上非常棒的视频 ...

  5. Android自定义视频播放器(三)

    参看:Android自定义视频播放器(一):https://blog.csdn.net/zxd1435513775/article/details/81507909 参看:Android自定义视频播放 ...

  6. HTML5 自定义视频播放器

    HTML5 自定义视频播放器 第一步:获取播放器 第二步:实现播放与暂停 第三步:实现全屏操作 第四步:实现播放的逻辑 第五步:实现播放过程的逻辑 第六步:实现视频的跳播 第七步:播放完毕后重置播放器 ...

  7. 自定义视频播放器与慢放滚轮

    受同学之邀,帮忙自定义一控件.需求是:开发慢放滚轮,用手指拨动实现帧级的慢速播放,滚轮可双向拨动,其滚动具有惯性,滚动速度决定视频播放的速度.需求很明朗,可我却是一头雾水.说实话,在此之前我还没有自定 ...

  8. Android 自定义视频播放器

    由于录像之后,原先选用的腾讯VOD点播播放器显示出来竖屏都变横屏了,虽然选中了现在的腾讯VOD点播,还是把Android视频播放器了解了一番. Android自定义视频播放器有以下三种: 一.Medi ...

  9. HTML5视频(自定义视频播放器源码)

    video对象 兼容情况: safari浏览器不支持webm格式 Chrome浏览器支持webm格式 ie8以及以下不支持video标签 , ie9支持video标签 ,但是支持mp4格式的 Fire ...

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

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

最新文章

  1. 制度汇编格式怎么生成目录_来自世界500强企业的管理表格DOC格式 1900套
  2. 最新调查:等这一波COBOL程序员退休,很多关键岗位就后继无人了
  3. GitHub最最最火的开源爬虫工具箱,一爬就取
  4. java object 引用类型_java中的四种引用类型
  5. arduino代码_arduino智能小车项目——01、配件介绍及代码部分教程
  6. java设计智慧教室_物联网智慧教室设计方案,更便捷的智慧教学体验
  7. Bootstrap 异常
  8. 获取当前电脑全部网络连接名字
  9. 构建插件式的应用程序框架(四)----服务容器(ZT)
  10. awk 字符串替换 gsub
  11. IDEA maven库里 添加自定义jar包
  12. stdafx.h到底有什么用
  13. 搭建公司wiki系统
  14. 从游戏中学习产品设计04:成就篇
  15. 戴尔服务器关闭系统自检,戴尔开机自检取消操作方法
  16. 手机,电脑都能用的,整人,恶搞代码连接,“你不会百度一下吗”教你用百度
  17. asp.net 面试题目
  18. 针对此次疫情的防控建议
  19. C语言简单入门教程(初学者用)
  20. vrp量子遗传matlab,遗传算法求解VRP问题的技术报告

热门文章

  1. Structs2-基础
  2. 我的世界手机版javaui材质包_传奇世界有元神怀旧版下载-传奇世界有元神怀旧版手机下载v1.0...
  3. Resource Hacker软件更换应用图标
  4. 回归方程的拟合优度检验_回归分析的“拟合优度”是什么?
  5. HSqlDB认识及使用
  6. 软件测试工程师企业级培训视频教程
  7. ArcGIS分享: 地图分幅及编号
  8. 新买的笔记本电脑怎么分盘_2020年笔记本电脑选购有哪些建议和推荐?
  9. 元宇宙8大创业方向:虚拟偶像、数字孪生…
  10. 简单易用的标签列表界面(宝宝用了都不哭了 )