aslan-h5/docs/视频特效播放说明.md

286 lines
7.8 KiB
Markdown
Raw Permalink Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

# VAP 播放接入说明
本文档整理当前项目中 VAP mp4 播放相关的组件、工具函数和活动页用法,方便后续复用、排查和扩展。
## 相关文件
| 文件 | 作用 |
| --- | --- |
| `src/components/VapMp4Player.vue` | 通用 VAP 播放组件,支持全屏弹层和页面内嵌播放 |
| `src/utils/vapMp4Config.js` | 从 mp4 文件中解析 `vapc` 配置并缓存 |
| `src/views/Activities/ActiveGame/vapBg.vue` | ActiveGame 顶部动图背景封装 |
| `src/views/Activities/ActiveGame/index.vue` | ActiveGame 中背景 VAP、奖励全屏 VAP 和预加载示例 |
| `src/config/imagePaths.js` | OSS 图片/视频 URL 生成,包含 `getMp4Url` |
| `src/utils/protectedAssets.js` | 受保护资源地址的编码和还原 |
依赖包在 `package.json` 中:
```json
"video-animation-player": "^1.0.5"
```
## 播放组件
`VapMp4Player.vue` 是项目里的通用播放器,内部使用 `video-animation-player`
基础用法:
```vue
<VapMp4Player
v-model="show"
:src="mp4Url"
mode="overlay"
fit="contain"
:loop="false"
:mute="false"
:auto-close="true"
:show-close="true"
:show-status="false"
/>
```
主要参数:
| 参数 | 类型 | 默认值 | 说明 |
| --- | --- | --- | --- |
| `modelValue` | Boolean | `false` | 控制播放组件显示,支持 `v-model` |
| `src` | String | `''` | mp4 地址 |
| `mode` | String | `'overlay'` | `overlay` 为全屏弹层,`inline` 为页面内嵌 |
| `fit` | String | `'contain'` | `contain``cover``fill` |
| `loop` | Boolean | `false` | 是否循环播放 |
| `mute` | Boolean | `false` | 是否静音 |
| `accurate` | Boolean | `true` | 传给 VAP 播放器的精准模式 |
| `autoClose` | Boolean | `true` | 非循环播放结束后是否自动关闭 |
| `showClose` | Boolean | `true` | 全屏弹层是否展示关闭按钮 |
| `showStatus` | Boolean | `true` | 是否展示加载/错误状态文案 |
| `vapData` | Object | `{}` | 额外透传给 `new Vap().play()` 的参数 |
事件:
| 事件 | 说明 |
| --- | --- |
| `update:modelValue` | 更新显示状态 |
| `loaded` | VAP 进入 playing 后触发 |
| `ended` | 播放结束 |
| `error` | 加载或播放失败 |
| `close` | 调用关闭逻辑后触发 |
注意:
- `overlay` 模式会通过 `Teleport` 挂到 `body`,默认 `z-index: 3000`
- `inline` 模式是 `position: absolute; inset: 0`,父容器需要有明确尺寸和定位。
- 组件内部会先调用 `resolveProtectedAssetUrl(src)`,因此可以直接传 `getMp4Url` 生成的受保护地址。
## VAP 配置解析
`src/utils/vapMp4Config.js` 负责从 mp4 中读取名为 `vapc` 的 box并解析其中的 JSON 配置。
导出方法:
```js
getVapConfigFromMp4(mp4Url)
preloadVapConfig(mp4Url)
clearVapConfigCache(mp4Url)
```
说明:
- `getVapConfigFromMp4(mp4Url)``fetch` 整个 mp4读取 ArrayBuffer 后查找 `vapc`
- 解析结果以 `mp4Url` 为 key 缓存在 `configCache` 中,重复播放同一个地址不会重复解析。
- `preloadVapConfig(mp4Url)` 适合页面预加载阶段使用,失败会吞掉错误并返回 `null`
- `clearVapConfigCache(mp4Url)` 可清除某个地址或全部缓存。
常见错误:
| 错误 | 可能原因 |
| --- | --- |
| `vapc box not found` | mp4 不是 VAP 格式,或没有内嵌 VAP 配置 |
| `mp4 request failed: xxx` | 地址不可访问、跨域、鉴权、OSS 路径错误 |
| `vapc box does not contain json` | `vapc` 存在但内容不是合法 JSON |
## mp4 地址约定
`src/config/imagePaths.js` 中提供了 mp4 URL 方法:
```js
getRawMp4Url(imagePath, filename)
getMp4Url(imagePath, filename)
```
示例:
```js
import { getMp4Url } from '@/config/imagePaths.js'
const mp4Url = (filename) => getMp4Url('Activities/ActiveGame/', filename)
const bgVapUrl = mp4Url('bg')
```
生成的线上地址形如:
```text
https://asset.global-interaction.com/h5/Azizi/Activities/ActiveGame/bg.mp4
```
开发环境会走:
```text
/oss/h5/Azizi/Activities/ActiveGame/bg.mp4
```
如果资源路径属于受保护范围,`getMp4Url` 会返回保护后的地址。播放器或预加载工具在真正 `fetch` 前需要用 `resolveProtectedAssetUrl` 还原。`VapMp4Player.vue` 内部已经处理播放时的还原;页面手动预加载时也要处理:
```js
import { preloadVapConfig } from '@/utils/vapMp4Config.js'
import { resolveProtectedAssetUrl } from '@/utils/protectedAssets.js'
await preloadVapConfig(resolveProtectedAssetUrl(bgVapUrl))
```
## ActiveGame 当前用法
### 顶部背景 VAP
`src/views/Activities/ActiveGame/vapBg.vue` 用于顶部背景:
```vue
<VapBg class="vap-background-layer" :src="bgVapUrl" />
```
内部实际使用:
```vue
<VapMp4Player
v-model="backgroundVisible"
:src="src"
mode="inline"
fit="cover"
:loop="true"
:mute="false"
:auto-close="false"
:show-status="false"
/>
```
页面样式中给背景 VAP 固定区域:
```scss
.vap-background-layer {
width: 100vw;
height: 150vw;
position: absolute;
top: 0;
left: 0;
z-index: 1;
pointer-events: none;
}
```
### 奖励全屏 VAP
点击奖励展示的左侧奖励图时,展示全屏居中的 VAP
```vue
<VapMp4Player
v-model="rewardVapShow"
:src="rewardVapUrl"
mode="overlay"
fit="contain"
:loop="false"
:mute="false"
:auto-close="true"
:show-close="true"
:show-status="false"
@error="handleRewardVapError"
/>
```
当前临时地址:
```js
const rewardVapUrl =
'https://asset.global-interaction.com/svgasource/manager-d824e59b-1a88-4d4f-aed3-01768ba20542.mp4'
```
## 预加载建议
如果页面打开后要尽快展示 VAP建议同时做两件事
1. 在页面预加载阶段调用 `preloadVapConfig`
2. 不要等 loading 结束后才挂载 VAP 组件,可以让页面在 loading 遮罩下先挂载VAP 提前初始化。
ActiveGame 当前预加载示例:
```js
await Promise.all([
preloadImages(criticalImages),
preloadVapConfig(resolveProtectedAssetUrl(bgVapUrl)),
preloadVapConfig(rewardVapUrl),
])
```
说明:
- `bgVapUrl` 来自 `getMp4Url`,需要先 `resolveProtectedAssetUrl`
- `rewardVapUrl` 是普通完整 OSS 地址,可以直接传入。
- `preloadVapConfig` 主要预热 VAP 配置解析和浏览器请求缓存,但最终播放仍由 `VapMp4Player` 创建 canvas 和播放器实例。
## 接入新页面步骤
1. 准备带 `vapc` 配置的 VAP mp4 文件。
2. 如果放在活动 OSS 目录,使用 `getMp4Url('Activities/xxx/', 'filename')` 生成地址。
3. 页面中引入 `VapMp4Player.vue`
4. 全屏播放用 `mode="overlay"`,页面背景或局部播放用 `mode="inline"`
5. 页面预加载阶段调用 `preloadVapConfig(resolveProtectedAssetUrl(mp4Url))`
6.`@error` 做兜底提示或日志,避免静默失败。
全屏弹层模板:
```vue
<VapMp4Player
v-model="vapShow"
:src="vapUrl"
mode="overlay"
fit="contain"
:loop="false"
:auto-close="true"
/>
```
页面背景模板:
```vue
<div class="vap-bg">
<VapMp4Player
v-model="vapVisible"
:src="vapUrl"
mode="inline"
fit="cover"
:loop="true"
:auto-close="false"
:show-close="false"
:show-status="false"
/>
</div>
```
```scss
.vap-bg {
position: absolute;
width: 100vw;
height: 150vw;
overflow: hidden;
pointer-events: none;
}
```
## 排查清单
- 页面空白或不播放:确认组件 `modelValue``true``src` 非空。
- 只有 loading 不结束:确认页面预加载流程有 `finally` 关闭 loading。
- 提示找不到 VAP 配置:确认 mp4 内有 `vapc` box。
- 本地能播线上不能播:检查 OSS 路径、跨域、资源保护地址是否还原。
- inline 不显示:确认父容器有 `position: relative/absolute` 和明确宽高。
- overlay 被遮挡:检查是否有更高的 z-index默认播放器弹层是 `3000`
- 背景遮挡内容检查页面层级ActiveGame 当前是页面背景 `z-index: 0`、VAP 背景 `z-index: 1`、页面内容 `z-index: 2`