AVPlayer视频播放

2023-11-14

AVFoundation中的元数据

Apple环境下的媒体类型主要有四种:

  • QuickTime(mov)
  • MPEG-4 video(mp4和m4v)
  • MPEG-4 audio(m4a)
  • MPEG-Layer III audio(mp3)

使用元数据

大部分使用AVAsset提供元数据,但是当涉及获取曲目一级元数据等情况时也会使用AVAssetTrack

获取资源中包含的所有元数据

NSURL *url = [NSURL URLWithString:@"url"];
AVAsset *asset = [AVAsset assetWithURL:url];
//需要加载的属性数组
NSArray *keys = @[@"availableMetadataFormats"];
//异步加载属性
[asset loadValuesAsynchronouslyForKeys:keys completionHandler:^{
    //获取属性的加载状态
AVKeyValueStatus status = [asset statusOfValueForKey:@"availableMetadataFormats"error:nil];
    if(status == AVKeyValueStatusLoaded){
        //将资源的元数据放入数组
        NSMutableArray *metadata = [NSMutableArray array];
        for(NSString *format in asset.availableMetadataFormats){
            [metadata addObject:format];
        }
    }
}];

筛选元数据

NSArray *metadata = @[];//AVMetadataItems
//常用的键空间
//AVMetadataFormatQuickTimeMetadata,
//AVMetadataFormatiTunesMetadata,
//AVMetadataFormatID3Metadata
NSString *keySpace = AVMetadataKeySpaceiTunes;
NSString *artisKey = AVMetadataiTunesMetadataKeyArtist;
NSString *albumKey = AVMetadataiTunesMetadataKeyAlbum;
//筛选获取演唱者的元数据
NSArray *artisMetadata = [AVMetadataItem metadataItemsFromArray:metadata withKey:artisKey keySpace:keySpace];
//获取唱片的元数据
NSArray *albumMetadata = [AVMetadataItem metadataItemsFromArray:metadata withKey:albumKey keySpace:keySpace];

AVMetadataItem *artisItem,*albumItem;
if(artisMetadata.count > 0){
    artisItem = artisMetadata[0];
}
if(albumMetadata.count > 0){
    albumItem = albumMetadata[0];
}

1.AVPlayer

AVPlayer可以支持播放本地、分布下载或通过HTTP Live Streaming协议得到的流媒体

注: AVPlayer只管理单独资源的播放,AVQueuePlayer可以管理一个资源队列

创建对象

//两个类方法创建
+ (instancetype)playerWithURL:(NSURL *)URL;
+ (instancetype)playerWithPlayerItem:(AVPlayerItem *)item;
//两个实例方法
- (instancetype)initWithURL:(NSURL *)URL;
- (instancetype)initWithPlayerItem:(AVPlayerItem *)item;

属性

//状态
@property (nonatomic, readonly) AVPlayerStatus status;
//AVPlayerStatusUnknown,
//AVPlayerStatusReadyToPlay
//AVPlayerStatusFailed

statusAVPlayerStatusFailedAVPlayer将不能播放,才是需要重新创建对象

拓展AVPlayerPlaybackControl

//当前播放速度,值为0.0时停止播放,值为1.0时为正常播放速度
@property (nonatomic) float rate;
//播放和暂停的方法
- (void)play;
- (void)pause;

拓展AVPlayerItemControl

//当前播放的项目
@property (nonatomic, readonly, nullable) AVPlayerItem *currentItem;
//替换当前播放的项目,可以用于切换视频或音频,当需要替换的item和currentItem为同一个时不做任何操作,音视频据需播放,没有任何影响
- (void)replaceCurrentItemWithPlayerItem:(nullable AVPlayerItem *)item;

//当播放完毕时的操作
@property (nonatomic) AVPlayerActionAtItemEnd actionAtItemEnd;
//AVPlayerActionAtItemEndAdvance 该属性只有AVQueuePlayer才可以用,表示继续播放下一个项目
//AVPlayerActionAtItemEndPause  播放完毕后暂停
//AVPlayerActionAtItemEndNone   不错任何处理

拓展AVPlayerTimeControl

//当前的播放时间
- (CMTime)currentTime;
//播放到指定时间位置
- (void)seekToDate:(NSDate *)date;
- (void)seekToDate:(NSDate *)date completionHandler:(void (^)(BOOL finished))completionHandler
- (void)seekToTime:(CMTime)time;
//直接播放到一个时间的范围
- (void)seekToTime:(CMTime)time toleranceBefore:(CMTime)toleranceBefore toleranceAfter:(CMTime)toleranceAfter;

