AVFoundation – AVPlayerItem 管理资源对象

零基础 Object-C 学习路线推荐 : Object-C 学习目录 >> Object-C 基础

零基础 Object-C 学习路线推荐 : Object-C 学习目录 >> Object-C 线程

零基础 Object-C 学习路线推荐 : Object-C 学习目录 >> OpenGL ES

零基础 Object-C 学习路线推荐 : Object-C 学习目录 >> GPUImage

零基础 Object-C 学习路线推荐 : Object-C 学习目录 >> AVFoundation

零基础 Object-C 学习路线推荐 : Object-C 学习目录 >> CocoaPods


一.前言

1.AVAsset

Assets 可以来自一个文件或用户的相册,可以理解为多媒体资源,通过 URL 作为一个 asset 对象的标识. 这个 URL 可以是本地文件路径或网络流;


2.AVAssetTrack

AVAsset 包含很多轨道 AVAssetTrack 的结合,如 audio, video, text, closed captions, subtitles…


3.AVComposition / AVMutableComposition

使用 AVMutableComposition 类可以增删 AVAsset 来将单个或者多个 AVAsset 集合到一起,用来合成新视频。除此之外,若想将集合到一起的视听资源以自定义的方式进行播放,需要使用 AVMutableAudioMix 和 AVMutableVideoComposition 类对其中的资源进行协调管理;


4.AVMutableVideoComposition

AVFoundation 类 API 中最核心的类是 AVVideoComposition / AVMutableVideoComposition 。

AVVideoComposition / AVMutableVideoComposition 对两个或多个视频轨道组合在一起的方法给出了一个总体描述。它由一组时间范围和描述组合行为的介绍内容组成。这些信息出现在组合资源内的任意时间点。

AVVideoComposition / AVMutableVideoComposition 管理所有视频轨道,可以决定最终视频的尺寸,裁剪需要在这里进行;


5.AVMutableCompositionTrack

多个 AVAsset 集合到一起合成新视频中轨道信息,有音频轨、视频轨等,里面可以插入各种对应的素材(画中画,水印等);


6.AVMutableVideoCompositionLayerInstruction

AVMutableVideoCompositionLayerInstruction 主要用于对视频轨道中的一个视频处理缩放、模糊、裁剪、旋转等;


7.AVMutableVideoCompositionInstruction

表示一个指令,决定一个 timeRange 内每个轨道的状态,每一个指令包含多个 AVMutableVideoCompositionLayerInstruction ;而 AVVideoComposition 由多个 AVVideoCompositionInstruction 构成;

AVVideoCompositionInstruction 所提供的最关键的一段数据是组合对象时间轴内的时间范围信息。这一时间范围是在某一组合形式出现时的时间范围。要执行的组全特质是通过其 AVMutableVideoCompositionLayerInstruction 集合定义的。


8.AVAssetExportSession

AVAssetExportSession 主要用于导出视频;


二.AVPlayer 简介

首先在 iOS 平台使用播放视频,可用的选项一般有这四个,他们各自的作用和功能如下: 

AVFoundation – AVPlayerItem 管理资源对象

由此可以看出,如果我们不做直播功能 AVPlayer 就是一个最优的选择。在创建一个播放器之前我们需要先了解一些播放器相关的类


1.AVPlayer

AVPlayer 控制播放器的播放,暂停,播放速度;

/*创建AVPlayer播放器*/
+ (instancetype)playerWithURL:(NSURL *)URL;
+ (instancetype)playerWithPlayerItem:(nullable AVPlayerItem *)item;
- (instancetype)initWithURL:(NSURL *)URL;
- (instancetype)initWithPlayerItem:(nullable AVPlayerItem *)item;

/*当前播放器播放的时间*/
- (CMTime)currentTime;

/*播放速度
    rate = 0.5;   // 慢放
    rate = 1.0;   // 正常播放
    rate = 0.0;   // 暂停
    rate = -0.5;  // 倒放
 */
