swift:基于MPMoviePlayerController的视频播放器

前言

高仿网易新闻遇到视频播放的问题,以前很少做多媒体这一块,我一向的逻辑就是想弄清楚就从零开始写。所以出于学习的目的,自己又制造了一个轮子。项目地址WLVideoPlayer-MP-, 花很大的心思加强复用性。具体效果如下。

准备

为了方便新同学学习多媒体视频播放的相关内容,已经把每一个步骤都打包成一个单独的工程

当然,你也完全可以从Github上clone整个项目。

WLVideoPlayer的使用

        playingPlayerView = WLVideoPlayerView(url: NSURL(string: urlStr)!)
        playingPlayerView?.customControlView = controlView //你需要的控制面板
        playingPlayerView?.placeholderView = UIImageView(image: UIImage(named: "placeholder")) // 视频加载时的等待图片
        playingPlayerView?.playInView(inView) // 播放

WLVideoPlayer提供了默认的视频控制面板,如果你想使用自己的,只需要继承自WLBasePlayerControlView并根据WLPlayerControlViewDelegate协议调用你想实现功能的相应代理方法即可。你所做的只有布局你的自定义控制面板。

功能分析

苹果提供的MPMoviePlayerController功能已经很完善了,那为什么还要要自定义视频播放器?弄清这一点,我们才能知道我们自定义视频播放器的的目的。

  • 最直接的无非就是控制面板的问题,视频控制面板太丑,上面很多控件是用不着的。
  • 支持的播放格式少

而又因为播放格式的问题涉及到视频文件的解码,这个对于不是学习视频算法的我们太过于牵强(虽然有VLC)。所以我们自定义视频播放器的的任务已经很明显了。

  • 能支持自定义视频控制面板
  • 视频播放\停止\拖拽快进等基本功能
  • 视频全屏与屏幕旋转问题的解决

其中我认为最重要的便是能支持自定义视频控制面板,它决定了你的这个小播放器能不能重复使用

代码简析

这是播放器主体代码,其他的部分都是测试用的数据源,是从作者另外一个开源项目高仿网易新闻中分离出来。具体实现不需要太过于关心。因为代码中加了大量的注释,所以只简单介绍一下重要的一些代码片段。

WLVideoPlayerView.swift

外接都是通过直接操作这个类来控制视频播放器的行为。


    var contentURL: NSURL? 
    var placeholderView: UIView?
    /// 用户自定义控制界面
    var customControlView: WLBasePlayerControlView? 
    /// 用户自定义视频控制面板自动隐藏的时间
    var customControlViewAutoHiddenInterval: NSTimeInterval 
    /// 进入全屏的模式
    var fullscreenModel: WLVideoPlayerViewFullscreenModel 
    

这些都是暴露出来提供外部来设置播放器的一些属性,其中值得一提的便是customControlView这个的属性。这便是我们的视频控制器视图了,当初在设计的时候十分头疼,原本应该是这样,这个customControlView必须是UIView的子类,而且他也必须遵守我设置的一系列协议规范。但是很可惜我没有发现swift中有类似于oc这样的写法

UIView<someProtocol> *customControlView

于是我在妥协之下,只能使用继承这种不太优雅的方式解决。设计了一个类似于抽象类的WLBasePlayerControlView

接下来是一堆私有属性,其中需要主要的是

lazy var playerControlHandler: WLPlayerHandler = WLPlayerHandler()

这个对象的功能是处理视频控制器的事件,比如暂停、快进、全屏等事件。设计这样一个对象的目的是为了将视频控制器的事件于播放事件进行分离,减少WLVideoPlayerView.swift的代码量。

然后值得一提的便是几个全屏\旋转的控制方法

func toLandscape(angle: CGFloat)
func toPortrait()
func enterFullscreen
func exitFullscreen()
func changePlayerScreenState

因为iPhone手机应用一般都会禁止项目的旋转,一般只会支持Portrait这一个方向,然而我们往往是希望当手机横屏播放视频的时候,视频内容能够铺满全屏。在这样的需求下,系统自带的setFullscreen方法是不好使的。所以只能自己实现放大、缩小、旋转的方法。当发生全屏、退出全屏、旋转等事件时,对播放器视图、控制面板视图进行处理。因为视频控制面板又是用户自定义的,几乎都是使用autolayout进行布局,所以在必须更新相应的约束。

