前言###

由于什么直播、小视频火爆之后,我们开发者也要准备我们的播放器了,最常用到的肯定是自定义AVPlayer播放器,虽然本文也主要研究的也是AVPlayer,但是你知道吗?苹果其实为我们提供了三种播放器。

播放两种视频###

1、播放本地视频
播放本地视频其实就是播放本地的视频文件路径,[NSURL fileURLWithPath:videoPath];找到文件路径并且播放
2、播放网络视频
简单来讲就是我们设置播放器url地址等参数后,播放器就会向远程url所在服务器发送请求(一般请求包括两个值,一个是offset偏移量,另一个是length长度),然后服务器就会根据参数返回数据给播放器。
3、播放器一般支持播放格式
AVPlayer支持WMV,AVI,MKV,RMVB,RM,XVID,MP4,3GP,MPG等
MPMoviePlayerController与MPMoviePlayerViewController支持MOV, MP4, .MPV、3GP等

苹果的三种播放器播放视频###

我写了一个实例demo,包括
1、MPMoviePlayerController播放视频
2、MPMoviePlayerViewController播放视频
3、AVPlayer播放视频当个视频
4、AVPlayer播放视频多个视频
项目下载地址:三种视频播放器大总结
项目效果图

三种播放器大总结.gif

一、MPMoviePlayerController播放视频,但是iOS3.2之后不建议使用
这个播放器在MediaPlayer中,所以在使用的时候,必须先导入
#import <MediaPlayer/MediaPlayer.h>
MPMoviePlayerController播放器是继承于NSObject,但是内部有个view可以展示视频内容,如果将该视图添加其他控制器的view上,即可显示视频内容
播放状态需要增加观察者来监听

  • (MPMoviePlayerController *)player
    {
    if(_player == nil)
    {
    // 1.创建播放器
    NSURL url = [NSURL URLWithString:self.videoPath];
    _player = [[MPMoviePlayerController alloc]initWithContentURL:url];
    // 2.给播放器内部的View设置frame
    _player.view.frame = CGRectMake(0, 64, self.view.bounds.size.width, self.view.bounds.size.width * 9 / 16);
    // 3.添加到控制器View中
    [self.view addSubview:_player.view];
    //监听当前视频播放状态
    [[NSNotificationCenter defaultCenter]addObserver:self selector:@selector(loadStateDidChange:) name:MPMoviePlayerLoadStateDidChangeNotification object:nil];
    // 4.设置控制面板的显示
    //_player.controlStyle = MPMovieControlStyleFullscreen;
    }
    return _player;
    }
    -(void)loadStateDidChange:(NSNotification
    )sender
    {
    switch (self.player.loadState) {
    case MPMovieLoadStatePlayable:
    {
    NSLog(@“加载完成,可以播放”);
    }
    break;
    case MPMovieLoadStatePlaythroughOK:
    {
    NSLog(@“缓冲完成,可以连续播放”);
    }
    break;
    case MPMovieLoadStateStalled:
    {
    NSLog(@“缓冲中”);
    }
    break;
    case MPMovieLoadStateUnknown:
    {
    NSLog(@“未知状态”);
    }
    break;
    default:
    break;
    }
    }
    二、MPMoviePlayerViewController播放视频,但是iOS3.2之后不建议使用
    其实MPMoviePlayerViewController播放视频与MPMoviePlayerController播放一样,只是MPMoviePlayerViewController只能全屏播放视频
    并且MPMoviePlayerViewController包含MPMoviePlayerController属性

  • (instancetype)initWithContentURL:(NSURL *)contentURL NS_DESIGNATED_INITIALIZER;
    @property (nonatomic, readonly) MPMoviePlayerController *moviePlayer;
    并且弹出方式也是modal方式
    -(void)presentMoviePlayerViewControllerAnimated:(MPMoviePlayerViewController *)moviePlayerViewController
    -(void)dismissMoviePlayerViewControllerAnimated

3、AVPlayer播放视频当个视频(本文重点讲解)
由于播放器可能在以后我们经常会用到,所以我建议封装成工具类。
首先我们来看看AVPlayer播放器设置一些什么鬼?

