音乐MV在演变发展。目前在网络上大量出现,并且广泛流行的音乐MV,令MTV和VH1 之类的电视音乐频道都黯然失色。不同于传统媒体( 例如电视) 一个接一个地播放,网络上的音乐录影带需要通过竞争吸引眼球。那么,艺术家如何让自己的作品脱颖而出,尤其如果你是像杰丝敏·维利加斯 (Jasmine Villegas)那样的后起之秀?
这是杰丝敏和IE浏览器团队试图面对的挑战,目标是通过营造浏览器上的互动体验吸引现有粉丝,并且帮助她拓展粉丝群。为了做好这件事,微软召集创意机构 Digital Kitchen和Bradley and Montgomery 的HTML5专家一同创建了justafriend.ie,它不仅实现了杰丝敏的目标,还展示了HTML5在Web上的力量。
简 介
大量的前沿技术使整只音乐录影带更复层次感,无论你是杰丝敏· 维利加斯的死忠粉,还是仅仅想更多地了解 HTML5 ,都可以通过这篇文章了解我们是如何赋予Just a Friend 活力的:
- 搭建基于(符合)HTML5标准的网站
- 将Facebook数据连接到 Web 应用上
- 在HTML5 Canvas和视频上投影图像
- 用像素记录视频帧数
- 为了性能 “ 打散” PNG
- 序列化和媒体资源加载
- 拨打您的数字电话
1 . [ 译注 ] 杰丝敏·维利加斯 (Jasmine Villegas) ,人们也称她为杰斯敏 V,1993年12月7 日出生,美国少年R&B 和流行歌手,曾出演贾斯汀比伯的成名作Baby的MV,经过多年音乐梦想的追寻,最终与索尼唱片签约。
搭建HTML5标准网站
如何确保高级浏览器能识别我们的网站,并且能使用 HTML5 视频技术而非插件?
很简单:
将社交网络数据连接到Web应用上
Facebook Connect 是
justafriend.ie 不可或缺的组件,它让用户能够亲身参与到体验中。当你第一次打开视频时,会被邀请连接到你的Facebook 账户,我们就可从你的账户中提取图片,直接放到视频中。我们还会根据故事的发展显示你的名字,让你感觉自己就像是视频中的人物。
在HTML5 Canvas 和视频上投影图像
HTML5图像投影不是一个新的概念。实际上,项目的大部分早期工作都是基于史蒂文·威腾斯 (Steven Wittens) 提供的项目acko.net/files/projectivecanvas/index.html。但在测试中,IE9 执行的Canvas 投影比其他现代浏览器更好,因此必须修改代码以保证在其他平台上的性能。

一个很好的例子是让记分牌显示从Facebook Connect 提取的用户姓名。为了做到这个,我们需要修改实现投影的代码来让它作用于canvas 缓冲区,而非单一的图片。这样我们就能先将不同种类的元素集合在canvas 缓冲区,再进行投影。我们利用canvas 绘图 API 将提取的姓名绘制到空白的记分牌图片上。顶部放置另一个PNG 图片,提供些许亮光,让投影的整体效果与视频完美融合。
除此之外,这种PNG 分层技术还应用在了视频开始部分将用户的Facebook照片粘贴到杰丝敏卧室墙壁上的效果。我们在用户的照片上叠加了有阴影效果的PNG 图片,使其与墙壁背景完美融合,并与其他照片非常自然地一同展现。视频结束时,应用了同样的技术对杰丝敏书桌上的照片进行处理 。最终效果如下所示:
投影前:

投影后:

