65.9K
CodeProject 正在变化。 阅读更多。
Home

Jasmine Villegas互动HTML5音乐视频幕后花絮

starIconstarIconstarIconstarIconstarIcon

5.00/5 (1投票)

2013年2月7日

CPOL

8分钟阅读

viewsIcon

18624

Jasmine Villegas互动HTML5音乐视频幕后花絮

30 天开发一个 Windows 8 应用

音乐视频正在不断发展。曾经在 MTV 和 VH1 等频道占据主导地位的音乐视频模式,如今正被网络上源源不断发布的音乐视频所淹没。与电视等传统媒体不同,电视上的音乐视频是一个接一个地播放,而网络上的音乐视频则在争夺观众的注意力。那么,艺术家们,尤其是像 Jasmine Villegas 这样冉冉升起的新星,如何才能在喧嚣中脱颖而出,引人注目呢?

这是 Jasmine 和 Internet Explorer 团队试图解决的挑战。她的愿景是创造一种互动体验,以实现两个目标:1)吸引现有粉丝群,2)帮助她吸引新粉丝。为了正确完成这项任务,微软请来了 HTML5 专家,来自创意机构 Digital KitchenBradley and Montgomery,共同打造了 justafriend.ie。其结果不仅达到了 Jasmine 的目标,还展示了 HTML5 在网络上的强大功能。

整个音乐视频中穿插着大量的技术亮点,为视频注入了生命力。无论您是 Jasmine Villegas 的铁杆粉丝,还是只想了解更多关于 HTML5 的信息,我们都希望为您提供更多关于我们如何在线打造《Just A Friend》的信息。

使用 HTML5 标准设置网站

我们开始项目时,首先确保现代浏览器将识别并使用 HTML5 视频而不是插件。这很容易

<!DOCTYPE html>

将 Facebook 数据连接到您的 Web 应用

Facebook Connect 是 JustaFriend.ie 的一个重要组成部分,因为它真正地将用户带入体验。当您首次开始观看视频时,会要求用户连接到他们的 Facebook 帐户。这使我们能够从他们的 FB 帐户中提取图像并直接投影到视频中,还可以让我们在上下文中显示他们的姓名。因此,Jasmine 的粉丝可以感觉自己是视频的一部分,与他们喜爱的歌手一起。

在 HTML5 画布和视频上投影图像

HTML5 中的图像投影并不是一个新概念。事实上,该项目的大部分早期工作都是基于 Steven Wittens 在 http://acko.net/files/projective-canvas/index.html 上提供的方案。但在 IE9 中,画布投影的性能测试结果远超其他现代浏览器,因此必须修改代码以实现跨平台兼容。

一个很好的例子是用于显示从 Facebook Connect 中提取的用户姓名的记分牌。为了实现这一点,投影代码被更新为使用画布缓冲区而不是图像。这使得可以在投影之前将各种元素合成到缓冲区中。从一个空白的记分牌 PNG 开始,使用画布绘图 API 绘制了姓名。另一张 PNG 图像叠加在顶部,以提供轻微的眩光效果。通过将此投影与视频帧匹配,而不是仅仅一个静止的平面,整个作品得到了进一步的提升。

PNG 图层的叠加也被用于将用户的 Facebook 照片投影到视频开头的 Jasmine 的卧室墙上。PNG 图层提供了阴影效果,使照片能与墙上现有的照片无缝融合。这项技术在视频结尾 Jasmine 桌子上的照片上也再次使用。这是最终的体验以及为其提供动力的代码。

以前

操作后

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;
    
    // View in the following line is a Backbone.js (http://documentcloud.github.com/backbone/#View) view.
    var self = view.extend({
        template:'<div class="scene HD" id="scoreboard_projection"></div>&',
        name:'scoreboardProjection',
        pageName: 'Bowling Scoreboard',
        onInit:onInit
    });
 
    return self;
 
    function onInit() {
        // First we load our images. "media" on the following lines are Media objects from http://www.justafriend.ie/cdn/js/jv/media.js
        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);
        
        // projection is part of the canvas projection library at http://www.justafriend.ie/cdn/js/jv/projection.js
        proj = projection(board_canvas, canvas, null, {
            wireframe:false,
            subdivisionLimit:3,
            patchSize:32
        });
 
    }

  // There's more to this, and you can find the full code at http://www.justafriend.ie/cdn/js/jv/scenes/scoreboardProjection.js       
}

查看原始 scoreboardProjection.example.js 此 GistGitHub 提供。

使用上述技术和此代码源,可以实现无缝融入您项目的图像投影。