拓展AVPlayerMediaControl

//当前播放的声音,如果想做媒体播放声音的进度条不要用这个,可以使用MPVolumeView,这个只是控制当前item播放音量而不是所有的item音量
@property (nonatomic) float volume

2.AVPlayerLayer

//需要一个AVPlayer对象做参数获取一个AVPlayerLayer实例
//AVPlayerLayer负责展示画面,AVPlayer负责链接资源
+ (AVPlayerLayer *)playerLayerWithPlayer:(nullable AVPlayer *)player
@property (nonatomic, retain, nullable) AVPlayer *player

//播放画面的缩放比例,和iamgeview的contentmode差不多
//AVLayerVideoGravityResizeAspect  默认值
//AVLayerVideoGravityResizeAspectFill
//AVLayerVideoGravityResize
@property(copy) NSString *videoGravity

//当前视频图像的大小位置
@property (nonatomic, readonly) CGRect videoRect

3.CMTime

//CMTime的定义
typedef struct
{
  CMTimeValue   value;          分子
  CMTimeScale   timescale;      分母
  CMTimeFlags   flags;
  CMTimeEpoch   epoch;
} CMTime;

//0.5秒
CMTime halfSecond = CMTimeMake(1, 2);
//5秒
CMTime fiveSecond = CMTimeMake(5, 1);
//44.1kHZ
CMTime oneSample = CMTimeMake(1, 44100);

4.播放视频

//根据url获得视频资源
_asset = [AVAsset assetWithURL:url];
//需要加载的属性数组
NSArray *keys = @[@"tracks",
                  @"duration",
                  @"commonMetadata",
       @"availableMediaCharacteristicsWithMediaSelectionOptions"];
//这种初始化方法可以同时加载属性    
_playerItem = [AVPlayerItem playerItemWithAsset:_asset automaticallyLoadedAssetKeys:keys];
//AVPlayerItem对象初始化AVPlayer
_player = [AVPlayer playerWithPlayerItem:_playerItem];
//为AVPlayerLayer设置AVPlayer
[(AVPlayerLayer *)self.layer setPlayer:_player];
//监听AVPlayerItem的播放状态
[_playerItem addObserver:self forKeyPath:@"status" options:0 context:&PlayerStatus];

监听方法

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

    if(context == &PlayerStatus){
      //因为不知道在哪个线程,所以指定组线程执行
        dispatch_async(dispatch_get_main_queue(), ^{
            if(_playerItem.status == AVPlayerStatusReadyToPlay){
              //移除监听状态
              [self.playerItem removeObserver:self forKeyPath:@"status"];
            //1.获取标题
            //2.获取播放时间,设置进度条
            //3.添加播放时间的监听
            //4.监听播放结束事件 
            //播放
              [_player play];
            }
        });
    }
}

设置标题

//首先获取commonMetadata属性的加载状态
AVKeyValueStatus status = [_asset statusOfValueForKey:@"commonMetadata" error:nil];
    if(status == AVKeyValueStatusLoaded){
        //获取标题项数据
        NSArray *items = [AVMetadataItem metadataItemsFromArray:_asset.commonMetadata withKey:AVMetadataCommonKeyTitle keySpace:AVMetadataKeySpaceCommon];
        if(items.count > 0){
            AVMetadataItem *titleItem = items[0];
            self.titleLabel.text = titleItem.stringValue;
        }else{
            self.titleLabel.text = @"";
        }
    }

获取播放总时间

CMTime duration = _playerItem.duration;
fload durationTime = CMTimeGetSeconds(duration);

添加播放时间的监听

CMTime interval = CMTimeMakeWithSeconds(1, 2);
__block typeof(self) weakSelf = self;
//这个返回的对象要强引用
self.timeObserver = [self.player addPeriodicTimeObserverForInterval:interval queue:dispatch_get_main_queue() usingBlock:^(CMTime time) {

    [weakSelf setSliderWithCurrentTime:CMTimeGetSeconds(time) durationTime:CMTimeGetSeconds(weakSelf.playerItem.duration)];
}];

播放结束通知

//注意强引用
self.playEndObserver = [[NSNotificationCenter defaultCenter] addObserverForName:AVPlayerItemDidPlayToEndTimeNotification object:self.playerItem queue:[NSOperationQueue mainQueue] usingBlock:^(NSNotification * _Nonnull note) {

}];

拖动进度条

