iPhone5官网剖析 看苹果公司如何用设计元素

摘要:众所周知,iPhone5已于9月13日发布,其性能、系统、应用以及硬件都被剖析得差不多了,但有多少人注意到了iPhone5网站的设计和实现?实际上Apple每次发布新产品都会用Web实现其特殊性能,本文既是对iPhone5网站上特殊效果的实现分析。

大家都知道iPhone5在9月12号发布了,新产品怎么会少了新网站呢?每次Apple发布新功能总会在网站上做一个Web实现,比如iPhone4的视网膜放大镜、会旋转的电池寿命时钟、new iPad奇怪的滚动效果(ugh)等等。新的iPhone5也一样,网站上同样展示了其新特性,但原理比看起来要更复杂一些:

网页上的iPhone5会在设备解锁后自动播放视频,但奇怪的是:页面上并没有<video>元素,只有<canvas>。即使你使用Chrome检查Web Inspector的“Network”标签,也同样不可能找得到任何视频,但会看到这样奇怪的JPEG图片:

为什么Apple会做如此荒谬的事?它既参与了h.262标准的制定,也开发了Safari,没有理由不知道这样的“捷径”:使用<video>元素。

这是因为,<video>元素在iPhone下必须全屏播放,这就毁了Apple播放内联视频的原意了;而在桌面端,Apple的网站需要兼容所有主流浏览器,但Firefox和Opera不支持h.264(同样,Apple也不可能后退一步使用开源的WebM或者Theora)。

你可以看看这个Retina Macbook Pro“特性”页面——2秒钟的展示视频却需要5M的JPEG图片(并使用了大量独立的HTTP请求)。而iPhone5的网页,Apple使用了一种新方法来避免为每个frame单独请求图片。新的动画仅需要很少的HTTP请求以及1M流量,相比于旧的解决方案性能得到明显提升。

下面是编码后的“视频文件”:

http://www.apple.com/iphone/design/images/unlock/unlock_manifest.jsonhttp://www.apple.com/iphone/design/images/unlock/unlock_keyframe.jpghttp://www.apple.com/iphone/design/images/unlock/unlock_001.jpghttp://www.apple.com/iphone/design/images/unlock/unlock_002.jpghttp://www.apple.com/iphone/design/images/unlock/unlock_endframe.jpg

该视频的逻辑实现依赖于ac_flow.js,我建议你在Chrome Web Inspector中打开“Pretty Print”(点击左下角的“{}”)仔细阅读。我不打算在这里做详细的代码解释,所以还是建议你仔细看看代码。

Apple使用的视频压缩方法仅仅会加载frame中更新了的部分:“unlock_001.jpg”和 “unlock_002.jpg”中存储了图片的更新部分,“unlock_manifest.json”文件描述更新部分该如何放置。下面是“unlock_manifest.json”的一个片段:

JPEG文件使用8×8的宏块来编码,所以Apple明智地使用了相同的大小(json里的“blockSize:8”),这还避免了无关的图片误用相同块的问题。(JPEG图片使用4:4:4的色度取样,所以其色度宏块也应该是8×8。)

“imagesRequired”表明,在动画开始时需要加载两张图片——“unlock_001.jpg”和 “unlock_002.jpg”,这两张图片被当作是连续的8×8块流从左向右、自上而下地来处理。(如果我在下面提到JPEG流,指的就是这个。)

这些“frame”看起来就像是base64,但实际上数据也按照base64偏移编码了。换句话说,这里的1Byte实际上是6bit。

下面是Apple解码base64的代码的片段:

每个frame由5字节指令构成,指令的前3字节编码位置来更新<canvas>的相应部分。后2字节则包含需要读取的块数。例如:第一个frame的第一个指令“AAxAC”意味着:从JPEG流中读取2块(“AC”,记住——这是base64编码后的字节),并在<canvas>位置49(“AAx”)进行绘制。

注意:这里并没有从JPEG流中重复利用JPEG块的功能,JPEG块只会在每次请求的时候使用一次,这会引起JPEG潜在的冗余问题,但也保证了manifest 更小,格式也更简单。

除了icons,上图中“最长的”frame就是动画化了的部分,这导致了JPEG流中块复制间的空白。以上就是Apple将视频编码为JPEG图片的原理,但不仅限于视频。

Apple还使用了该压缩方法重新实现了QTVR(虚拟现实)——当你拖动上图中的耳机时,你实际上是在播放耳机转动的视频,这个视频使用的也是相同的JS/JSON/<canvas>压缩技术。

效果怎么样?似乎不怎么样……

出什么问题了?<canvas> API (“drawImage”)所花时间甚少,大部分时间都浪费在解码frame以及apply diff上了。

结果证明,在这样的视频中寻找功能特别费时间,因为解码一个单独的视频frame,首先需要解码每个单独的frame——毕竟这个格式的目标只是来解码修改了的部分,这意味着现在我们需要计算没有计算过的位置。

为了缓解这一问题,Apple提供了向前/向后两种视频播放模式(否则,反向旋转耳机会非常慢)。不幸的是,这却直接造成文件大小加倍的问题,但没有解决在用户快速拖拽耳机时“跳帧”的问题。

苹果下一步会怎么做?使用更适合操作二进制文件的东西代替JSON?

似乎Apple正在尝试在新版本中将manifest编码在PNG图片,以此代替当前JSON里的base64字符串。并且因为PNG格式是无损的,而且<canvas>对其支持得非常好,所以很适合编码很多字节的数据,即使它并不是个图片。我对使用PNG格式后对性能性能的影响以及动画文件大小的改变非常感兴趣。

原文链接:iPhone 5 website teardown: How Apple compresses video using JPEG, JSON, and <canvas>

Published by

风君子

独自遨游何稽首 揭天掀地慰生平

发表回复

您的电子邮箱地址不会被公开。 必填项已用 * 标注