问题是背景,该用图片序列还是视频?一般经验告诉我们,像这种全景的东西,顺放倒放的,肯定都是用序列:flv倒放会卡。比如经典的IEKA网站用的就是图片序列。但是,这是过去的经验了。Barcinski & Jeanjean 告诉我们:jpg效率低,用 flv 才是高效,而且文件量小。How could it be?
OK,不知道大家是否有注意,在编码 flv 的时候可以设置关键帧距离。下图是AE里截的,Flash自带的编码器也可以设置。
一般我们都用自动方式,所以没太注意。但是如果将这个值设为1,那么就等于每一帧都编码为关键帧。由于播放器在解码非关键帧的时候需要在这一帧之前的关键帧数据,所以顺放和倒放的区别就在于:当前帧依赖的关键帧是否已经读取到内存中。那么如果每一帧都是关键帧,那顺放和倒放并没有区别!这样的设置无疑会增加 flv 的大小,但是还是比 jpg 序列小很多。而且在执行效率上,解码 flv 比 解码 jpg 速度快!感谢技术的进步,我们终于可以和臃肿的 jpg 序列说拜拜了!
过去还有个经验是:先载小图,再载大图盖上去。但是在这个网站里并没有这种做法,对此他们的解释是:无法忍受freeze。因为大图片的解码过程会让 Flash Player卡住,通常情况下,用户不会注意到这瞬间的停顿。但是这里场景中结合了Papervision3D制作的纸,具有动态的物理效果,这样的停顿 就会很明显。因此他们采用直接加载最终精度的flv的办法。
还记得IKEA网站中独特的加载方式吗?那是一种将序列重新组织的方法。可以让用户边下载边体验,没加载到的部分是过不去的。Barcinski & Jeanjean 面临同样的难题:即便用了flv压缩,主文件还是有16m之大。他们想了个天才的解决方法,在这篇文章里他们画了一个圆饼图表述了他们的思路。我总结一下:首先是在这个网站里达到平滑顺畅的全景体验需要144帧,如果我们隔一帧就抽掉一帧,就能省掉一半的文件量。此时播放的原始帧序号为“1,3,5,7,9,11,...”。如果我们再重复一次上一步的抽帧操作,那就只剩1/4的文件量了,已经降到的3M左右可以接受的范围。经过两次抽帧的文件只剩下36帧,此时播放的原始帧序号为“1,5,9,13,...”。抽帧后的视频仍然是一个完整的全景循环,只是不够平滑而已。
方法出来了:我们先提供经过抽帧两次的视频,用户加载完这个文件已经可以正常的浏览网站。然后在后台继续加载第二次操作中抽去的那部分,当这个文件加载结束后,就已经还原了1/2的帧数。最后再把剩下的1/2——也就是所有的偶数帧组成的视频文件加载进来。
非常酷的解决思路!我们团队立即给奔驰S网站重新开发了这部分功能。
要实现它需要两步工作:一是制作出三个抽过帧的视频文件,二是开发一个播放逻辑。
首先在AE中制作抽帧,手动操作显然不现实,我们的全景循环有300多帧!于是我找到了一个用Expression实现的办法。其实也很简单,用Time Remap重新映射就可以了,对应的表达式如下:
- 视频文件1 : time*4
- 视频文件2 : time*4+0.1
- 视频文件3 : time*2+0.05
由于time的单位是秒,我没找到将秒转换成帧数的方法。所以有了+0.1,+0.05这样奇怪的小数,其实换算过来就是+2帧和+1帧。表达式写好以后,要是不确定的话,拖动时间条看看重新计算过的时间码是否正确就可以了。
接下来讲播放部分,最核心的是开发一个程序使得主时间轴的帧序号映射到三个视频文件中的对应帧。我们用set1_mc,set2_mc,set3_mc分别去加载三段视频。实现的代码如下:

//判断当前帧对应哪一个视频文件,和对应哪一帧
if (n%2) {
//奇数帧分散在前两个文件中
if (n%4 == 1) {
currentSet = set1_mc;
setFrame = (n+3)/4;
} else {
currentSet = set2_mc;
setFrame = (n+1)/4;
}
} else {
//偶数帧
currentSet = set3_mc;
setFrame = n/2;
}
//如果对应的视频文件已经加载完成...
if (currentSet.ready) {
//其余的文件隐藏
set1_mc._visible = false;
set2_mc._visible = false;
set3_mc._visible = false;
currentSet.video.gotoAndStop(setFrame);
currentSet._visible = true;
}
最后为大家准备了这个网站的脱机版,有兴趣的自行下载研究下吧。感谢Barcinsk & Jeanjean和其他无私分享知识的人们,是他们让这个网络变得更加美好:)
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 如何编写易于单元测试的代码
· 10年+ .NET Coder 心语,封装的思维:从隐藏、稳定开始理解其本质意义
· .NET Core 中如何实现缓存的预热?
· 从 HTTP 原因短语缺失研究 HTTP/2 和 HTTP/3 的设计差异
· AI与.NET技术实操系列:向量存储与相似性搜索在 .NET 中的实现
· 地球OL攻略 —— 某应届生求职总结
· 周边上新:园子的第一款马克杯温暖上架
· Open-Sora 2.0 重磅开源!
· .NET周刊【3月第1期 2025-03-02】
· [AI/GPT/综述] AI Agent的设计模式综述