- (void)beginSlider {
  //可以存储播放速度
  //停止播放然后移除播放时间监听
  [self.player pause];
  [self.player removeTimeObserver:self.timeObserver];
}

- (void)progressSlider {
  //取消上一次的查找
  [self.playerItem cancelPendingSeeks];
  //移动到播放对应时间
  [self.player seekToTime:CMTimeMakeWithSeconds(self.slider.value, 1) toleranceBefore:kCMTimeZero toleranceAfter:kCMTimeZero];
}

- (void)endSlider {
  //存储拖动前的播放速度前提下,可以根据播放速度进一步进行处理
  //添加播放时间监听
  [self addTimeObserver];
  [self.player play];
}

获取对应时间的图像

//需要强引用对象
self.imageGenerator = [AVAssetImageGenerator assetImageGeneratorWithAsset:_asset];
//指定获取图片的大小,图片会根据宽度自动调整高度
self.imageGenerator.maximumSize = CGSizeMake(200, 0);

CMTime durationTime = _asset.duration;
//存储需要获取图片的时间点
NSMutableArray *times = [NSMutableArray array];
//将影片时间分为20个点
CMTimeValue increment = durationTime.value/20;
CMTimeValue currentValue = kCMTimeZero.value;
while (currentValue <= durationTime.value) {
    CMTime currentTime = CMTimeMake(currentValue, durationTime.timescale);
    [times addObject:[NSValue valueWithCMTime:currentTime]];
    currentValue += increment;
}
//请求图片
[self.imageGenerator generateCGImagesAsynchronouslyForTimes:times completionHandler:^(CMTime requestedTime, CGImageRef  _Nullable image, CMTime actualTime, AVAssetImageGeneratorResult result, NSError * _Nullable error) {

    if(result == AVAssetImageGeneratorSucceeded){
        //主线线程处理
    }
}];

显示字幕

//加载字幕或者语音需要先加载资源的availableMediaCharacteristicsWithMediaSelectionOptions属性
AVMediaSelectionGroup *group = [self.asset mediaSelectionGroupForMediaCharacteristic:AVMediaCharacteristicLegible];
//获取和本地一样的语言字幕
NSArray *options = [AVMediaSelectionGroup mediaSelectionOptionsFromArray:group.options withLocale:[NSLocale currentLocale]];
[_playerItem selectMediaOption:options[0] inMediaSelectionGroup:group];
//遍历循环查找英文字幕
for(AVMediaSelectionOption *option in group.options){
    if([option.displayName isEqualToString:@"English"]){
        [_playerItem selectMediaOption:option inMediaSelectionGroup:group];
    }
}
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