@property (nonatomic) float rate;

/*播放 默认 rate = 1.0*/
- (void)play;

/*暂停播放 rate = 0.0*/
- (void)pause;

注意更改播放速度要在视频开始播放之后才会生效;


2.AVURLAsset

前面文章有对 AVAsset 介绍,AVURLAsset 是 AVAsset 的一个子类,使用 URL 进行实例化,实例化对象包换 URL 对应视频资源的所有信息;

NSURL *url = <#A URL that identifies an audiovisual asset such as a movie file#>;
AVURLAsset *anAsset = [[AVURLAsset alloc] initWithURL:url options:nil];

注意 NSURL 的使用:

[NSURL URLWithString:@"网络路径"]
[NSURL fileURLWithPath:@"本地路径"]
如果读取的是本地文件,那么请用第二个方法,第一个会出错,读取不到URL.

3.AVPlayerItem

AVPlayerItem 管理资源对象,提供播放数据源;


4.AVPlayerLayer

AVPlayerLayer 负责显示视频,如果没有添加该类,只有声音没有画面;


三.获取 AVPlayerItem 播放状态

AVPlayerItem 作为资源管理对象,它控制着视频从创建到销毁的诸多状态。

//播放状态 status

typedef NS_ENUM(NSInteger,AVPlayerItemStatus) {

    AVPlayerItemStatusUnknown,      //未知
    AVPlayerItemStatusReadyToPlay,  //准备播放
    AVPlayerItemStatusFailed        //播放失败

};


在上一篇文章 《AVPlayer播放视频》最后提示:

AVPlayer 创建后,播放并不是可以直接使用,还要对它的状态进行检查,只有 AVPlayerItem.status 的值为 AVPlayerStatusReadyToPlay 时,才能进行播放,所以这里需要使用 KVO 模式对该状态进行监控,以决定何时可以进行播放;


示例代码如下:

/******************************************************************************************/
//@Author:猿说编程
//@Blog(个人博客地址): www.codersrc.com
//@File:AVFoundation - AVPlayerItem 管理资源对象
//@Time:2021/08/04 07:30
//@Motto:不积跬步无以至千里,不积小流无以成江海,程序人生的精彩需要坚持不懈地积累!
/******************************************************************************************/

#import "ViewController.h"
#import <AVFoundation/AVFoundation.h>

@interface ViewController ()
{
    AVPlayerItem* _item ;         //用于加载媒体
    AVPlayer* _player;            //控制播放器的播放,暂停,播放速度
    AVPlayerLayer* _playerLayer;  //用于显示画面
}


@end

@implementation ViewController

- (void)viewDidLoad
{
    [super viewDidLoad];
//    self.view.backgroundColor = [UIColor redColor];
    
    //创建一个资源实例
    NSURL* url = [NSURL fileURLWithPath:[[NSBundle mainBundle] pathForResource:@"123.mp4" ofType:nil]];
    AVURLAsset* asset = [[AVURLAsset alloc] initWithURL:url options:nil];
    
    //AVPlayerItem关联播放资源
    _item = [[AVPlayerItem alloc] initWithAsset:asset];
    
    //添加观察者,对该状态进行监控,以决定何时可以进行播放
    [_item addObserver:self forKeyPath:@"status" options:NSKeyValueObservingOptionNew context:nil];
    
    //创建AVPlayer
    _player = [AVPlayer playerWithPlayerItem:_item];
   
    
    //创建AVPlayerLayer用来显示资源内容
    _playerLayer = [AVPlayerLayer playerLayerWithPlayer:_player];
    //设置frame
    _playerLayer.frame = self.view.frame;
    //添加到当前的view,否则无法显示
    [self.view.layer addSublayer:_playerLayer];
    
}

