iOS AVPlayer和AVPlayerViewController

1. AVPlayer

AVPlayer是iOS常见的播放器,使用时需导入

#import <AVKit/AVKit.h>

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

// 初始化
+ (instancetype)playerWithURL:(NSURL *)URL;
+ (instancetype)playerWithPlayerItem:(nullable AVPlayerItem *)item;
- (instancetype)initWithURL:(NSURL *)URL;
- (instancetype)initWithPlayerItem:(nullable AVPlayerItem *)item;

// 常用属性
@property (nonatomic, readonly) AVPlayerStatus status; // 播放媒体状态
@property (nonatomic) float rate; // 播放速度, 在视频开始播放之后才会生效

// 常用方法
- (void)play; // 播放
- (void)pause; // 暂停
// 添加周期时间观察者
- (id)addPeriodicTimeObserverForInterval:(CMTime)interval queue:(nullable dispatch_queue_t)queue
		 usingBlock:(void (^)(CMTime time))block;

单纯使用AVPlayer类是无法显示视频的,要将视频层添加至AVPlayerLayer中,这样才能将视频显示出来

// 初始化
+ (AVPlayerLayer *)playerLayerWithPlayer:(nullable AVPlayer *)player;

// 常用属性
@property (nonatomic, retain, nullable) AVPlayer *player; 
// AVLayerVideoGravityResize, 非均匀模式。两个维度完全填充至整个视图区域
// AVLayerVideoGravityResizeAspect, 等比例填充,直到一个维度到达区域边界
// AVLayerVideoGravityResizeAspectFill, 等比例填充,直到填充满整个视图区域,其中一个维度的部分区域会被裁剪
@property(copy) AVLayerVideoGravity videoGravity;

播放视频

self.player = [[AVPlayer alloc] initWithURL:[NSURL URLWithString:@"http://xxx.mp4"]];
AVPlayerLayer *playerLayer = [AVPlayerLayer playerLayerWithPlayer:self.player];
playerLayer.videoGravity = AVLayerVideoGravityResizeAspect;

playerLayer.frame = self.playerView.bounds;
[self.playerView.layer addSublayer:playerLayer];

2. AVPlayerItem

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

// 初始化
+ (instancetype)playerItemWithURL:(NSURL *)URL;
+ (instancetype)playerItemWithAsset:(AVAsset *)asset;

- (instancetype)initWithURL:(NSURL *)URL;
- (instancetype)initWithAsset:(AVAsset *)asset;

// 常见属性
@property (readonly) AVPlayerItemStatus status; // 播放状态
@property (nonatomic, readonly) AVAsset *asset;
@property (readonly) CMTime duration; // 总时间
@property (readonly) NSArray<NSValue *> *loadedTimeRanges;  // 缓存时间

// 主要方法
- (CMTime)currentTime; // 当前时间

结构体CMTime是以分数的形式表示时间,value表示分子,timescale表示分母,flags是位掩码,表示时间的指定状态。

typedef struct
{
	CMTimeValue	value; // 帧数
	CMTimeScale	timescale; // 帧率(影片每秒有几帧)
	CMTimeFlags	flags;
	CMTimeEpoch	epoch;
} CMTime;

获取当前播放时间

float currentTime = self.playItem.currentTime.value/self.playItem.currentTime.timescale;

还有一种利用系统提供的方法,我们用它获取视频总时间:

float totalTime = CMTimeGetSeconds(self.playItem.duration);

使用KVO监测AVPlayerItem,获取播放状态的变化

- (void)viewDidLoad {
    __weak __typeof(self)weakSelf = self;
    [self.player addPeriodicTimeObserverForInterval:CMTimeMake(1, 1) queue:nil usingBlock:^(CMTime time) {
        NSLog(@"%lld/%.2f", weakSelf.playerItem.currentTime.value/weakSelf.playerItem.currentTime.timescale,
              CMTimeGetSeconds(weakSelf.playerItem.duration));
    }];
    
    [self.playerItem addObserver:self forKeyPath:@"status" options:NSKeyValueObservingOptionNew context:nil];
    [self.playerItem addObserver:self forKeyPath:@"loadedTimeRanges" options:NSKeyValueObservingOptionNew context:nil];
}