AVPlayer视频播放 的相关文章

  • 如何在 iPhone 上缩小 UIPickerView?

    我想降低一个高度UIPickerView在我的 iPhone 应用程序中 使其仅显示一行和一列 选择器视图的高度应等于行的高度 我正在使用 Interface Builder 来构建UIPickerView 但我找不到调整此控件大小的简单方
  • IOS - 如何创建具有模糊背景的 Facebook 反应栏?

    虽然这周可能不会复制 Facebook 的某些设计 但我希望能够设计我自己的下面的反应指示器视图版本 我有三个UIImageViews 排列在与上面相同的位置 问题是 与 Facebook 不同 背景颜色可能会改变 即位于UIBlurEff
  • 高度在 IOS (iphone) 上无法正常工作

    我已经创建了this https codepen io salman15 project live DWbWpo Codepen 上的网站 在尝试使其响应所有平台时 我遇到了问题 看起来单个 div 覆盖了整个页面 仅在 IOS 上 并且并
  • 是否可以在“NSFetchRequest”中按子类排序而不添加其他属性?

    我想对结果进行分组NSFetchRequest按实体 这些实体都共享相同的抽象父级 例如 animal cat dog The NSFetchRequest has includesSubentities set TRUE and enti
  • 在 iPhone 应用程序中获取路线和路线导航

    我正在开发一款应用程序 该应用程序将重点关注在驾驶时为用户提供路线和逐段指示 他们在驾驶过程中留在应用程序中非常重要 因此我真的不想让他们离开应用程序并转到内置的地图应用程序 我最近对如何包含此功能进行了大量研究 众所周知 这并不容易 因为
  • iOS 在视图中添加/删除阴影

    我不明白如何删除添加到视图中的阴影 我添加到我的视图中initWithFrame这样的阴影 self layer borderWidth 2 self layer borderColor UIColor clearColor CGColor
  • 如何从 NSData 创建字节数组

    请任何人指导我如何从 nsdata 创建字节数组这是我创建 nsdata 的代码 NSData data UIImagePNGRepresentation img 如果您只想阅读它们 有一个非常简单的方法 unsigned char byt
  • iPhone 应用程序拒绝 17.2:应用程序要求用户使用 Facebook 帐户登录

    我按照此处的本机 iOS 应用程序的登录说明进行操作https developers facebook com docs mobile ios build https developers facebook com docs mobile
  • 如何在 iOS 企业帐户中创建开发人员配置文件请求?

    我们有 iOS 企业帐户 现在我们想要向我们的团队添加一名开发人员 该开发人员将创建一个开发人员配置文件 问题是新添加的开发人员在他的苹果帐户中看不到配置文件标签 任何人都知道新添加的开发人员如何创建配置文件 感谢您 Steps 您可以通过
  • 如何更改 iOS 5 中 UITabBarItem 中文本的颜色

    iOS 5 中有更多外观控制 我们如何更改 UITabBarItem 文本颜色 从默认白色变为其他颜色 编辑 工作解决方案 UITabBarItem appearance setTitleTextAttributes NSDictionar
  • AUGraph 在 iOS 上是否已被弃用?如果是的话,什么时候?

    我听到过这样的传言AUGraph在 iOS 上已被弃用 例如这篇推特帖子 https twitter com marcoarment status 878323409339338753 marcoarment 您对 atpfm 关于需要重写
  • 当我使用prepareForSegue将值传递给目标控制器时,存在一些问题

    首先 我使用storyboard创建两个uiviewcontroller 第一视图控制器 and 第二个视图控制器 并使用 xcode 嵌入导航控制器 into 第二个视图控制器 编辑器 gt 嵌入 gt 导航控制器 然后 我还想使用 se
  • swift 中 pch 的替代品是什么?

    我想知道可以用什么来代替 swift 中的 pch 有没有 pch 的替代方案或方法可以快速摆脱导入 这样我们就不需要对所有类都这样做 我不想一直随身携带 进口 swift 中 pch 的最佳替代品是什么 您无法在 swift 中定义 宏
  • Gmail 中删除了 iOS 深层链接

    我正在尝试发送一封带有深层链接的电子邮件到我的 iOS 应用程序 使用 myapp 格式从电子邮件中将其打开 它可以在任何 iOS 邮件客户端 邮件 邮箱等 中运行 即点击它打开应用程序 但不能在 Gmail 应用程序 甚至网络 中运行 因
  • 如何处理 iPhone 屏幕尺寸/背景图像分辨率

    在 iPhoneX 之后 我真的很纠结于支持所有设备的图像尺寸和命名约定 有没有办法在 4 7 5 5 和 5 8 屏幕上使用 3x 图像 全屏图像视图应该使用的确切尺寸是多少 您可以使用图像 pdf格式 因此您只需要管理 1x 的单比例图
  • 在 iPhone 上搜索 PDF

    经过两天尝试使用 Quartz 从 PDF 中读取注释后 我成功做到了并且发布我的代码 https stackoverflow com questions 4080373 get pdf hyperlinks on ios with qua
  • 隐藏故事板中的导航栏

    谁能告诉我如何隐藏故事板中的导航栏 我下面的代码在模拟器中运行时工作正常 但它仍然出现在我的故事板中 这真的很烦我 因为它弄乱了我的图像的位置 有人可以帮忙吗 void viewWillAppear BOOL animated super
  • 在 swift ios 中播放远程 mp3 文件需要花费大量时间

    我有麻烦了 我想在我的应用程序中播放远程 mp3 文件 但 mp3 文件需要很长时间 大约 5 6 分钟 来播放 为什么 任何人都可以建议我应该做什么 import UIKit import AVFoundation class TestV
  • 如何处理 iPhone 6S Plus 字体大小?

    与其他屏幕尺寸相比 iPhone 6S Plus 的屏幕非常大 我似乎无法找到一种在不以编程方式调整大小的情况下处理标签字体大小的好方法 如何调整标签的字体大小 使其在 iPhone 5 上看起来更小 在 iPhone 6 Plus 上看起
  • 如何从 UI 测试访问 App Delegate?

    我想访问特定的属性router在 UI 测试期间从启动的应用程序的应用程序委托中获取 但我不知道这是否可行 我努力了 let appDelegate UIApplication sharedApplication delegate as A

随机推荐