Appearance
配方 · 高清需要登录
参考实现:
examples/team-video-vue/AuthGatedVideoPlayer.vue
需求:未登录用户只能看标清;高清档位显示「登录享」;点击弹登录框; 登录成功后自动切到高清。
关键认知:「被锁档位」不是契约概念
契约里的 QualityLevel 只有 { level, label?, height?, bitrate? } —— 没有 requiresAuth 这种字段,也不会有。
清晰度要不要登录,是你的业务规则,SDK 不掺和。所以这个配方的做法是: SDK 照常给出全部档位,团队层在渲染菜单时自己判断哪些该锁。
ts
// 被锁档位 = 需鉴权且未登录的那些(业务概念,不进契约)
const lockedQuality = computed(() =>
props.isLoggedIn ? [] : props.qualityLevels.filter((q) => q.requiresAuth).map((q) => q.index),
)requiresAuth 来自你自己的视频详情接口,不是 ready 事件。
三步接线
① 改标签
ts
const qualityLabels = computed<Record<number, string>>(() => {
const map: Record<number, string> = {}
for (const q of props.qualityLevels) {
map[q.index] = q.requiresAuth && !props.isLoggedIn
? t('quality.hdLoginRequired') // 「高清(登录享)」
: q.label
}
return map
})② 拦截点击
被锁的档位点了不切换,而是走登录流程:
ts
function handleQualityLocked(level: number) {
const chosen = props.qualityLevels.find((q) => q.index === level)
if (!chosen) return
wasHdRequested.value = true // 记下用户想要高清
analytics.track(ANALYTICS_EVENTS.QUALITY_LOGIN_REQUIRED, {
resolution: chosen.resolution,
})
showDialog({ /* ... */ }).then(() => emit('loginRequired', chosen))
}③ 登录后自动补上
ts
watch(
() => props.isLoggedIn,
(loggedIn) => {
if (loggedIn && wasHdRequested.value) {
playerRef.value?.setQuality(props.premiumQualityIndex)
currentQualityIndex.value = props.premiumQualityIndex
wasHdRequested.value = false
}
},
)wasHdRequested 这个标记是体验的关键。没有它,用户为了看高清专门去登录, 回来发现还是标清,得再点一次菜单 —— 白费一次交互。
别忘了 qualitychange 的 auto 字段
js
onQualityChange({ level, auto })auto: true 表示是 ABR 自适应切的,不是用户选的。
菜单里「当前选中」的高亮不该被 ABR 的自动切换改掉 —— 否则用户手动选了 720p,网络一波动 ABR 降到 480p,菜单跟着跳, 用户会以为自己的选择被系统推翻了。
js
function handleQualityChange({ level, auto }) {
currentPlayingLevel.value = level // 实际在播的,用于显示"当前 480p"
if (!auto) userSelectedLevel.value = level // 只有手动切才更新"用户选择"
}高清源本身也要鉴权
菜单锁住只是 UI 层面 —— 用户改改前端代码就能绕过。真正的门槛在源上:
高清那一档的 URL 应该是登录后才签得出来的签名 URL。未登录时, 要么这一档根本不在 manifest 里,要么拉流会 403。
前端的锁是为了体验(告诉用户为什么看不了),不是为了安全。
相关
- 在播放器上做 UI · 场景 7 —— 占位档位菜单的具体写法
- 鉴权与签名过期