- (void)dealloc {
    [self.playerItem removeObserver:self forKeyPath:@"status"];
    [self.playerItem removeObserver:self forKeyPath:@"loadedTimeRanges"];
}

- (void)observeValueForKeyPath:(NSString *)keyPath ofObject:(id)object change:(NSDictionary *)change context:(void *)context {
    if ([keyPath isEqualToString:@"status"]) {
        switch (self.playerItem.status) {
            case AVPlayerItemStatusReadyToPlay:
                NSLog(@"AVPlayerItemStatusReadyToPlay");
                break;
            case AVPlayerItemStatusUnknown:
                NSLog(@"AVPlayerItemStatusUnknown");
                break;
            case AVPlayerItemStatusFailed:
                NSLog(@"AVPlayerItemStatusFailed");
                break;
        }
    } else if ([keyPath isEqualToString:@"loadedTimeRanges"]) {
        NSArray<NSValue *> *array = _playerItem.loadedTimeRanges;

        //本次缓冲时间范围
        CMTimeRange timeRange = [array.firstObject CMTimeRangeValue];
        float startSeconds = CMTimeGetSeconds(timeRange.start);
        float durationSeconds = CMTimeGetSeconds(timeRange.duration);
        NSTimeInterval totalBuffer = startSeconds + durationSeconds;//缓冲总长度
        NSLog(@"当前缓冲时间:%f",totalBuffer);
    } else {
        [super observeValueForKeyPath:keyPath ofObject:object change:change context:context];
    }
}

3. AVPlayerViewController

AVPlayerViewController整合了一个完整的播放器,可以作为控制器进行操作显示。

// 主要属性
@property (nonatomic, strong, nullable) AVPlayer *player;
@property (nonatomic) BOOL showsPlaybackControls; // 是否显示媒体播放组件
@property (nonatomic, copy) AVLayerVideoGravity videoGravity; // 拉伸模式

AVPlayerViewController可以全屏播放,也可以在UIView里播放

// 全屏播放
- (void)onFullScreenPlayClick:(UIButton *)sender {
    AVPlayerViewController *playerViewController = [[AVPlayerViewController alloc] init];
    playerViewController.player = self.player;
    [self presentViewController:playerViewController animated:YES completion:nil];

    [self.player play];
}

// 在UIView里播放
- (void)onViewPlayClick:(UIButton *)sender {
    AVPlayerViewController *playerViewController = [[AVPlayerViewController alloc] init];
    playerViewController.player = self.player;
    playerViewController.view.frame = self.playerView.bounds;
    [self.playerView addSubview:playerViewController.view];
    
    [self.player play];
}
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
iOS AVPlayer 是苹果官方提供的一个强大的音视频播放器框架。AVPlayer 提供了丰富的功能和接口,可以用来播放各种不同格式的音视频文件。 iOS AVPlayer 播放器的 UI 取决于个人的设计需求和实现方式。一般情况下,可以通过 AVPlayerLayer 来显示视频画面,并在其上添加一些自定义的控件来实现播放器的 UI。 可以使用 AVPlayerLayer 来创建一个视图层用于显示视频,然后将其添加到你的视图层级中。你可以设置 AVPlayerLayer 的 frame 属性来确定视频画面的位置和大小。 除了视频画面的显示,你还可以添加一些控件来实现播放器的控制功能。比如可以添加一个播放/暂停按钮、一个进度条显示当前播放的进度、一个音量调节控件等等。这些控件可以通过与 AVPlayer 进行交互来实现不同功能。 在实现过程中,你可以利用 AVPlayer 的一些相关属性和方法来控制播放器的状态。比如可以使用 play() 方法来播放视频,pause() 方法来暂停视频的播放,并且可以通过 KVO(键值观察)机制来监听播放器的状态变化,以及通过观察 AVPlayerItem 的属性来获取视频的总时长等信息。 另外,你还可以根据需要进行一些自定义的 UI 设计来美化播放器的外观,比如更改按钮的样式、调整进度条的颜色等等,以增强用户体验。 综上所述,iOS AVPlayer 播放器的 UI 取决于你个人的设计需求和实现方式,可以通过 AVPlayerLayer 实现视频画面的显示,通过添加自定义控件来实现播放器的控制功能,并根据需要进行一些自定义的 UI 设计。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值