美文网首页iOS进阶知识程序员iOS Developer
Swift 封装一个视频播放器 VGPlayer

Swift 封装一个视频播放器 VGPlayer

作者: Vein_ | 来源:发表于2017-06-13 11:18 被阅读1317次
    Banners.png

    # 前言

    之前学习了 Swift 一直想做一个项目,这次下定决心花了近1个月的空闲时间基于 AVPlayer 封装了一个视频播放器。

    # 源代码

    • GitHub地址:VGPlayer
    • 有什么意见建议可以提 issues,在博文下留言,如果觉得不错,欢迎点star。

    # 更新列表

    • 2017-6-13 v0.0.1
    • 2017-6-17 v0.0.2 支持外挂字幕 格式 srt & ass 两种都支持
    • 2017-7-1 边播边缓存 v0.1.0
    • 2017-7-11 修复所有编译⚠️. v0.1.2
    • 2017-7-16 修复缓存视频时URL解析错误导致的crash. v0.1.3
    • 2017-8-10 修复退出全屏后的播放视图frame error问题,修复iOS9播放卡住问题,增加example 嵌入在cell中的播放模式. v0.1.4
    • 2017-9-6 v0.1.5 修复URL 解析问题 修复暂停播放问题
    • 2017-9-21 v0.2.0 整理代码、转换成Swift 4

    # 演示

    demo1.gif demo2.gif vgplayer_embed_in_cell.gif

    # 功能

    • 集成了视频播放器常有的手势,包括单击显示控制视图,双击暂停,水平滑动快进、后退,竖直滑动亮度和音量调节。
    • 全屏播放,自适应手机屏幕旋转方向。
    • 自定义控制视图

    # 实现思路

    流程图.png

    VGPlayer

    VGPlayer是一个对AVPlayer封装提供播放功能,displayView为播放器画面绘制。
    主要是使用了以下几个类:

    • AVURLAsset是 AVAsset的子类,用来本地或者网络视频地址的初始化网络请求,也可以用来获取视频每一帧的画面来实现滑动提前预览图的功能(后续应该会版本迭代加上此功能)
    • AVPlayerItem 是对AVPlayer播放的视频数据管理,对播放的Asset资源进行记录,提供或者视频的时间,播放状态等。
    • AVPlayer 调控数据和视图
    • AVPlayerLayer 进行视频视图绘制

    VGPlayer封装AVPlayer提供给调用者可选代理方法

    // player delegate
        // play state
        func vgPlayer(_ player: VGPlayer, stateDidChange state: VGPlayerState)
        // playe Duration
        func vgPlayer(_ player: VGPlayer, playerDurationDidChange currentDuration: TimeInterval, totalDuration: TimeInterval)
        // buffer state
        func vgPlayer(_ player: VGPlayer, bufferStateDidChange state: VGPlayerBufferstate)
        // buffered Duration
        func vgPlayer(_ player: VGPlayer, bufferedDidChange bufferedDuration: TimeInterval, totalDuration: TimeInterval)
        // play error
        func vgPlayer(_ player: VGPlayer, playerFailed error: VGPlayerError)
    

    VGPlayerView

    • VGPlayerView负责画面的展示,,只作为展示,而绘制层则是AVPlayerLayer提供,可继承此类进行控制视图的自定义
    • VGPlayerView封装AVPlayerLayer提供可选代理方法
    // player view delegate
        /// fullscreen
        func vgPlayerView(_ playerView: VGPlayerView, willFullscreen fullscreen: Bool)
        /// close play view
        func vgPlayerView(didTappedClose playerView: VGPlayerView)
        /// displaye control
        func vgPlayerView(didDisplayControl playerView: VGPlayerView)
    
    

    VGPlayerError

    • VGPlayerError一个 struct 用来播放出现Error时返回

    # 细节调整

    • 后台播放的实现
      设置工程
    backgroundModes.png
    // AppDelegate settings
     func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplicationLaunchOptionsKey: Any]?) -> Bool {
            // Override point for customization after application launch.
            do
            {
                try AVAudioSession.sharedInstance().setCategory(AVAudioSessionCategoryPlayback)
            }
            catch let error as NSError
            {
                print(error)
            }
            return true
        }
    

    设置VGPlayer的Background mode

    self.player.backgroundMode = .proceed
    
    • VGPlayerUtils 提供判断视频类型方法和一些通用的方法
    • UIButton+VGPlayer 扩展按钮点击范围
    • Timer+VGPlayer 解决Timer的 retain cycle问题

    边播边缓存 (参考: VIMediaCache)

    • 使用AVAssetResourceLoader 来控制视频缓存

    • 使用Range请求数据,可取消下载,分段缓存

    • 在 Simulator debugging, 可以看到缓存的文件


      test
    • 使用:

    // Settings maxCacheSize
    VGPlayerCacheManager.shared.cacheConfig.maxCacheSize = 160000000
    
    // Setting maxCacheAge   default one weak
    VGPlayerCacheManager.shared.cacheConfig.maxCacheAge = 60 * 60 * 24 * 7
    
    // clean all cache
    VGPlayerCacheManager.shared.cleanAllCache()
    
    // clean old disk cache. 
    // This is an async operation.
    VGPlayerCacheManager.shared.cleanOldFiles { }
    
    

    # 参考

    # 总结

    • 了解了AVPlayer的整体结构,对播放过程完整的思路和一些遇到的问题。
    • 踩了屏幕旋转细节、按钮点击范围调整的一些交互细节的坑

    相关文章

      网友评论

      • eecac22d66cf:只希望视频页面能横屏,其他都是竖屏(所以不能全局设置打开landscope Right)。请问这种情况怎么处理呢
      • Tate_code:最近刚好想学下swift视频这一块,感谢分享O(∩_∩)O哈!
      • Leo724651142:想请问下外挂字幕怎么实现
        Vein_:解析srt 、ass两种格式的字幕文件 ,解析成包括index标记、 star字幕开始时间、 end字幕结束时间 content字幕内容的结构体 , 然后剩下就是写label 展示上去 解析实现具体可以看看VGSubtitles
      • withJessicaZ:为什么pod找不到VGPlayer呢
        withJessicaZ:@Vein_ 竟然又可以了:flushed:
        withJessicaZ:@Vein_ 有没有其它联系方式:pensive: 我这里确实不行 想截图给你看看:pensive:
        Vein_:platform :ios, '8.0'
        use_frameworks!

        target ‘test’ do
        pod 'VGPlayer'
        end

        我测试了一下没有问题的
      • 小天枢丶:你好,我想问下缓存功能是怎么用的?
        Vein_:@null_b703 pod 'VGPlayer', '~>0.1.0'
        0.1.0以后版本才加入cache功能
        小天枢丶:@Vein_ pod安装下来的话是没有MediaCache文件夹的..VGPlayer.swift文件里面也没有缓存的那两行代码,直接下载下来拖进项目里面才有..
        Vein_:已经直接集成进去了。本地的视频不会缓存,网络的会缓存。
        fileprivate var resourceLoaderManager = VGPlayerResourceLoaderManager()
        self.playerItem = resourceLoaderManager.playerItem(URL)
        上面这两行就直接能缓存了 你可以在VGPlayer.swift 这个源文件看到
        然后
        VGPlayerCacheManager.shared.cacheConfig.maxCacheSize = 160000000

        // Setting maxCacheAge default one weak
        VGPlayerCacheManager.shared.cacheConfig.maxCacheAge = 60 * 60 * 24 * 7
        // clean all cache
        VGPlayerCacheManager.shared.cleanAllCache()

        // clean old disk cache.
        // This is an async operation.
        VGPlayerCacheManager.shared.cleanOldFiles { }
        可以对缓存做限制和清除

      本文标题:Swift 封装一个视频播放器 VGPlayer

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