iOS视频播放之AVFoundation框架

作者: 清溪丷 | 来源:发表于2016-03-21 20:28 被阅读10216次

    上一章说了iOS中音频播放的一些方法,不过现在APP中音频和视频都是不可缺少的,他们都是AVFoundation框架中的类,这里就简单的说下视频的类AVPlayer。

    首先要说一下,现在是iOS9的系统,苹果公司在推出iOS9之后弃用了之前使用的MPMoviePlayerViewController,改用了AVPlayerViewViewController(<AVKit/AVKit.h>)框架,这个框架是使用视频播放控制器的时候要使用的方法,简单的创建一个视频播放器不导入AVKit也可以的,只需导入AVFoundation框架即可。

    首先介绍一下视频播放相关的类名

    1.AVPlayer 用于播放音视频
    2.AVPlayerItem 音频的对象
    3.AVPlayerLayer 播放显示视频的图层界面
    4.AVPlayerViewController 他会帮你去创建显示视频的图层 有调节控件

    接下来我们说一下具体的步骤

    在开始之前,我们需要明白,播放视频需要三部分完成,第一部分是AVPlayer,视频播放器,第二部分是AVPlayerItem,视频要播放的元素,AVPlayerLayer,视频显示的图层。

    他们的具体流程是AVPlayer(视频播放器) ->去播放AVPlayerItem视频播放的元素 ->展示播放的视图AVPlayerLayer

    要注意视频播放和音频播放雷同,也需要把视频播放器设置为全局变量

    @interface ViewController ()
    {
        AVPlayer *player;
    }
    @end
    

    同样我们需要一个视频元素的URL,这里我直接使用本地工程内的一个文件。

    //   1 创建要播放的元素
    
        NSURL *url = [[NSBundle mainBundle]URLForResource:@"视频文件名" withExtension:nil];
    //    playerItemWithAsset:通过设备相册里面的内容 创建一个 要播放的对象    我们这里直接选择使用URL读取
        AVPlayerItem *item = [AVPlayerItem playerItemWithURL:url];
    
        //    duration   当前播放元素的总时长
    //    status  加载的状态         AVPlayerItemStatusUnknown,  未知状态
    //    AVPlayerItemStatusReadyToPlay,  准备播放的状态
    //    AVPlayerItemStatusFailed   失败的状态
    
    //    时间控制的类目
    //    current
    //    forwordPlaybackEndTime   跳到结束位置
    //    reversePlaybackEndTime    跳到开始位置
    //    seekToTime   跳到指定位置
    
    //2  创建播放器
    player = [AVPlayer playerWithPlayerItem:item];
    //也可以直接WithURL来获得一个地址的视频文件
    //    externalPlaybackVideoGravity    视频播放的样式
    //AVLayerVideoGravityResizeAspect   普通的
    //    AVLayerVideoGravityResizeAspectFill   充满的
    //    currentItem  获得当前播放的视频元素
    
    //    3  创建视频显示的图层
        AVPlayerLayer *layer = [AVPlayerLayer playerLayerWithPlayer:player];
        layer.frame = self.view.frame;
       // 显示播放视频的视图层要添加到self.view的视图层上面
        [self.view.layer addSublayer:layer];
    
    //最后一步开始播放
    [player play];
    

    到这一步,就能实现简单的视频播放了,但是并不能像手机应用上面,既有快进,又有暂停,还可以看到进度条。那么我们来试着实现这几点。

    视频一共有几个状态,没播放之前的状态,预播放状态,播放状态,当视频预播放的时候我们才能获得时长,但是我们怎么能知道什么时候视频预播放完毕,就是怎么样获得时长的办法了,我们可以通过KVO来实现这一要求。添加一个观察者去监听item的状态。

    //    采取kvo的形式获取视频总时长
    //    通过监视status判断是否准备好
    
        [item addObserver:self forKeyPath:@"status" options:NSKeyValueObservingOptionNew context:nil];
    
    -(void)observeValueForKeyPath:(NSString *)keyPath ofObject:(id)object change:(NSDictionary<NSString *,id> *)change context:(void *)context
    {
    //    NSLog(@"%@",change[@"new"]);
        switch ([change[@"new"]integerValue]) {
            case 0:{
                NSLog(@"未知状态");
                break;
            }
            case 1:{
                NSLog(@"获得视频总时长  %f",CMTimeGetSeconds(player.currentItem.duration));//CMTime在下面会介绍
                break;
            }
            case 2:{
                NSLog(@"加载失败");
                break;
            }
            default:
                break;
        }
    }
    

    那么这样我们通过添加一个监听来达到可以获得他视频元素状态的改变,来得到一个视频时长。

    还有一点要说的是,我们得到视频时长的时候,获得的值是一个CMTime类型的值,他表示视频播放的进度,它里面有两个属性,一个是value(进度)一个是timescale(帧率)

    //    CMTime 视频播放进度  value(进度)    timescale(帧率)
    //    CMTimeMake(<#int64_t value#>, <#int32_t timescale#>)
    //    kCMTimeZero  表示初始进度
    //    seekToTime:跳转到某一个进度
    //    currentTime获得当前时间,CMTime类型
    //    CMTimeGetSeconds(<#CMTime time#>)通过一个CMTime来获得当前播放时间的秒数
    

    了解了这个属性之后快进功能我们也可以来实现了
    快进的功能就是得知当前视频的时间,然后在这个时间的基础上加上一段时间,就达到了快进的功能。
    那么我们可以获得当前的时间

     Float64 cur = CMTimeGetSeconds(player.currentTime);
    

    首先获得当前的时间,然后令他自加5秒。
    每次点击,都获得当前的时间,然后令他自加5秒。
    然后使用视频播放时来跳转到这个时间。

    [player seekToTime:CMTimeMake(cur, 1)];
    

    帧率在这里我们可以先不用去管它,如果想了解的话也可以去度娘一下,在视频动画制作的时候会接触这个知识。

    然后说一个视频播放的系统方法

    - (void)itemDidPlayToEndTime:(NSNotificationCenter *)not
    {
        NSLog(@"播放结束");
        //使视频在播放结束的时候跳转到初始画面。
        [player seekToTime:kCMTimeZero];
    }
    

    基本属性在上面都有介绍,这是制作一个简单的视频播放器的方法,那怎么样能快速简洁的制作一个播放器呢,其实iOS里面有一个专属的类,交视频播放控制器AVPlayerViewController。
    使用这个方法可以直接跳转到一个带有视频播放器的一个控制器controller。同时里面带有工具栏。需要注意的是在你使用AVPlayerViewController的时候,需要先导入AVKit框架。在开头已经告诉了大家这个框架。

    1 准备一个播放器

    AVPlayer *player = [AVPlayer playerWithURL:[[NSBundle mainBundle]URLForResource:@"视频文件名" withExtension:nil]];
    

    2.创建一个AVPlayerViewController,同时把其上面的播放器设置为你初始化的播放器。

    AVPlayerViewController *playerVC = [[AVPlayerViewController alloc]init];
        playerVC.player = player;
    
    playerVC.view.frame = CGRectMake(50, 50, 300, 250);
        [self.view addSubview:playerVC.view];
        player.externalPlaybackVideoGravity = AVLayerVideoGravityResizeAspectFill;//这个属性和图片填充试图的属性类似,也可以设置为自适应试图大小。
    

    3 开始播放

    [player play];
    

    只有简单的几部就可以完成一个视频播放器。这个视频播放控制器也可以通过跳转来进入

    showsPlaybackControls这个属性可以控制播放器是否显示工具栏,默认是YES
    它里面也有一些代理方法来方便对其进行操作
    - (void)playerViewControllerWillStartPictureInPicture:(AVPlayerViewController *)playerViewController;
    {
    // 在视频将要开始播放的时候调用
    }

    - (void)playerViewControllerDidStartPictureInPicture:(AVPlayerViewController *)playerViewController;
    {
        //视频已经开始的时候调用
    }
    
    - (void)playerViewController:(AVPlayerViewController *)playerViewController failedToStartPictureInPictureWithError:(NSError *)error//播放失败的时候
    
    - (void)playerViewControllerWillStopPictureInPicture:(AVPlayerViewController *)playerViewController;//将要停止的时候
    
    - (void)playerViewControllerDidStopPictureInPicture:(AVPlayerViewController *)playerViewController;//已经停止的时候
    

    经常使用的就是这些属性,这次简单介绍了视频播放的一些知识,下次在介绍一些视频录制的一些相关知识。

    相关文章

      网友评论

      • Mister志伟:AVPlayer 的
        -(void)seekToTime
        方法当time时间大小小于一秒的时候,AVPlayer就不会作同步的处理(如:快进,后退等),会依然保留在原来的位置。
        AVPlayerDemo里面,通过Slider去拖动时,也是当经过时间大与1的时候才会进行一次同步。
        想请问一下怎么让AVPlayer 快进/后退 1秒以下的时间?
      • zhangferry:播放器全屏又什么办法吗,直接设置frame又会回到之前的状态
        91402a65e33d: [self presentViewController:playerVC animated:YES completion:nil];
        VPlayerViewController *playerVC 这个是全局的
      • afa38ae8399f:楼主问下,问什么这个播放点击屏幕就崩溃了啊
      • 再见代码:创建视频显示的图层 为啥只是高度相同 宽度会随视频宽度改变
      • puppySweet:这个框架能处理视频的尺寸么……控制播放速率和帧数
        清溪丷:@puppySweet 速度是没有的,CMTime当中有两个属性,第一个是就是时间,第二个是帧率,这个和动画的帧率有关,你可以去查询一下帧率的概念,如果你要做一个快放功能的话你可以在快进按钮里面更改它的current time值,把它的数值变成以自加2的形式,选中状态的时候就让它一直自加,形成一个快速播放的方式。至于分辨率,在这个框架内是没办法设置的,你只能获得这个属性,是个只读的,因为你的视频元素是固定的,所以这个就没办法了,他是在预播放的状态下获得到的,可以找一下你们公司其他部门的人在中间调整一下他的属性吧
        puppySweet:@清溪丷录像的是时候只能设置分辨率啊而且分辨率 只有几种。尺寸设置真找不到 ..CMTime这个是帧率么 速度也找不到😦😱😱求楼主帮助
        清溪丷:@puppySweet externalPlaybackVideoGravity这个属性是让视频自适应或者填充满的,视频的尺寸好像录制的时候才可以设置,不过可以调整播放器的大小来处理,控制速率和帧数是可以的

      本文标题:iOS视频播放之AVFoundation框架

      本文链接:https://www.haomeiwen.com/subject/svvklttx.html