- (void)observeValueForKeyPath:(NSString *)keyPath ofObject:(id)object change:(NSDictionary<NSKeyValueChangeKey,id> *)change context:(void *)context {
    if ([object isKindOfClass:[AVPlayerItem class]]) {
        if([keyPath isEqualToString:@"status"])
        {
            switch(_item.status)
            {
                case AVPlayerItemStatusReadyToPlay:
                    [_player play];
                    NSLog(@"AVPlayerItemStatusReadyToPlay");
                    break;
                case AVPlayerItemStatusUnknown:
                    NSLog(@"AVPlayerItemStatusUnknown");
                    break;
                case AVPlayerItemStatusFailed:
                    NSLog(@"AVPlayerItemStatusFailed");
                    break;

                default:break;
            }
        }
    }
}
- (void)dealloc
{
    //删除观察者
    [self removeObserver:self forKeyPath:@"status"];
}

@end


四.时间监听


1.定期监听

//@interface AVPlayer (AVPlayerTimeObservation)

/*
* 函数描述:以一定的时间间隔获得通知,比如需要随着时间的变化移动播放头位置或更新时间显示;

* 函数参数:
*
*   interval:指定通知周期间隔的CMTime值(例如:间隔1秒通知播放器滑块刷新);
*   queue:默认为主队列。不可以使用并行调度队列,API没有处理并行队列的方法;
*   block:一个在指定的时间间隔中就会在队列上调用的回调块。这个块传递一个CMTime值用于指示播放器的当前时间;
*
*/
- (id)addPeriodicTimeObserverForInterval:(CMTime)interval queue:(nullable dispatch_queue_t)queue usingBlock:(void (^)(CMTime time))block;


2.边界时间监听


//@interface AVPlayer (AVPlayerTimeObservation)

/*
* 函数描述:监听时间,可以得到播放器时间轴中多个边界点的遍历结果,比如可以定义 25%、50% 边界的标记,当播放器的播放到 25% 或者 50%会触发 block 回调;

* 函数参数:
*
*   times:CMTime 值组成的一个 NSArray 数组定义了需要通知的边界点;
*   queue:与定期监听类似,为方法提供一个用来发送通知的顺序调度队列。指定NULL等同于明确设置主队列;
*   block:每当正常播放中跨域一个边界点时就会在队列中回调方法块,不提供遍历的CMTime值,需要为此执行一些额外计算进行确定;
*
*/

- (id)addBoundaryTimeObserverForTimes:(NSArray<NSValue *> *)times queue:(nullable dispatch_queue_t)queue usingBlock:(void (^)(void))block;

3.播放结束通知

播放完成时,AVPlayerItem 会发送 AVPlayerItemDidPlayToEndTimeNotification 通知 。注册成为监听器,即获得播放器结束通知。


4.完整代码

此处内容需要购买后查看,黄金会员可免费查看

支付19.9元查看


五.播放相关通知

播放相关通知

1、声音类

//声音被打断的通知(电话打来)
AVAudioSessionInterruptionNotification

//耳机插入和拔出的通知
AVAudioSessionRouteChangeNotification



2、播放类

//播放完成
AVPlayerItemDidPlayToEndTimeNotification

//播放失败
AVPlayerItemFailedToPlayToEndTimeNotification

//异常中断
AVPlayerItemPlaybackStalledNotification



3、系统状态

//进入后台
UIApplicationWillResignActiveNotification

//返回前台
UIApplicationDidBecomeActiveNotification


对于播放完成的通知我们可以这么写:

[[NSNotificationCenterdefaultCenter] addObserver:self selector:@selector(playerMovieFinish:) name:AVPlayerItemDidPlayToEndTimeNotificationobject:[self.player currentItem]];

提示:所有通知和 KVO 的使用我们都要记得在不用时 remove 掉。


六.猜你喜欢


未经允许不得转载:猿说编程 » AVFoundation – AVPlayerItem 管理资源对象
喜欢(2) 打赏

评论抢沙发

评论前必须登录!

不积跬步无以至千里,不积小流无以成江海,程序人生的精彩需要坚持不懈地积累!!

开始学习

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

微信扫一扫打赏