WLPlayerHandler.swift

这个文件主要是WLPlayerHandler类的实现,之间也解释了,WLPlayerHandler是为了将视频控制面板的逻辑与视频播放本身逻辑进行分离而设计的一个类。WLPlayerHandler主要处理用户自定义控制面板的一些事件,比如:暂停按钮点击、全屏按钮的点击、进度条拖拽等

    weak var player: MPMoviePlayerController!
    weak var customControlView: WLBasePlayerControlView!

这里使用weak关键字是为了防止WLVideoPlayerView的实例对象与WLPlayerHandler实例对象造成循环引用。

WLBasePlayerControlView.swift

这个文件里面定义了WLPlayerControlViewDelegate代理协议与WLBasePlayerControlView类,这样是妥协的设计办法,暂时因为作者能力有限没找到更加优雅实现方式。WLBasePlayerControlView类是所有自定义视频控制面板的基类,如果想实现你自己的播放面板,你得继承自这个类,并通过delegate属性调用WLPlayerControlViewDelegate协议提供的方法来处理你面板上的事件。

PlayerControlView.swift和PlayerDemoControlView.swift

这两个文件是提供给大家参考的视频控制面板的实现方式,PlayerControlView是用xib进行布局,而PlayerDemoControlView.swift是使用SnapKit进行布局。参照这两个的实现方式,完全可以自定义你专属的视频控制面板。

PlayerControlViewAuxiliary.swift

这里面定义的是UpdateProgressProtocol协议以及提供的默认实现,也是提供给自定义视频控制面板使用的

总结

在实现WLVideoPlayer这个轮子的过程中,发现如果不涉及对视频的解码,自定义一个播放器的过程也就是自定义它的视频控制面板的过程。而对于视频播放的逻辑处理(如快进、全屏等)各个播放器基本都是一样的。不同的仅仅在于视频控制面板的样式不同。正因为这一特征,我才将视频控制面板逻辑处理与视图布局分离。这样,我只需要写一次通用的逻辑处理方式,以后再根据不同的需求设计不同控制面板即可。这样这个轮子造的才有意义。如果你是新手,您根据我开发工程的步骤,对代码重构的过程,应该会有理解。如果您有更好的建议或者意见,欢迎您的指出。

后续工作

这个轮子已经具备的一个简单播放器的基本功能,但任然有很多的功能可以添加,日后将不断对这个项目进行完善、对代码质量进行提高。不过MPMoviePlayerController这个类苹果已经不建议我们使用了,所以以后应该还会使用AVPlayer开发一个类似的播放器。最后再次附上本项目地址WLVideoPlayer-MP-

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 212,294评论 6 493
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 90,493评论 3 385
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 157,790评论 0 348
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 56,595评论 1 284
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 65,718评论 6 386
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 49,906评论 1 290
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 39,053评论 3 410
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 37,797评论 0 268
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 44,250评论 1 303
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 36,570评论 2 327
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 38,711评论 1 341
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 34,388评论 4 332
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 40,018评论 3 316
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 30,796评论 0 21
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 32,023评论 1 266
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 46,461评论 2 360
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 43,595评论 2 350

推荐阅读更多精彩内容

  • 发现 关注 消息 iOS 第三方库、插件、知名博客总结 作者大灰狼的小绵羊哥哥关注 2017.06.26 09:4...
    肇东周阅读 12,066评论 4 62
  • 昨天开始了在一个为期一个月的自信打卡群打卡的第一天。要求是在早晨七点前在群里发送自信日记,记录自己前一天对自己表现...
    Hannah_阅读 245评论 0 1
  • 1.出去走走,换换空气,,散散心,,一条腿的青蛙,,,,两条腿的,,,1:永远不要让任何一个男人成为你生命的全部,...
    简明估阅读 583评论 0 0
  • It is a bad day! 真是糟透了的一天! 越是追求事事完美,往往事情就会往相反的方向去发展。今天就是一...
    怡方阅读 352评论 0 0
  • 01. “嗒铃嗒铃——” 林思雨看了一眼手机屏幕上显示的名字,她嘴角不自觉地上扬,她伸出手数着数,手机铃声响了三声...
    栗胖胖1996阅读 850评论 13 7