遨游浏览器“广告快进”产品思考和技术初探
作者:magictong
前言
这个功能个人觉得在产品侧的创新要大于在技术侧创新,因此花了较大篇幅来讲解该对该功能的产品体验和产品思考,而把技术分析放在了最后面。
背景
视频网站播放视频时,前面长达30秒,甚至60秒的视频广告一直是用户的痛点,这个在我们做广告过滤功能时多次听到用户反馈过,其实我们自己也挺烦的,但是我们之前的拦截方案是强技术的,直接拦截视频广告资源链接,干扰视频播放器的行为,更改用户的hosts信息等等方式,这种拦截方式有很大的法律风险(参考[1])。另外,腾讯视频那边也多次找到我们协商去掉对腾讯视频广告的拦截,迫于一些法律风险,视频广告频繁的对抗,造成拦截难度越来越高,因此后来我们的广告拦截逐步去掉了视频网站播放前广告的拦截。
而最近(2014/2/24)遨游浏览器推出了一款“广告快进”版本,为了推广该功能,广告是铺天盖地,连万利达一楼的电视广告上面都放了遨游的广告快进广告。
产品体验
第一时间装上了遨游的这个广告快进版本进行体验,发现确实可以快进优酷,爱奇艺,凤凰网等主流视频网站的广告,甚至连视频内容本身都可以快进。
然而主流视频网站的反制跟进也非常迅速(参考[2]),首先是25号早晨(可能更早)优酷发现如果广告被快进了,直接提示“本网站不支持您所使用的浏览器”。牛逼轰轰的,有点感觉是做了一个艰难的决定^_^。
到了25号晚上,优酷做了技术上面的反制,优酷的广告无法快进了,但是视频内容本身还可以快进。同样是25号晚上,遨游浏览器做了升级,把首页宣传广告快进的视频样例换成了爱奇艺的(不换不行了,快进不了优酷了嘛)。
目前还没有看到其它的视频网站做出反制措施,可能还在观望,毕竟目前傲游浏览器的市场份额少得有那么一点可怜(CNZZ数据:2%左右)。也许遨游这次的出风头是为了找下一家也不一定。
产品思考
遨游的这种方式可以认为是一个产品上面的创新,既可以给到用户一个满意的体验,60秒的广告,可能5秒就快进完了,又不会显得很暴力,我没有拦截你的广告呀,我只是给了用户一个快进的入口,有点打擦边球的感觉。但是你想过视频网站的感受没?!外面一片叫好声那是因为他们不是视频网站的开发者和运营者,换位思考一下,如果用户觉得电脑管家扫描病毒太慢了,修补漏洞太慢了,有个厂商说我出了一个“管家保姆”,提升扫描病毒的速度,然后把一系列关键API给挂钩了,让管家跳着扫描,速度果然快了,管家能接受了吗?!例子不太合适,但是我想优酷,爱奇异目前的心情应该是类似的^_^。
另外视频网站可以做的反制措施是很多的,再说你把广告快进了会影响视频网站收入吗?!当然会影响的!因此反制会是强烈的吗?!当然是强烈的!这简直就是红果果的“羞辱”视频网站的播放器技术嘛,如果我是优酷视频播放器的开发者,你觉得我会不会死命的反制呢?!
另外一点是像遨游这种首创,虽然可能很快就被反制了,但是广告效应是有了,对它们也是有利的,投入产出比相当低,而我们再跟进一个类似功能,意义可能不大。遨游可能开发这个功能花了一个月,视频网站可能几个小时就反制了。我们再去开发,一个月可能是搞不定的,毕竟管家没有自己的浏览器,后面的技术部分会讲到为什么这个地方没有浏览器是难点。
有没有什么其它的方案?也有一些童鞋提到过,我们可以在视频放广告的时候,提醒用户去干别的事情,然后在广告播完之后,弹一个轻Tips告诉用户,广告放完啦,可以看视频了,也许是一种方法,重点是让用户觉得没有浪费时间,又没有错过视频的观看。
建议我们可以先观察一下视频网站和遨游的战况情况吧。
技术初探
其实像swf这种视频的快进是很容易实现的,因为flash是支持js脚本调用它的导出接口的,而播放swf的默认播放器导出了很多视频播放控制接口(参考[3]),可以写一个小例子来看一下。
<html>
<head>
<title>flash快进</title>
</head>
<body>
<script type="text/javascript">
// Get Flash Object
functiongetFlashMovieObject(movieName)
{
if (window.document[movieName])
{
returnwindow.document[movieName];
}
else if (navigator.appName.indexOf("Microsoft")==-1)
{
if (document.embeds &&document.embeds[movieName])
returndocument.embeds[movieName];
}
else
{
returndocument.getElementById(movieName);
}
}
</script>
<p>
Game(swf)<br/>
<object id="GameFlashObj2"classid="clsid:D27CDB6E-AE6D-11cf-96B8-444553540000"codebase="http://download.macromedia.com/pub/shockwave/cabs/flash/swflash.cab#version=6,0,29,0"width="550"
height="400">
<param name="movie"value="1.swf">
<param name="quality"value="high">
<param name="play"value="false">
<embed id="GameFlashObj2"src="1.swf"play="false" quality="high"pluginspage="http://www.macromedia.com/go/getflashplayer"type="application/x-shockwave-flash"
width="550"height="400"></embed>
</object>
</p>
<input type="button" value="播放SWF"id="playSWF"> <inputtype="button" value="停止SWF"
id="stopSWF"><br/>
<input type="button" value="快进SWF(+100帧)"id="fastSWF">
<script type="text/javascript">
varbtnplay=
document.getElementById("playSWF");
btnplay.onclick =function()
{
getFlashMovieObject("GameFlashObj2").Play();
}
varbtnfast=
document.getElementById("fastSWF");
btnfast.onclick =function()
{
varobjFlash=
getFlashMovieObject("GameFlashObj2");
if (objFlash &&objFlash.IsPlaying())
{
objFlash.GotoFrame(objFlash.CurrentFrame()
+ 100);// 4097Frame
objFlash.Play();
}
}
varbtnstop=
document.getElementById("stopSWF");
btnstop.onclick =function()
{
getFlashMovieObject("GameFlashObj2").StopPlay();
}
</script>
</body>
</html>
这个例子非常简单,用来控制swf文件的播放是完全没有问题的,而且控制代码可以跨浏览器跨平台。想快进的话简单调用swf播放器的跳帧接口就实现了。
事情如此简单吗?!显然不是,那是因为视频网站播放的根本不是swf文件,而主要是f4v文件,这其实也是Adobe弄出来的一种高清视频格式,需要使用flash来播放,但是默认的flash播放器是胜任不了的,因此就需要使用flash来写一些专用的播放器,这些专用播放器也算的上是各大视频网站在客户端上运行的唯一有点技术含量的东东了,因此内部的复杂性也就可想而知,优酷有自己的播放器,爱奇异也有自己的播放器,大家都是不一样的。像下面这段爱奇异视频的播放HTML代码(截取自Chrome,IE下面可能会有微小差异),Play.swf这个玩意就是爱奇异自己的视频播放器,你可以下下来反编译一下,至于真正播放的视频的地址和广告地址等等都在flahsVars参数里面。
最开始我的想法是,遨游可能是脚本层面控制了这些视频播放器,但是找遍了也没有看到类似的控制脚本,而至于去反编译一款视频网站的播放器来研究,看起来则是一个不太可能完成的任务,像下面这个爱奇异的播放器反编译结果,里面类都有上千个,勿论去看每个类的代码了。何况视频网站这么多,每个都分析一遍,一个月是不可能完成的。
因此,遨游通过直接控制各种播放器的方式来快进的方式应该是不太可能的,虽然这样对于浏览器的兼容性可能会更好。
我实际编写了一些JS脚本去试图控制这些视频网站的播放,也都失败了。
另外一种可能的技术方案是控制flash的视频流,毕竟你的播放器要通过浏览器去下载视频的资源,在这个过程中,如果能够做一些手脚,控制视频的播放速度是有可能的。但是这里有几个问题存在。
1、不同版本的flash插件处理音频流和视频流是有差别的,有些甚至差别还很大,尤其是IE下面,N个版本。
2、浏览器内核有很多,在不同的内核下面,flash的插件肯定是不一样的。像IE下面flash插件是一个ocx控件,而chrome下面flash的插件就是一个npapi插件。
3、不同热度的视频资源,视频网站使用了不同的广告投放技术方案,热度更高的视频,相对来说广告不容易屏蔽。
这是最主要的难点,也是我在上面说到为什么管家不容易做的原因,因为管家自己是插件注入到形形色色的浏览器里面,各种浏览器内核,各种flash控件\插件版本,要解决这些兼容性问题就是一个无穷无尽的事情。而如果有自己的浏览器,那事情就简单多了,在研究遨游的过程中,发现遨游巧妙的解决了这个问题,遨游本身是双核浏览器,但是它在用户观看视频网站时,锁定为Chrome内核,用户无法切换内核。
另外就是打包了一个固定版本的flash.dll文件(Adobe公司,改名成NPSWF*.dll)。
这样它只需要处理这一个版本的flash插件即可,就解决了不同的flash版本之间的音视频解码的差异问题。
但是目前还是不清楚,遨游具体使用了什么技术方案,貌似也没有什么分析头绪,只好拿着遨游的老版本和新版本对比,查看各种可能的技术方案,网上查找各种控制视频流的技术方案,此处省略5000字……
最后发现新版本遨游自己挂钩了几个时间相关的API,时间!而进行InlineHook的那个dll是遨游自己MxVodCtrl.dll,嗯,从这个名字上面来看,好像是那么回事。
验证一下。把这几个钩子恢复一下,遨游的快进功能真的完蛋了。原来如些!
剩下的任务是枯燥的逆向这几个API钩子都干了些什么事情,但是可以大概的想象一下,它既然是Hook的时间相关的API,那么就说明那些视频播放器里面也调用了这些API,它们调用这些API的目的不外乎控制目前的播放进度和播放时间,当然最主要的事情可能还是计算需要读多长的视频缓存呢?嗯,发挥小伙伴的想象力吧!
至于网站反制显然也很容易,它只要使用其它的方法来统计广告的总共播放时间,甚至做timestamp校验,就能绕过这个“广告快进”。这也是为什么遨游辛辛苦苦几个月,优酷分分钟就反制了的原因。你的技术方案依赖人家的技术实现嘛。
因为目前我们暂时是观望态度,没有对这个技术做更深入的分析(如果需要的话,估计需要几天的时间来逆向那些APIHOOK函数,另外最好是有在WEB视频播放这块比较熟悉的开发介绍一下视频播放的过程,对逆向会更有利)。
参考资料
[1] 金山优酷陷官司纠纷互诉不正当竞争各胜一场http://tech.qq.com/a/20131227/016573.htm
[2] 遨游声音太大,视频网站反弹http://info.broadcast.hc360.com/2014/02/260952592240.shtml
[3] JS控制网页中Flash影片的播放(附带各参数)http://blog.csdn.net/lzkkevin/article/details/6789593
[4] JS传值给flashhttp://blog.csdn.net/lulu_jiang/article/details/6233493
[5] flv f4v 格式web 网页嵌入 源代码http://blog.163.com/w_jingli/blog/static/3825536920100445944690/
[6] Javascript与Flash通信全解析https://www.imququ.com/post/39.html
[7] js调用flash中定义的方法http://www.phpvar.com/archives/2769.html
[8] ActionScript与javascript相互调用http://blog.csdn.net/u010150082/article/details/14446087