@property (nonatomic, strong) AVPlayerItem *currentPlayerItem; //当前正在播放视频的Item
@property (nonatomic, strong) AVPlayer *player;
@property (nonatomic, strong) AVPlayerLayer *currentPlayerLayer; //当前图像层
AVPlayerItem:播放器的播放model,管理资源的对象,这个东东很重要,不仅可以可以获得到播放状态status,还可以看到缓冲进度loadedTimeRange、playbackBufferEmpty、playbackLikelyToKeepUp
等属性。
AVPlayer:播放器自身的播放工具类,可以播放play、暂停pause等
AVPlayerLayer:播放器播放的View,预览层,把这个View增加到播放页面显示区域,就可以看到播放的画面

第一步:
导入AVPlayer播放器框架

#import <AVFoundation/AVFoundation.h>
第二步
使用url初始化播放器AVPlayerItem、AVPlayer、AVPlayerLayer

//加载视频的方式
if([url.absoluteString hasPrefix:@“http”])
{
//网络加载数据
AVPlayerItem *playerItem=[AVPlayerItem playerItemWithURL:[NSURL URLWithString:[url.absoluteString stringByAddingPercentEscapesUsingEncoding:NSUTF8StringEncoding]]];
self.currentPlayerItem = playerItem;
}
else
{
//本地视频
self.currentPlayerItem = [AVPlayerItem playerItemWithURL:url];
}
self.player = [AVPlayer playerWithPlayerItem:self.currentPlayerItem];
self.currentPlayerLayer = [AVPlayerLayer playerLayerWithPlayer:self.player];
self.currentPlayerLayer.frame = CGRectMake(0, 0, superView.bounds.size.width, superView.bounds.size.height);
第三步
初始化完成,那么什么时候播放视频呢,查看AVPlayerItem的属性@property (nonatomic, readonly) AVPlayerItemStatus status;但是是只读的,如果我们想要知道播放器的状态,那么就利用KVO监听状态、同时监听播放器的缓冲进度playbackBufferEmpty、是否加载完成(注意监听者可以在初始化的时候就增加)playbackLikelyToKeepUp

#define LZBVideoPlayerStatus @“status”
#define LZBVideoPlayerPlaybackBufferEmpty @“playbackBufferEmpty”
#define LZBVideoPlayerStatusplaybackLikelyToKeepUp @“playbackLikelyToKeepUp”
//增加播放器播放监听

  • (void)addPlayerObserver
    {
    //播放状态监听
    [_currentPlayerItem addObserver:self forKeyPath:LZBVideoPlayerStatus options:NSKeyValueObservingOptionNew context:nil];
    [_currentPlayerItem addObserver:self forKeyPath:LZBVideoPlayerPlaybackBufferEmpty options:NSKeyValueObservingOptionNew context:nil];
    [_currentPlayerItem addObserver:self forKeyPath:LZBVideoPlayerStatusplaybackLikelyToKeepUp options:NSKeyValueObservingOptionNew context:nil];
    }
    //移除播放器播放监听
  • (void)removePlayerObserver
    {
    [_currentPlayerItem removeObserver:self forKeyPath:LZBVideoPlayerStatus];
    [_currentPlayerItem removeObserver:self forKeyPath:LZBVideoPlayerPlaybackBufferEmpty];
    [_currentPlayerItem removeObserver:self forKeyPath:LZBVideoPlayerStatusplaybackLikelyToKeepUp];
    }
    第四步
    监听播放器的状态
  • (void)observeValueForKeyPath:(NSString *)keyPath ofObject:(id)object change:(NSDictionary<NSKeyValueChangeKey,id> *)change context:(void *)context
    {
    if([keyPath isEqualToString:LZBVideoPlayerStatus])
    {
    [self processObserveValueStatusWithItem:(AVPlayerItem *)object];
    }
    else if ([keyPath isEqualToString:LZBVideoPlayerPlaybackBufferEmpty])
    {
    [self processObserveBuffering];
    }
    else if([keyPath isEqualToString:LZBVideoPlayerStatusplaybackLikelyToKeepUp])
    {
    [self processObserveBuffered];
    }
    }
    //监听status
  • (void)processObserveValueStatusWithItem:(AVPlayerItem *)playerItem
    {
    AVPlayerItemStatus status = playerItem.status;
    switch (status) {
    case AVPlayerItemStatusUnknown:{
    }
    break;
    //监听到准备播放
    case AVPlayerItemStatusReadyToPlay:{
    [self.player play]; //开始准备播放
    [self.showSuperView.layer insertSublayer:self.currentPlayerLayer atIndex:0]; //把预览层增加到父类显示区域
    }
    break;
    case AVPlayerItemStatusFailed:{
    }
    break;
    }
    }

