iOS视频播放(二)

作者: 卡丁车手 | 来源:发表于2016-09-24 13:21 被阅读1508次

    这篇文章介绍一下基于AVPlayer的视频播放器。

    先上Demo,点击我的GitHub下载Demo。

    AVPlayer介绍

    AVPlayer最大的优势是能够定制播放器的界面样式。AVPlayer本身是不能播放视频的,要播放视频,必须创建一个AVPlayerLayer,将AVPlayerLayer添加到控制器视图才能播放。除了AVPlayer和AVPlayerLayer,还需要一个类AVPlayerItem。AVPlayerItem是媒体资源管理对象,管理视频的一些基本信息和状态,一个AVPlayerItem对应着一个视频资源。

    创建好AVPlayer、AVPlayerLayer、AVPlayerItem对象之后就能开始播放视频。下面一一介绍播放暂停、播放时间、缓冲进度等功能。

    ToolBar.png
    1、播放/暂停

    使用视频URL初始化一个AVPlayerItem,把AVPlayerItem设置为AVPlayer的currentItem,然后通过KVO监听AVPlayerItem的属性[playerItem addObserver:self forKeyPath:@"status" options:NSKeyValueObservingOptionNew context:nil],当属性变为AVPlayerStatusReadyToPlay时,通过AVPlayer调用- (void)play方法即可播放视频。

    AVPlayer的- (void)play- (void)pause分别控制播放和暂停,根据AVPlayer的播放速度rate可以判断当前是否为播放状态,rate=0暂停,rate=1播放。视频播放完成后AVPlayerItem会发送AVPlayerItemDidPlayToEndTimeNotification通知。

    2、视频时间

    视频时间包含两部分:视频总时间和视频当前播放时间。视频总时间通过CMTimeGetSeconds(_player.currentItem.duration)获取,当前播放时间通过CMTimeGetSeconds(_player.currentTime)获取。

    获取到这两个时间,就可以展示视频播放进度。播放进度需要一秒更新一次,可以用定时器来更新,也可以用AVPlayer的方法- (id)addPeriodicTimeObserverForInterval:(CMTime)interval queue:(nullable dispatch_queue_t)queue usingBlock:(void (^)(CMTime time))block在Block里更新。建议使用这个方法更新时间,因为它更新时间更加准确,使用block的参数time获得准确的播放进度。

    获取播放进度之后,分别给显示时间的Label和UISlider赋值,用户可以拖动UISlider对视频进行拖动播放,在拖拽结束之后,使用- (void)seekToTime:(CMTime)time toleranceBefore:(CMTime)toleranceBefore toleranceAfter:(CMTime)toleranceAfter让视频从拖拽到的地方开始播放。

    3、缓冲进度

    通过KVO监听AVPlayerItem的loadedTimeRanges属性来监听缓冲进度更新,在KVO中添加下面代码获取当前缓冲进度。

    NSArray *array = _player.currentItem.loadedTimeRanges;
    CMTimeRange timeRange = [array.firstObject CMTimeRangeValue];//本次缓冲时间范围
    NSTimeInterval startSeconds = CMTimeGetSeconds(timeRange.start);//本次缓冲起始时间
    NSTimeInterval durationSeconds = CMTimeGetSeconds(timeRange.duration);//缓冲时间
    NSTimeInterval totalBuffer = startSeconds + durationSeconds;//缓冲总长度
    float totalTime = CMTimeGetSeconds(_player.currentItem.duration);//视频总长度
    float progress = totalBuffer/totalTime;//缓冲进度
    
    4、视频切换

    每个AVPlayer只能播放一个视频,切换视频可以用- (void)replaceCurrentItemWithPlayerItem:(AVPlayerItem *)item来实现。

    视频切换.png

    播放器代码已经上传了我的GitHub,欢迎下载,这里就不贴代码了。

    ** 全屏播放效果:**

    全屏播放.png

    相关文章

      网友评论

      • 9f219eed9d2a:viewWithFrame只要调用这个方法就报错 什么原因 怎么解决啊xcode9
        9f219eed9d2a:我找到错误原因了 应该不是你项目的问题 这个在ios11上也没有失效 是xcode9的原因 我用Xcode8打开 编译找到了错误原因 现在已解决
        卡丁车手:可能是NSBundle的方法在ios11上失效了,如果项目中使用视频播放器,我推荐你使用这个:https://github.com/renzifeng/ZFPlayer 毕竟我这个只是练手的demo:joy:
      • hu9134:请教一个问题,现在有一个需求是实现视频慢速播放,2,4,8倍慢速播放,我是使用的AvPlayer,本来是设置的rate来控制播放速度,因为正常播放时rate为1,想设置慢速的话,就设置0--1之间的数字,但是发现设置0.5和0.1都是一个速度,请问这个怎么实现?非常感谢!
        hu9134:@灵魂车手 大神你好,非常感谢能解答我的问题,这个问题算是解决了,苹果好像就是只支持几种速度:唯一支持的值是0.50,0.67,0.80,1.0,1.25,1.50和2.0 ,我是按照这个里面的解决方法:http://stackoverflow.com/questions/6630356/avplayer-rate-property-does-not-work
        hu9134:@灵魂车手 @灵魂车手 好的,非常感谢!我再看看有没有什么别的办法能实现吧.是不是iOS10对这个api有更新了,我这里对api的注释是这样的
        /*!
        @property rate
        @abstract Indicates the desired rate of playback; 0.0 means "paused", 1.0 indicates a desire to play at the natural rate of the current item.
        @discussion
        Setting the value of rate to 0.0 pauses playback, causing the value of timeControlStatus to change to AVPlayerTimeControlStatusPaused.
        Setting the rate to a non-zero value causes the value of timeControlStatus to become either AVPlayerTimeControlStatusWaitingToPlayAtSpecifiedRate or AVPlayerTimeControlStatusPlaying, depending on whether sufficient media data has been buffered for playback to occur and whether the player's default behavior of waiting in order to minimize stalling is permitted. See discussion of AVPlayerTimeControlStatus for more details.

        AVPlayer can reset the desired rate to 0.0 when a change in overall state requires playback to be halted, such as when an interruption occurs on iOS, as announced by AVAudioSession, or when the playback buffer becomes empty and playback stalls while automaticallyWaitsToMinimizeStalling is NO.

        The effective rate of playback may differ from the desired rate even while timeControlStatus is AVPlayerTimeControlStatusPlaying, if the processing algorithm in use for managing audio pitch requires quantization of playback rate. For information about quantization of rates for audio processing, see AVAudioProcessingSettings.h. You can always obtain the effective rate of playback from the currentItem's timebase; see the timebase property of AVPlayerItem.
        */
        卡丁车手:@hu9134
        /*! @property rate
        @abstract Changes the playback rate of the input signal
        @discussion
        A value of 2.0 results in the output audio playing one octave higher.
        A value of 0.5, results in the output audio playing one octave lower.

        Range: 0.5 -> 2.0
        Default: 1.0
        Mixer: AVAudioEnvironmentNode
        */
        这是苹果API对rate的描述,看样子只能设置0.5到2.0之间的速率。。
      • 峰子1994:发现了一个问题就是我播放完了一个视频然后拖动进度条然后到0然后他又会自动的播放视频是怎么回事呀这个情况呀
      • kinmo:好的 谢谢,顺便问一下怎么自动隐藏进度条
        卡丁车手:@July丶ye 你可以在播放器类里写个定时器,toolView显示的时候开始定时,隐藏后暂停定时,定时器在开启5秒后隐藏toolView
        kinmo:@灵魂车手 就是想当进度条处于显示状态,一段时间后自动隐藏进度条
        卡丁车手:@July丶ye 进度条在toolView里,你可以隐藏整个toolView,self.toolView.hiden=YES;
      • kinmo:楼主在么
        异常断点停在:[self.player removeTimeObserver:self];这一句
        具体错误:Terminating app due to uncaught exception 'NSInvalidArgumentException', reason: 'You did not supply a reference to an object returned by either -addPeriodicTimeObserverForInterval:queue:usingBlock: or -addBoundaryTimeObserverForTimes:queue:usingBlock:'
        请帮忙解决一下
        卡丁车手:@July丶ye 把[self.player removeTimeObserver:self];这行代码删除就不崩溃了。具体崩溃原因需要研究一下,完了给你答复 :blush:
      • kinmo:从A控制器跳转到B控制器,然后在B控制器播放视频,当返回A控制器的时候报错
      • kinmo:进度条怎么自动隐藏?
      • 小白我们走吧:啊啊啊,我的不是xcode8 :disappointed_relieved:
        小白我们走吧:@灵魂车手 好的 射射
        卡丁车手:@花無缺 如果用Xcode7运行报错:The document "(null)" requires Xcode 8.0 or later. 右键报错的StoryBoard或Xib文件-->Open As-->Source Code,删除 <capability name="documents saved in the Xcode 8 format" minToolsVersion="8.0"/>这一行即可。
      • Clee:楼主你好,我现在想播放某个区间的视频段,比如一个视频是30s,我只播放5s-10s,我使用了这个方法- (void)seekToTime:(CMTime)time toleranceBefore:(CMTime)toleranceBefore toleranceAfter:(CMTime)toleranceAfter,开始时间没问题,但是结束的时间不对,视频总是会播放到30s,你有用过吗?
        卡丁车手:@cleexiang AVPlayer似乎没有这个需求的API,另外你对- (void)seekToTime:(CMTime)time toleranceBefore:(CMTime)toleranceBefore toleranceAfter:(CMTime)toleranceAfter这个方法的理解似乎有误,这个方法作用是:播放时间跳转到time处,这个时间的准确度是[time-toleranceBefore , time+toleranceAfter]。假如time=5、toleranceBefore=1、toleranceAfter=0.5,那么你调用这个方法之后,视频会从4s-5.5s区间内开始播放。

      本文标题:iOS视频播放(二)

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