为coplay Chrome扩展添油加醋

上次参加黑客马拉松之前有一个想法,就是希望能为两个人异地同看一个在线视频提供更好的体验:进度同步,弹幕,实时涂鸦等等。还有更多的实时语言功能就其实直接使用现成的微信就好。这样看来,视频进度同步和播放/暂停和拖动进度条的指令同步是核心功能。

当初想的通信技术方案是搭建一个私有服务器,两个浏览器通过一个Bookmarklet注入脚本,Websocket通信,并由中间的私人服务器中转进行。视频控制准备强制将flash视频转为Html5播放,方便控制,不过拖着一直没去实现。

最近看到一个推荐Chrome插件的知乎回答,答主使用Chrome扩展注入脚本,使用Peer.js,底层是WebRTC通信。去中心服务器直接通信,的确方便很多,并且已经支持多个视频站,插件也已经在Chrome Web Store上架,并Github开源,试用后立即Star了。

不过应该还有很多功能可以加,查看代码后觉得可扩展性也很好,不过在那之前,我想也许应该支持更多的视频站、让视频同步的体验更好才是纯粹的。

Flash的视频控制

之前固执地认为Flash视频是不可与Javascript交互的,2014年HackShanghai的时候,我们需要控制优酷视频的播放,后来由颢神找到了获取视频地址的方法,便转Html5的方式播放。不过那次由于想给用户提供一个更好的体验,很多UI都重写了,视频更加一体地融合在网页中,而这是Flash播放器做不到的。在看coplay源码的时候发现某些视频站已经发布了可以直接使用的API,如优酷的PlayerPause(false);info = PlayerInfo();等,可以直接方便地控制,更多的视频站由于自身需要,也加上了对javascript的API,通常我们query到DOM中的flash节点后,可以调用一个方法,比如土豆的player.notify('play'),更多是类似player.pauseQiyiVideo()这样。

Flash节点没有办法遍历这些在Flash中对外暴露的方法,那是怎么获得这些API的呢,可能官网上有文档,懒得去找了,跟随网页上Javascript的蛛丝马迹也许也能猜到。

尝试添加芒果台的适配器

于是我便开始猜测芒果台的API,在众多Javascript中(看到不少typo)找到了和Flash节点的调用,比如c('hunantv-player-1').getActionLogInfo(),不过只是一些视频信息。

我又开始尝试跟踪console中的播放和暂停的log,不过log是从Flash中打出的,或者是eval获得的,无法追踪源头。最终发现了一点Javascript中供Flash调用的回调函数,也没用什么用。我便觉得可能芒果台没有提供对外的API了。

看来硬猜是效率很低的。

通过反编译获知Flash视频控制的API

回想起之前Flash被Adobe降低优先级的新闻,提到Flash是ActionScript语言编写的,并交由FlashPlayer执行,之前并没有Flash的编程经验,但感觉应该很类似Java和JVM,便搜索到了一个免费的SWF decompiler,于是兴致勃勃地试了一下。

ffdec

反编译以后几乎是源码,ActionScript也基本上能读懂。查询Adobe文档后定位到ExternalInterface.addCallback()是注册对外的接口,而ExternalInterface.call()是Flash调用外部的Javascript函数,全文搜索反编译的结果很快就能定位到API了。

不过芒果台没有提供Seek,也就是设置视频进度的API,尝试Hack无果,最后还是放弃了。好在Bilibili和Acfun的API比较全,于是我便简单地加上了Bilibili的适配器。

应该来说一个好工具让我们效率倍增,尤其是Hack和性能调优的时候,比如Chrome的Javascript Profiler,Timeline和Trace就很好用,Web调优必备。