第五步
监听什么时候缓冲完成。主要逻辑:监听是否正在缓冲processObserveBuffering,如果正在缓冲,那么调用bufferingForSeconds,暂停播放、等过了2s之后再去播放一次并且检查时候缓冲完成,如果缓冲完成就播放,如果没有就继续等2s,这样循环到缓存完成。(只是适合播放小视频)

//缓冲进度

  • (void)processObserveBuffering
    {
    if(self.currentPlayerItem.playbackBufferEmpty)
    {
    [self startLoadingViewInSuperView:self.showSuperView];
    self.isBuffering = YES;
    [self bufferingForSeconds];
    }
    }
    //缓冲完成
  • (void)processObserveBuffered
    {
    if (self.currentPlayerItem.playbackLikelyToKeepUp){
    [self stopLoading];
    [self startPlayerTimeProgress];
    self.coverImageView.hidden = YES;
    self.isBuffering = NO;
    }
    }
    -(void)bufferingForSeconds{
    if (self.isBuffering == NO) return;
    [self.player pause];
    dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(2 * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{
    [self.player play];
    if (!self.currentPlayerItem.isPlaybackLikelyToKeepUp) {
    [self bufferingForSeconds];
    }
    });
    }
    第六步
    在播放过程中还可以获取播放时长和已经播放的时间

float totalDuration = CMTimeGetSeconds(self.currentPlayerItem.duration);
float currentTime = CMTimeGetSeconds(self.currentPlayerItem.currentTime);
NSInteger residueTime =(NSInteger)(totalDuration - currentTime);
第七步
播放过程中还要考虑,app的状态,并且监听内存等