记分牌场景的源代码在此:http://www.justafriend.ie/cdn/js/jv/scenes/scoreboardProjection.js

要了解更多关于使用 HTML5 画布进行开发的信息,请尝试以下链接

通过像素提取视频帧

HTML5 视频仍是一项不断发展的技术。尽管已经做了大量工作来确保帧的准确性,但它仍然不完美。所以我们不得不借助一些帮助来解决它

HTML5 MediaElement API 提供了一个 'currentTime' 的 getter,它声称可以精确到毫秒,但这并不总是与屏幕上渲染的当前帧相匹配。当在视频渲染时进行计算量大的处理时,这尤其是一个问题。

为了解决这个问题,我们从视频中提取了帧号,通过视频中嵌入的黑白像素来获取,这些像素放置在屏幕外。这不是您在视频中看到的标准 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;
}

查看原始 currentFrameFromTimecode.example.js 此 GistGitHub 提供。

使用此代码源来帮助同步视频和交互元素。您可以在此处获取“帧代码读取器”模块的源代码
http://www.justafriend.ie/cdn/js/jv/frameCodeReader.js

为了性能而放大 PNG

在舞蹈游戏中,图形元素需要与节拍模式匹配,并在击中挡板时爆炸,以产生酷炫的效果。对于爆炸效果,PNG 精灵被转换为画布图像数据,然后创建了一个粒子系统,其中每个粒子代表图像中的一个像素。粒子系统非常基础,是使用 toxiclibs 的 Javascript 移植版中的 2D Vector 类开发的。

在此处获取代码示例:http://haptic-data.com/toxiclibsjs/

在早期测试中,一次渲染过多粒子时存在性能问题。最简单的解决方案是在 Photoshop 中创建带有大量透明度的精灵。然后,当创建粒子系统时,仅为那些不透明度超过特定阈值的像素创建粒子。通过快速淡出和销毁粒子,获得了更好的性能。

早期原型可以在这里看到:http://www.justafriend.ie/cdn/dev/proto13b.html

序列和媒体加载

在整个体验过程中,根据用户互动会有不同的结果。由于这些不同的结果,不得不创建许多不同的视频。因此,媒体加载器需要以一种使过渡看起来无缝的方式工作。

最初使用了 Popcorn.js 和在其他 IE9 项目中用于 Cut The RopePopcorn.sequence 模块。然而,很快就发现该框架对于此项目来说过于复杂,并且无法提供所需的精确度来进行排序。首先,在使用非整数的入点和出点时,序列会中断,并且时间回调实际上不同步。

最终,创建了一个具有帧特定入点和出点的场景系统。在每一帧,都会渲染所有应该可见的场景。每个场景都可以被视为一个叠加层,因为 HTML5 视频在后台渲染。

每个场景都使用自定义媒体加载器在启动时预加载所需的资源。有各种 HTML5 的媒体加载器,但找不到一个能满足项目特定需求的。因此,创建了一个自定义媒体加载器,它与 RequireJS 一起工作,并支持图像、视频和音频。该加载器支持 onCompleteonError 回调以及应用程序级别的状态通知。所有请求都排队并限制在一定数量的并发“线程”内,以避免某些浏览器中最常见的 HTTP 管道问题,幸运的是,这对于 Internet Explorer 9 等现代浏览器来说不是问题。

一个问题是,由于现代浏览器自然地以渐进方式加载视频片段的方式,HTML5 视频剪辑无法完全预加载。为了确保视频被缓存,它们通过 Ajax 风格的 XHR 加载。主视频是唯一允许以传统方式流式传输的视频。主视频是根据用户交互而不改变的唯一元素。如果它被预加载,那么在体验开始时的初始加载时间将非常长。通过结合预加载和渐进加载视频元素,消除了传统的缓冲时间。

调整此代码源以加载您的资源,使它们无缝过渡。

媒体加载器的源代码在此:http://www.justafriend.ie/cdn/js/jv/media.js

拨打您的号码

体验中隐藏的一个元素是 Tropo API 的使用,它允许您在视频结尾桌上的手机上输入您的电话号码。这样做,Jasmine 会拨打您拨的号码并留下 6 条随机语音留言中的一条。该 API 易于实现,并为经历此过程的个人增添了一层惊喜和愉悦。

总结

感谢阅读 Jasmine Villegas 的《Just A Friend》幕后开发者拆解。

要了解更多关于为现代浏览器开发跨浏览器代码的信息,请从 MSDN 开始:http://msdn.microsoft.com/ie

HTML5 视频资源

© . All rights reserved.