全景展示绕不开 Krpano。最近项目里来了个新需求:把现场拍摄的 360° 视频接入到已有的漫游站点里,用户可以在浏览器里拖拽视角、切换场景、看视频里的热点介绍。折腾完这圈,踩了不少坑,这篇随笔趁热记录下来。
市面上的思路大致两条:用 three.js 这类前端 3D 库自己写播放器,或者用 krpano 这种成熟的全景方案。我选择了后者,原因后面细说。这篇文章主要面向已经在用 krpano、但还没搞过视频的人;也适合那些视频接入后遇到编码、多分辨率、热点同步问题的同行。内容按 krpano 1.20 系列的用法来讲,老版本个别属性名会有一点差异,查一下对应版本文档就行。
1. 全景视频,到底解决什么问题
先泼一盆冷水:不是所有场景都该上全景视频。静态的空间展示,全景图更合适——文件小、加载快、随便一台旧手机都能流畅看。但如果你要表达的是过程、动作、光线变化、人群流动,全景图就废了。
全景视频的价值在于多了一个时间维度。我这次接的需求里,有几个典型场景:
- 售楼处的周边环境预览。窗外不是一张静态效果图,而是傍晚时分的车流、江面的波光,这些静止画面传递不了。
- 工厂车间关键工位的巡检记录。机器在转、机械臂在动,客户想看的是真实运行状态,不是一张摆拍的 360° 照片。
- 活动全程回放。舞台灯光、现场人群、主持人走位,静态照片只能抓到一瞬间。
判断标准很简单:画面里有“必须动起来”的内容,就上视频;没有,就老老实实用图。全景视频的成本比全景图高不少,素材体积大、编码讲究、播放性能敏感,这些问题后面都会碰到。提前想清楚场景边界,能省下大量返工时间。
1.1 全景图与全景视频的应用边界
全景图和全景视频本质上都是“贴在一个球体内部的实时图像”。区别在于,全景图是单帧,全景视频是连续帧序列。这个区别带来三个连锁问题:体积、解码、交互。
体积方面,一张 4K 全景图压缩后大概几 MB,一段 4K 全景视频哪怕压缩成 H.264,几秒钟就超过一张图的体积。解码方面,全景视频播放时,浏览器要把视频帧实时映射到球面上,再配合鼠标或陀螺仪旋转,对 GPU 和 CPU 的压力远高于普通视频。交互方面,全景图加热点是静态坐标,点哪跳哪;全景视频里热点要么跟着时间轴走,要么固定在屏幕上,否则很容易和画面内容错位。
所以我的经验是:能用全景图表达的,坚决不硬塞视频。只有用户确实需要“看到动态过程”时,才引入全景视频。比如给某个展厅做线上展示,展厅本身就是静止建筑,全景图足够;但展厅里如果有一块正在播放产品宣传的屏幕,或者一台上电运行的设备,那这部分就值得单独用视频场景来表达。
1.2 为什么是 Krpano,而不是自己用 WebGL 写
前端做全景视频,自己写也不是不行。用 three.js 加 videoTexture,把视频贴到球体内部,鼠标拖拽、惯性、陀螺仪、热点叠加,全部手写,至少两周起步,而且各种兼容性问题会占掉大量时间。Krpano 的优势在于,这些能力已经封装成 XML 标签,你只需要关心配置和交互逻辑。
我用 Krpano 还有个更实际的原因:漫游项目往往不只一个页面。全景图场景、全景视频场景、普通视频弹窗、场景切换、地图导航,这些需要混在一个项目里。Krpano 的场景机制天然支持图片和视频混排,而且热点、自动旋转、视角过渡、皮肤控制条这些都是一体的。用自研方案,做单个视频播放器不难,难的是把视频、图片、热点、场景串成一套完整的参观动线。
当然,Krpano 是商业产品,商用要确认授权。个人学习用免费版也能跑起来,但发布到商业项目之前,记得把授权这件事纳入成本,这是每个正规项目都要核对的。我本地的测试环境一直用的是官方免费许可,真正交付时再按项目购买授权,流程上比较稳妥。
2. 视频素材与编码:一半的坑都在这里
全景视频接入后出现黑屏、卡顿、音画不同步,多半不是 Krpano 的问题,而是素材编码不符合浏览器要求。这个板块是重灾区,值得单独写。
2.1 拍摄与拼接:先拿到 2:1 的等距柱状视频
Krpano 直接吃等距柱状投影(equirectangular)格式。你可以把它想象成一张世界地图:图片长宽比固定为 2:1,图片中间是正前方,上下边缘分别对应头顶和脚下,左右边缘缝合起来是正后方。全景相机如果支持直出,一般会输出这种格式;如果拍的是多段鱼眼视频,需要先用拼接软件做全景合成,再导出 2:1 的视频。
这里我踩过一个大坑:某次拿到的素材是“四路鱼眼视频”而不是拼接好的全景视频,我图省事直接拖进 Krpano,结果画面里出现四个圆形鱼眼画面,完全没法看。原因很简单,Krpano 默认认为视频已经是等距柱状投影,不会帮你去鱼眼化。后来老老实实把四段视频拼接成全景后再导入,问题立刻解决。
素材分辨率方面,我建议桌面端至少准备 4K(3840x1920),移动端用 1080p(1920x960)做低档位。你别想着用 1080p 源头糊弄,全景视频要铺满整个视野,原始分辨率如果只有 1080p,放大到全屏之后糊得没法看,尤其是 VR 模式下,观感会非常差。
帧率建议 25fps 或 30fps。除非拍摄内容有明显的快速运动需要丝滑效果,否则别轻易上 60fps——体积翻倍,解码压力翻倍,但大部分用户看不出来差异。
2.2 转码参数怎么定,才不至于黑屏或卡顿
浏览器播放全景视频,兼容性最好的编码方案是 H.264 + MP4,音频用 AAC。H.265/HEVC 虽然压缩率更高,但浏览器支持不统一,很多安卓机不支持硬解,一量码率高一点就卡成幻灯片。所以我给客户交付的素材一律 H.264,不追求极致压缩比,追求稳定播放。
转码参数我一般这样定:
| 清晰度档位 | 分辨率 | H.264 Profile/Level | 参考码率 |
|---|---|---|---|
| 移动端标清 | 1920x960 | High / 4.0 | 4-8 Mbps |
| 桌面高清 | 3840x1920 | High / 5.1 | 15-30 Mbps |
| 高码率旗舰 | 3840x1920 | High / 5.2 | 30-50 Mbps |
立体声是 50,但你最终定的码率要看素材动态程度。室内谈话场景可以调低,户外快速移动镜头必须给足。一个经验是:码率宁可高一点也不要低,全景视频一旦出现块状压缩模糊,用户旋转视角时会非常明显,比普通视频的劣化刺眼得多。
下面这条 ffmpeg 命令是我常用的 4K 档位转码模板:
ffmpeg -i input_equirect.mov \ -vf "scale=3840:1920" \ -c:v libx264 -preset medium -tune film \ -profile:v high -level 5.2 \ -pix_fmt yuv420p -r 30 \ -g 60 -keyint_min 60 -sc_threshold 0 \ -c:a aac -b:a 192k -ac 2 -ar 48000 \ -movflags +faststart \ output_4k.mp4拆开解释一下关键点:
-pix_fmt yuv420p:强制 8bit 4:2:0 采样,这是浏览器兼容性最好的像素格式。-r 30:固定帧率。如果源素材是可变帧率(VFR),播放到某些片段时音画会逐渐不同步,这一步直接强制为 CFR。-g 60:每 60 帧一个关键帧,也就是 2 秒一个关键帧,方便用户拖进度条时快速定位。-sc_threshold 0:禁止编码器因为场景切换而打乱关键帧节奏,防止 seek 时响应变慢。-movflags +faststart:把 moov 元数据移到文件头部,网页播放时不用等整个文件下载完就能开始解析。
这条命令还有一个好处:压缩出来的文件拖进 Krpano 后,即使不加多分辨率方案,普通桌面浏览器跑 4K 也能流畅播放。前提是显卡支持硬解,后面在排查章节会展开讲。
2.3 帧率、关键帧与音频同步
帧率问题我专门拎出来说,是因为全景视频对“帧率一致性”比普通视频敏感。普通视频短暂掉帧,人眼可能注意不到;全景视频一旦掉帧,旋转视角时会出现画面“拉扯感”,很容易头晕。
所以转码时一定要确认输出固定帧率。终端有可能给你的是一个带 B 帧、VFR、甚至交错扫描的素材,这些都要在转码阶段处理掉。B 帧本身问题不大,交给解码器处理就行,但 VFR 必须转成 CFR。
音频方面,AAC 双声道 192kbps 对于全景视频足够。全景声(Ambisonics)在浏览器端的支持还比较混乱,如果客户没明确要求,别主动上。另一个容易忽略的点:音频和视频要同步封装在同一条 MP4 里,Krpano 播放视频时默认按封装时间轴走,如果音视频轨道各自开头时间戳不一致,会出现“画面比声音晚半秒”这种怪问题。
要快速检查素材信息,可以用 ffprobe:
ffprobe -v error -select_streams v:0 -show_entries stream=codec_name,profile,level,pix_fmt,r_frame_rate -of default=noprint_wrappers=1 output_4k.mp43. 接入 Krpano:核心 XML 配置拆解
素材准备好之后,真正的技术活是写 XML 配置。Krpano 的玩法是:XML 定义项目结构,JS 负责运行时交互,我这次只讲 XML 部分。
3.1 最简视频配置:video 标签与文件目录
先看目录结构。我习惯这样组织项目文件:
project/ tour.xml video/ preview.jpg video_1080.mp4 video_4k.mp4 skin/ ...所有视频文件单独放一个目录,预览图单独放一个文件,避免和图片素材混在一起。路径全部用相对路径,不要写绝对路径或者带盘符的路径,后面迁移到服务器或者打包给别人时不会出问题。
最简的 video 配置是这样的:
<krpano version="1.20"> <include url="skin/vtour.xml" /> <video autostart="false" loop="true" posterurl="video/preview.jpg" volume="100" > <source type="video/mp4" src="video/video_1080.mp4" /> <source type="video/mp4" src="video/video_4k.mp4" /> </video> <view hlookat="0" vlookat="0" fov="100" /> </krpano>posterurl是视频加载时的预览图,很重要。没有它,视频流还没就绪时浏览器会显示一片黑,用户会以为页面坏了。预览图用静态全景图的第一帧导出就行,但要压到几百 KB 以内。
autostart在桌面浏览器里设置为 true 通常有效,但在 iOS Safari 和部分安卓浏览器里,自动播放会被浏览器策略拦截。为了保险,我一般设置成 false,让用户点击播放按钮或场景时再触发播放,这样最稳妥。
多 source 标签的意义:Krpano 会自行判断当前设备能流畅播放哪个档位,优先选最优的那一个。如果只写一个高分辨率,移动端大概率卡死;如果只写一个低分辨率,桌面端画质吃亏。一个项目至少准备两档,是多花不了多少时间的。
3.2 初始化视角与 VR 模式
全景视频的初始视角用view标签控制。hlookat是水平视角角度,0 度代表正前方;vlookat是垂直视角角度,0 度代表水平线;fov是视野范围,数值越大看到的范围越广,越小越接近望远镜效果。
我推荐视频场景的初始视角设置在 0/0,视野在 100 到 110 之间。原因很简单:全景视频不同于全景图可以慢慢旋转观察,它有自己的叙事时间线,如果一上来就歪着头看,用户很容易错过重点内容。让用户先看到画面主体,再自己旋转探索,体验会好很多。
VR 模式是 Krpano 自带的强项。只要页面运行在支持 WebXR 的浏览器里,并且部署在 HTTPS 环境下,就能直接进入 VR 模式。注意,陀螺仪和 VR 相关 API 很多浏览器要求 HTTPS,否则会被拦截,纯本地打开文件一般只能鼠标拖拽,手机上的陀螺仪大概率不生效。开发阶段可以用本地 HTTP 服务配合手机调试,正式发布一定走 HTTPS。
这些不是 Krpano 的 bug,而是浏览器安全策略。遇到手机陀螺仪不工作,先检查部署环境,别上来就怀疑配置写错了。
3.3 控制条与自定义按钮
如果你用的是 Krpano 自带的 vtourskin,启用了视频之后,皮肤会自动出现一个视频控制条,播放/暂停/进度条/音量基本都全的。我很少再用自带皮肤,客户项目一般要定制 UI,所以我会自己挂按钮。
自己写控制按钮的核心是调用 Krpano 内置的 videointerface 系列动作:
<plugin name="playpause" url="btn_play.png" align="bottom" edge="bottom" y="40" onclick="toggleplay()" /> <action name="toggleplay"> videointerface_toggleplay(); </action>videointerface_toggleplay()会在播放和暂停之间切换。类似的接口还有videointerface_pause()、videointerface_stop()、videointerface_play(),以及用于跳转进度的videointerface_seek(seconds)。不同版本里部分接口命名会有差异,写的时候对着你那版 Krpano 的 doc 文件夹确认一下,不要照抄我这里的名字就完事。
音量调节也是一样,用setvolume相关接口。我建议把默认音量控制在 70% 左右。全景视频音量开满会很突兀,尤其展厅里突然“轰”一声,客户体验非常差。加一个静音按钮比调音量按钮更实用,很多现场用户只想安静地看画面。
4. 多分辨率与流媒体:让网差的人也能看
一个 4K 全景 MP4 可能上百 MB,用户网速不行时,加载过程就像一个黑洞。多分辨率和流媒体方案就是用来解决这个问题的。
4.1 为什么一个 MP4 不够用
单 MP4 的问题有三个:
- 加载慢:浏览器必须下载足够的数据才能开始播放,4K 文件体积大,首帧等待时间长。
- 内存爆炸:Krpano 解码全景视频时要同时处理多帧缓冲,高分辨率视频在低端手机上极容易卡顿甚至崩溃。
- 拖动进度条慢:如果关键帧分布不好,用户拖进度条要等几秒才能播,体验很割裂。
所以我的原则是:真正交付的项目,至少准备两个清晰度档位。移动端 1080p,桌面端 4K,由 Krpano 根据设备自动选择。如果客户对清晰度有执念,再额外加一个 2K 中间档位,尽量不搞一档走天下。
4.2 用 ffmpeg 切出 HLS 素材
Krpano 的多 source 支持直接加载 HLS(HTTP Live Streaming)流。HLS 的好处是能把视频切成一段一段的小切片,播放器边下边播,拖动进度条时只加载附近片段,大幅节省流量。
用 ffmpeg 切 HLS 的命令大致如下:
ffmpeg -i video_source.mp4 \ -vf "scale=1920:960" \ -c:v libx264 -b:v 8M \ -preset medium \ -g 60 -keyint_min 60 -sc_threshold 0 \ -hls_time 6 \ -hls_playlist_type vod \ -hls_segment_filename "segments/1080p_%04d.ts" \ index_1080p.m3u8几个关键参数:
-hls_time 6:每个切片 6 秒。切片太短会增加请求次数;太长则拖动进度条的粒度不够细。6 秒是比较均衡的值。-hls_playlist_type vod:明确这是点播流,不是直播,播放器可以预加载更多数据。-hls_segment_filename:切片文件命名规则,后续维护方便。
如果要做多档位,就把scale和-b:v换成对应分辨率,跑出多套 m3u8 + ts 文件,然后分别放目录。切完之后记得检查一下 m3u8 里的切片路径是不是相对路径,如果是绝对路径或者带本地盘符,部署到服务器上也会挂。
4.3 在 XML 里声明多档位
HLS 素材接入 XML 时,把 source 的 type 改成application/x-mpegURL:
<video autostart="false" loop="false" posterurl="video/preview.jpg"> <source type="application/x-mpegURL" src="video/index_1080p.m3u8" /> <source type="application/x-mpegURL" src="video/index_4k.m3u8" /> </video>Krpano 拿到多档 HLS 后,会结合设备的解码能力和网络条件选择最合适的档位。注意,它不是“永远选最高码率”,网速不够时会自动切低档位,这一点实测下来比较聪明。
这里有个特别容易踩的坑:HLS 切片文件分布在另一个域名(比如 CDN)时,必须配置 CORS 跨域头,否则浏览器会直接拦截请求,Krpano 表现就是视频黑屏但控件又能点。我在本地联调时遇到过一次,排查了半天,最后发现是服务器少了Access-Control-Allow-Origin响应头,加上之后就正常了。如果你的视频和页面在同一个域名下,一般不会触发这个问题,这也是我建议项目文件尽量同域部署的原因。
如果你觉得 HLS 切片太麻烦,也可以不做,直接放两个普通 MP4 让 Krpano 多 source 选择。代价是拖动进度条时体验稍差,但实现成本最低。我的经验是:小项目用双 MP4,大项目或客户明确要求“打开快、拖动快”时,再上 HLS。
5. 热点交互:让视频能“点”
全景视频如果只是“能播放能旋转”,那它还是一个视频播放器。真正把视频变成“漫游产品”,靠的是热点交互。我这次做了三类热点,分别解决不同问题。
5.1 常规热点:点击跳转场景
第一种是固定的球面坐标热点。所谓球面坐标,是指热点固定在当前视角的某个经纬度上,视频画面转动时,它跟着画面一起转动。Krpano 中定义方式如下:
<hotspot name="nextscene" url="arrow.png" ath="30" atv="-10" distorted="false" onclick="loadscene(scene_2, null, MERGE, BLEND(0.5));" />ath是水平角度,atv是垂直角度。比如 30 度向右、-10 度向下,热点就悬浮在那个位置。点击之后通过loadscene切换到另一个场景,实现从视频场景跳转到展厅全景图场景,或者反过来。
这类热点适合“换场景”操作,比如视频到了一个时间节点,屏幕右下方出现“进入下一站”的箭头。但要注意,Krpano 的全景热点是绑在视角上的,不是绑在视频画面里的某个物体上。视频画面本身在播放中不断变化,一个门把手刚才在画面左侧,下一秒就跑到画面右侧了,热点并不会跟着物体移动。
因为没有外部位置跟踪数据,前端无法知道视频每一帧里物体对应的球面坐标。所以全景视频里的热点绝大多数用“屏幕固定位置”或者“按时间显隐”来做,而不是试图钉在画面里的某个真实物体上。这个认知能帮你省掉很多无效折腾。
5.2 按时间轴控制热点显隐
第二种是时间轴热点,这是全景视频最实用的交互方式。视频播放到某个时间点时,显示对应热点;过了这个时间点,自动隐藏。实现思路是定时器循环刷新 + 读取当前播放时间。
大致结构如下:
<events onload="setinterval(refresh_video_hotspots, 250);" /> <action name="refresh_video_hotspots"> if(videotime GT 5 AND videotime LT 15, set(hotspot_product.visible, true); set(hotspot_product.visible, false); ); </action>videotime是当前播放时间,单位秒。上述动作的意思是:视频播到第 5 秒到第 15 秒之间时,显示hotspot_product这个热点,其他时间隐藏。当用户点击热点时,可以用loadscene跳转,也可以弹出一个图片说明,甚至可以切换视角聚焦到某个方向。
这段逻辑如果只是写个示意,逻辑并不复杂,但实际项目里要注意几个细节:
- 时间判断不是“点触发”,而是“区间触发”。用户可能会从第 20 秒拖回第 10 秒,如果你只在特定时间点设置一次显隐,拖回进度条时状态不会刷新。所以每次定时器刷新都要根据当前时间重新计算所有热点的显隐状态。
- 定时器间隔不要太短,250ms 足够,太频繁会导致 CPU 徒增。
- 热点显隐最好配合一点透明度动画,否则突然出现会打断观看,让用户出戏。
时间轴热点很适合做解说型内容:视频讲到某个设备时,画面边缘浮出“设备参数”按钮,点击查看详情。我这次给车间巡检项目就是这么用的,客户反馈很好。
5.3 播放进度埋点与统计
第三种不是用户能看见的,但对项目方很值钱:播放进度埋点。全景视频项目往往要写验收报告,用户到底看了哪些内容、看到百分之几关掉了,这些数据最容易被量化成交付成果。
埋点思路和解说热点类似,周期性地记录当前播放时间,然后传给后端接口。Krpano 里可以用js()动作调用页面里的 JavaScript 函数,把数据发出去。
简单示意:
<action name="refresh_progress"> if(videotime GT 30 AND videotime LT 31, js("reportProgress(30)"); ); </action>这里只会在视频播到 30 秒到 31 秒之间时上报一次“看到第 30 秒”,避免每 250ms 上报一次把后端打爆。实际项目里我一般采集几个百分比节点:播放开始、25%、50%、75%、100%,以及最后的跳转行为,足够了。
埋点要部署在 HTTPS 页面下,否则混合内容会被拦截。另外,后端接口要做简单的频率限制,防止用户反复拖动进度条产生大量垃圾请求。
6. 常见问题与排查技巧实录
这部分是我最想写给同行的,因为全景视频的坑非常隐蔽,出问题时第一反应经常是“Krpano 配置写错了”,但真正原因往往是素材、服务器或者浏览器策略。
6.1 高频问题速查表
| 现象 | 常见原因 | 处理办法 |
|---|---|---|
| 视频黑屏无画面 | 视频编码不是 H.264 或像素格式不是 yuv420p | 用 ffmpeg 重编码,强制 H.264 + Main/High Profile + yuv420p |
| 有画面没声音 | 音频编码或轨道参数不被浏览器支持 | 音频统一转 AAC,双声道 48kHz,不要用 AC-3 或 DTS |
| 手机端卡顿严重 | 视频分辨率太高或 H.265 无硬解 | 给移动端准备 1080p 档位,不要一台设备通吃 4K |
| iOS 自动播放被拦 | 浏览器策略限制自动播放 | 不要依赖 autostart,让用户点击后触发播放 |
| 视频拖进度条很慢 | 关键帧间隔太长或 HLS 切片粒度太大 | 每 2 秒一个关键帧,HLS 切片时长控制在 6 秒左右 |
| 热点显示但点不到 | 热点被其他元素遮挡或屏幕坐标出界 | 检查 zindex 排序,热点尺寸和 hitarea 也要设大一点 |
| 跨域加载失败 | 视频文件与页面不在同一域名,且没有 CORS 头 | 配置Access-Control-Allow-Origin,或者全部文件同域部署 |
| 视角一开始歪的 | 视频源素材的拼接中心不在正前方 | 调整 view 的 hlookat/vlookat,或重新导出等距柱状投影时设置中心点 |
这些问题的共性是:Krpano 本身是没错的,错在“喂给它的数据不对”。排查顺序我建议是:先 ffprobe 看素材编码参数,再确认服务器响应头,最后才怀疑 XML 配置。
6.2 移动端优化与真机测试
移动端是最容易翻车的环节。桌面浏览器解码能力普遍强,4K 全景视频都能跑;手机端解码能力差异巨大,尤其是一些中低端安卓机,H.264 的 4K 硬解支持都不完整。
我的优化策略是三档降级:
- 检测到移动端(通过 JS 判断 userAgent 或设备类型)时,优先使用 1080p 视频源;
- 如果移动端还卡,降低默认 fov,减少当前帧需要渲染的像素数;
- 关闭移动端的自动旋转,避免陀螺仪与鼠标拖拽同时运算导致发热卡顿。
真机测试也有一套固定流程:准备一台旧款 iPhone 和一台中低端安卓机,用 4G 网络而不是 WiFi 测试。WiFi 下带宽充足,问题不容易暴露;4G 网络才能看出加载速度和卡顿情况。我在交付前至少会跑三轮:WiFi 桌面、WiFi 手机、4G 手机。每一轮都盯着首帧时间、拖动进度响应和整体发热情况,有问题当场改。
另一个容易忽略的点是内存。Krpano 全景视频在低内存手机上容易被系统杀后台,所以视频场景不要同时加载太多热点图片和插件。热点图尽量用 PNG 压缩后的尺寸,不要放一个大几千像素的雪碧图进去。
6.3 几条实际踩坑后的心得
写到最后,分享几条从项目里磨出来的经验,都是文档里不会写的内容。
第一,调试时先用低分辨率代理视频。开发阶段先用一段几 MB 的 540p 测试视频把交互逻辑全部跑通,确认热点、跳转、进度条没问题之后,再换成正式的高清素材。如果一上来就用 4K 大文件调试,每次改 XML 都要等加载,效率会低到怀疑人生。
第二,所有局部变量尽量用 Krpano 的 trace 日志排查。Krpano 浏览器端调试时可以打开 console 面板,XML 里也可以用trace()输出变量值。热点不显示时,先 trace 一下热点 visible 状态和 videotime 当前值,往往一眼就能看出来是时间区间写错了还是热点自身问题。
第三,视频和 XML 文件全部放同域。无论是普通 MP4 还是 HLS,跨域都可能带来额外的问题。如果你必须把视频放在 CDN,优先用 HLS 并配好 CORS,比直接放 MP4 省心得多。
第四,视频封面图一定要做,而且不要太大。我遇到过一次客户说“打开项目黑屏”,排查到最后发现是 4K 预览图太大,在手机上加载太慢,所以首屏一直黑。后来封面图压到 200KB 以内,问题消失。
第五,最后再说一个小技巧:如果用自定义播放按钮,记得给按钮加一个onover状态,放大或者改变透明度,否则用户很难发现那是可以点的。全景视频场景里信息层级本来就比普通页面多,交互元素的视觉反馈一定要明显,不然按钮就像隐形的一样。
全景视频这个模块,素材编解码占四成问题,XML 配置占三成,剩下的都是设备适配和交互细节。把这几块理顺了,交付一个流畅稳定的全景视频漫游项目并不难。后面如果碰到新的坑,我再开一篇随笔补上。