//增加app运行状态监听
-(void)addObserverOnce{
if (!self.isAddObserver) {
// 添加监听,只能增加一次
[[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(appDidEnterBackground) name:UIApplicationWillResignActiveNotification object:nil];
[[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(appDidEnterPlayGround) name:UIApplicationDidBecomeActiveNotification object:nil];
[[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(playerItemDidPlayToEnd:) name:AVPlayerItemDidPlayToEndTimeNotification object:nil];
[[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(receiveMemoryWarning) name:UIApplicationDidReceiveMemoryWarningNotification object:nil];
}
self.isAddObserver = YES;
}
小细节:本文demo中还增加了视频加载过程的默认默认背景图等。
AVPlayer播放多个视频留到下一篇文章,未完待续。。。。
下一站
AVPlayer播放多个小视频切换

详情代码请直接下载demo查看:
项目下载地址:三种视频播放器大总结

作者:weixin_34288121
原文:https://blog.csdn.net/weixin_34288121/article/details/86856634

【播放器】播放器对比相关推荐

  1. react项目中使用阿里播放器播放视频,包括切换视频,播放定时跳转(兼容ios和andro),播放完成

    react项目中使用阿里播放器播放视频,包括切换视频,播放定时跳转(兼容ios和andro),播放完成 1.index.html引入阿里播放器的cdn <link rel="style ...

  2. android+省电播放器,播放耗电:QQ影音等三款最省电_软件资讯软件评测-中关村在线...

    参测软件播放耗电情况 使用PC电脑(使用电源)平台来播放视频时,由于电力来自于电源,因此在电量的消耗方面,在普通的使用中,并不会被考虑太多. 然而安卓手机端在播放视频时,播放视频过程中的耗电情况,我们 ...

  3. Android开源音乐播放器之播放器基本功能

    系列文章 Android开源在线音乐播放器--波尼音乐 Android开源音乐播放器之播放器基本功能 Android开源音乐播放器之高仿云音乐黑胶唱片 Android开源音乐播放器之自动滚动歌词 An ...

  4. Android多媒体学习五:调用Android自带的播放器播放Audio

    Android有其自带的播放器,我们可以使用隐式Intent来调用它:通过传入一个Action为ACTION_VIEW同时,指定Data为所要播放的Audio的Uri对象,并指定格式信息,则我们就可以 ...

  5. 与众不同 windows phone (14) - Media(媒体)之音频播放器, 视频播放器, 与 Windows Phone 的音乐和视频中心集成...

    原文:与众不同 windows phone (14) - Media(媒体)之音频播放器, 视频播放器, 与 Windows Phone 的音乐和视频中心集成 [索引页] [源码下载] 与众不同 wi ...

  6. 使用 阿里云 播放器播放 .flv 和 hls(.m3u8) 格式的视频流

    一.使用 阿里云 播放器播放 .flv 和 hls(.m3u8) 格式的视频流 官方教程:https://help.aliyun.com/document_detail/125570.htm?spm= ...

  7. html选择本地文件视频并播放器,使HTML5视频播放器播放不同的文件(Make a HTML5 video player play a different file)...

    使HTML5视频播放器播放不同的文件(Make a HTML5 video player play a different file) 在播放视频时,我无法让HTML5播放器播放不同的视频,我尝试更改 ...

  8. Ubuntu安装播放器 或 Linux上比较好用强大、并且可以倍速播放的播放器SMplayer

    Ubuntu16.04安装播放器 或 Linux上比较好用强大.并且可以倍速播放的播放器SMplayer 文章目录: 1 SMplayer 1.1 SMplayer 播放器 1.2 SMplayer在 ...

  9. php 音频顺序播放,MP3播放器音频文件不按顺序播放的解决方法,简单实用

    MP3播放器对于现在的我们来说很多已经是过去了,但是我们总会有用到它的时候:当你听一些录音课程或者评书故事,亦或者使用迷你音响播放歌曲时常会发现拷贝进MP3播放器中的音频文件根本不按照你自己的想象进行 ...

  10. android集成EasyPlayer播放器播放实时流媒体视屏

    android集成EasyPlayer播放器播放实时流媒体视屏 最近公司项目需要实现一个rtsp实时流媒体视频的播放,在移动端尝试了多个第三方能播放rtsp流实时视频的软件后发现EasyPlayer的 ...

最新文章

  1. oracle中 怎么替换,oracle如何替换字符串?
  2. python划分代码_多分类评价指标python代码
  3. 高效学习,战胜拖延症
  4. rsync+inotify实现服务器之间文件实时同步
  5. 三维坐标系带偏航角俯仰角_浅谈三维旋转的三种方法及差异
  6. 欧菲光修正2020年业绩为预计亏损18.5亿元
  7. 学习node.js的一些笔记
  8. [转载] Java并发编程:Callable、Future和FutureTask
  9. 勘测定界界址点坐标交换格式的读写
  10. cmake出错:Building inplace are not allowed. You should create a separate directory for Building.
  11. R3live笔记:从代码看lio线程
  12. (六)springMvc 和 mybatis 整合
  13. 计算机技术辅助笔迹鉴定,GB∕T 37239-2018 笔迹鉴定技术规范(高清版).pdf
  14. OkHttp请求json数据
  15. Java学习-数据操作高级篇
  16. 国家对应下拉列表 相应的 js特效
  17. ubuntu 下myeclipse下载,安装,破解
  18. 【源码】电压控制DC/DC双向变换器仿真
  19. 苹果手机怎么把中文翻译英文
  20. java神秘岛_Minecraft1.4.2MOD整合版

热门文章

  1. day01 -Web API介绍—DOM 介绍—获取元素—事件基础—操作元素—排他操作—自定义属性操作—节点操作—案例:动态生成表格—创建元素的三种方式(经典面试题)
  2. 老李分享:《Java Performance》笔记2——JVM命令行选项及垃圾收集日志解析 2
  3. 完美解决织梦CMS加入lian666自动友情链接代码正常显示
  4. 虚拟化高级应用、Win快捷键操作 、 Win+R快速调用
  5. 分子动力学(一)-定义与理解
  6. codeforces 760B B. Frodo and pillows(二分)
  7. Window环境下MQTT安装
  8. CDN中加速域名和源站地址和回源HOST是什么,应该怎么填
  9. Ubuntu安装输入法却不能切换输入法
  10. 为什么越来越多的企业这么重视AAA企业信用等级认证?