Appearance
浏览器劫持:UC、夸克、微信里发生了什么
在国内做 Web 播放器,绕不开一件事:有些浏览器会把你的视频抢走, 换成它自己的播放器。
什么叫"劫持"
正常情况下,<video> 元素归你控制:你画自己的控件、覆盖层、按钮。
UC 和夸克会检测页面里的 <video>,然后:
- 强制接管播放,换成它自己的全屏播放器
- 你的覆盖层 UI 全部失效——因为视频已经不在你的页面层级里了
- 夸克的表现是 xgplayer 的控件直接消失(坑 #10)
- UC 的表现是强制切到内置播放器(坑 #9)
用户看到的是浏览器厂商的播放器,不是你的。你的品牌、你的按钮、你的埋点,全没了。
为什么 SDK 不"对抗"它
这是个刻意的决定:SDK 只检测并告诉你,不尝试对抗。
理由很实际:
- 对抗手段都是 hack,依赖厂商当前版本的实现细节,下个版本就失效
- 对抗失败的表现更糟——半接管状态下,视频可能既不在你的层里也不在它的全屏里
- 这是浏览器厂商的产品决策,不是 bug,不会因为你 hack 而让步
所以 CompatPlugin 做的事很简单:
ts
export function detectCompat(ua: string): CompatResult {
if (UC_RE.test(ua)) return { incompatible: true, browser: 'uc', ... }
if (QUARK_RE.test(ua)) return { incompatible: true, browser: 'quark', ... }
return { incompatible: false }
}命中就抛一次 compatwarning 事件,由你决定怎么提示用户。
别高估这个插件
它只认这两个 UA,只上报,不补救。 坑点索引里曾把微信相关的几个坑也记在它名下,那是不准确的,已经修正。
真正让这些环境能播的是下一节讲的 SourceRouter。
js
// payload 是 { code, message, ua } —— **没有 browser 字段**,
// 要区分具体内核请自己解析 ua
function onCompatWarning({ code }: { code: string }) {
if (code === 'W_BROWSER_INCOMPATIBLE') {
showBanner('建议使用 Chrome 或 Safari 获得最佳体验')
}
}注意它是警告不是错误——不中断播放。能播多少是多少,只是体验打折。
微信是另一回事:不劫持,但环境受限
微信不在"劝你换浏览器"的名单里
这是刻意的。微信是主力平台,如果每个微信用户都被弹"请换浏览器",那是严重误伤。 compat.ts 的注释里明确写了这一点。
微信 WebView 的问题不是抢走视频,而是:
- FLV 兼容差——X5 内核对 MSE 的支持不完整
- 全屏行为和标准浏览器不同(坑 #6)
- iOS 微信里调原生全屏会崩(坑 #7)
- 小程序 WebView 有额外的播放中止问题(坑 #8)
真正的解法:强制走 HLS
微信、UC、夸克这三类环境的共同处置,其实在 SourceRouter 里:
ts
requiresHls = isIOS || isWeChat || isUC || isQuark || !hasMediaSource命中任何一条,强制选 HLS 源,绕开 FLV 在这些环境里的兼容问题。
这是最有效的一招:不去对抗浏览器的行为,而是换一条它一定支持的播放路径。 HLS 分片走标准 HTTP,兼容性远好于需要 MSE 的 FLV。
所以你的直播必须传两种源。只传 FLV 的话,这些环境里 SDK 无源可选, 只能抛
E_MEDIA_NOT_SUPPORTED。见 怎么选视频源。
还没解决的部分(如实说明)
以下几个坑目前只登记、没有代码处理:
| # | 症状 |
|---|---|
| #6 | 微信 WebView 竖屏点全屏没反应 |
| #8 | 微信小程序 WebView 播放中止 |
| #11 | 老版本 Android WebView canvas 白屏 |
| #12 | 三星浏览器 fullscreen 请求异常 |
| #19 | 微信 Android 需要注入 x5-video-* 属性 |
其中 #19 涉及 X5 内核的一组私有属性(x5-video-player-type 等), 用来控制微信里的播放形态。SDK 目前没有注入它们。
如果你的主战场是微信 WebView 深度交互,这几个和你直接相关—— 可以在团队封装层自己给 <video> 加属性,但 iframe 模式下摸不到内部 DOM, 需要用 inline 模式 —— React 和 Vue 现在都有 inline(ADR-052 取代了「Vue 只做 iframe」那条, 见 五种接入怎么选)。
实践建议
- 一定订阅
compatwarning,至少记个埋点,你才知道有多少用户在这些环境里 - 横幅要可关闭,别挡住播放
- 不要在 UC / 夸克里投入精力做复杂覆盖层 UI——大概率白做
- 微信是主力场景,要真机测,尤其是全屏和自动播放