实现代码:
function scoreboardProjection(frame_offset) {
if (frame_offset == null) frame_offset = 0;
var canvas, proj;
var score_img_1,
score_img_2,
overlay,
board_canvas,
score_canvas_1,
score_canvas_2;
//下面这几行代码使用的是Backbone.js 的View
(http://documentcloud.github.com/backbone/#View).
var self = view.extend({
template:'
&',
name:'scoreboardProjection',
pageName: 'Bowling Scoreboard',
onInit:onInit
});
return self;
function onInit()
//首先加载图片。前三行的“media”来自media.js
(http://www.justafriend.ie/cdn/js/jv/media.js) 的Media对象。
score_img_1 = media.getImage('img/bowlingscore1.png');
score_img_2 = media.getImage('img/bowlingscore2.png');
overlay = media.getImage('img/bowlingscore_overlay.png');
var scale_down_to_blur = .75;
board_canvas=canvasUtil.create(Math.floor(800*scale_down_to_blur),
Math.floor(450 * scale_down_to_blur));
score_canvas_1 = canvasUtil.create(800, 450);
score_canvas_2 = canvasUtil.create(800, 450);
canvas = canvasUtil.create(10, 10);
//投影工作的代码来自
http://www.justafriend.ie/cdn/js/jv/projection.js
proj = projection(board_canvas, canvas, null, {
wireframe:false,
subdivisionLimit:3,
patchSize:32
});
}
//查看完整代码请访问
http://www.justafriend.ie/cdn/js/jv/scenes/scoreboardProjection.js
}
利用上述技术,就可实现无缝拼接的图像投影。
计分牌场景源代码:
www.justafriend.ie/cdn/js/jv/scenes/scoreboardProjection.js
想要了解更多关于HTML5 Canvas 开发的内容,请尝试这些链接:
选择 Canvas,还是 SVG :
msdn.microsoft.com/en-us/library/ie/gg193983(v=vs.85).aspx
如何 在Canvas上创建3D 图形:
msdn.microsoft.com/en-us/library/ie/hh535759(v=vs.85).aspx
用像素记录视频帧数
HTML5视频技术仍处于发展阶段,尽管人们做了大量工作来确保帧的准确度,但仍然没有到达完美的程度。因此我们需要使用一些巧妙的方法来保证它的准确度:
HTML5 MediaElement API提供了获取视频当前时间( currentTime , 精确到毫秒) 的 getter 方法,但视频并不总能渲染出当前帧的正确画面,尤其是当渲染工作和其他计算密集型的工作同时进行的时候。

为了解决这问题,我们利用16个黑/ 白像素点组合成16位二进制数(黑代表1, 白代表0),一个16 位的二进制数代表一个视频帧的帧数,并将每组像素点按照其帧数嵌入到对应的视频帧的图像中,这些像素点不会显示出来,我们只是利用它来提取图像帧数。这不是你在视频中看到的标准NTSC 扫描显示, 相反地, 它是手动创建并烧录进视频以保证正确同步的二进制数据。虽然看似简单, 但这个技术能够真正确保用户在交互过程中能看到正确的画面。如果没有该技术,视频无法正确同步,并导致重叠。
function getCurrentFrameFromTimecode() {
frame_canvas_ctx.drawImage(video, 961, 0, 1, 16, 0, 0, 1, 16);
var timeBitmap = frame_canvas_ctx.getImageData(0, 0, 1, 16);
var timeData = timeBitmap.data;
var frame = 0;
var value;
for (var i = timeData.length - 1; i >= 0; i -= 4) {
value = (timeData[i - 3] + timeData[i - 2]
+ timeData[i - 1]) > 125 ? 1 : 0;
if (Math.floor(i / 4) == 15) {
frame = value << Math.floor(i / 4);
} else {
frame |= value << Math.floor(i / 4);
}
}
current_frame_text = "Frame: "+frame;
return frame;
}
使用该源代码,有助于视频和互动元素保持同步。您可以在这里获得“帧码阅读器” 代码:
www.justafriend.ie/cdn/js/jv/frameCodeReader.js 。
为了性能 “ 打散” PNG
在视频中的舞蹈游戏部分,图形元素必须配合节拍,一旦被击中立即爆破形成超酷效果。至于爆破效果,我们将PNG sprites转化成canvas 图像数据,然后创建粒子系统,图中一个粒子就是一个像素。粒子系统是利用toxiclibs 的2D Vector 类开发而成。你可以从这里获得代码实例:
haptic-data.com/toxiclibsjs/。
在早期测试中,如果一次渲染太多粒子就会出现性能问题。最简单的解决方案是使用 Photoshop 为 sprites 增加透明度。这样, 当创建粒子系统时,仅为那些超过一定透明度阈值的像素创建粒子。通过快速淡化和销毁粒子,渲染性能就会大大提升。
您可以在此查看早期原型:
www.justafriend.ie/cdn/dev/proto13b.html。
Sequence和媒体加载
在整个体验中,用户的不同操作会导致不同结果,所以必须创建大量不同视频。媒体加载器需要让用户感觉不到视频间的切换。
最初我们尝试了在 “
割绳子” (
www.cuttherope.ie) ——
另一个 IE9 项目 —— 中使用的Popcorn.js 和Popcorn.sequence 模块,但是我们很快发现,这些框架对我们的项目来说有很多用不上的功能,而且无法提供sequence所需的精度。首先就是,当使用非整型的起点/ 终点时序列就会被打破,定时回调函数也并非同步执行。最终,我们创建了一个在指定帧上的起点/ 终点的场景渲染系统。在每一帧上,所有被渲染的场景都对该帧是可见的。当HTML5视频在后台被渲染时,每个场景都可以被看作是它上面的一层。
每个场景都使用我们自制的媒体加载器,在启动时预加载所需资源。我们尝试了各种 HTML5媒体加载器,但没有找到能满足项目特定需求的。因此,我们创建了一个与RequireJS 配合使用的媒体加载器, 支持图像、视频和音频的加载。加载器支持onComplete 和onError回调函数,以及应用程序级别的状态通知。所有的资源请求都要进入队列等待,并且只能被一定数量的并发“ 线程” 处理,这就避免了在一些浏览器中常见的HTTP流水线问题,幸运的是,像Internet
Explorer 9 这样的高级浏览器没有这类问题。
有一个问题是,因为现代浏览器以渐进方式加载视频片段,所以HTML5视频剪辑不会完全被预加载进来。通常使用Ajax 风格的XHR 进行加载,以确保视频片段能够被缓存。一般来讲,只有主视频是以流的方式进行传输,用户的操作不会对其产生影响。如果对主视频进行预加载,那么加载时间将会变得超长。因此视频预加载和渐进加载的结合使用,是避免或缩短视频缓冲时间有效手段。
在此提供媒体资源加载器源代码:
www.justafriend.ie/cdn/js/jv/media.js。
拨打您的电话
视频体验中有一个隐藏环节,就是在片尾的时候,如果你用桌上的电话输入你的手机号,杰丝敏就会呼叫你的号码并留下6 条随机语音消息中的一条。电话拨叫功能是由Tropo API 实现的,它不仅很容易使用,更重要的是为参与体验的人带来惊喜和乐趣。
结束
感谢您阅读《Just a Friend 》开发背后的故事。了解更多高级浏览器最新技术,请查阅MSDN:
msdn.microsoft.com/ie 。原文地址:
www.justafriend.ie/dev 。
全文PDF文档下载:
Just a Friend 开发技术大揭秘册子_Vol.2.pdf标签:HTML5开发IE Web网页版