# Veplayer小程序播放器

> 小程序播放器微信原生版本

## 前提条件
在**小程序后台 > 开发 > 开发设置 > 服务器域名**中添加以下域名配置：

- 日志上报域名：https://mcs.zijieapi.com
- 播放请求域名（Vid 方式播放时需要）：https://vod.volcengineapi.com

操作截图如下所示。
![](https://p6-addone.byteimg.com/tos-cn-i-hhc0kcolqq/a5826e66424a4ba8aabb978a7328b144.png~tplv-hhc0kcolqq-image.image)
> 视频资源的 CDN 域名不需要添加到域名配置中。

## 安装
``` bash
# npm
npm i veplayer-mp-wechat
npm i veplayer-mp-logger

# yarn 
yarn add veplayer-mp-wechat
yarn add veplayer-mp-logger
```
## 构建 npm 包
请优先了解微信小程序官网对于 [npm 支持](https://developers.weixin.qq.com/miniprogram/dev/devtools/npm.html) 的介绍。
您需要点击微信开发者工具中的菜单栏，**工具 > 构建 npm**。
![](https://p6-addone.byteimg.com/tos-cn-i-hhc0kcolqq/cbca0d871cdf4441ae64b6515e70d6a0.png~tplv-hhc0kcolqq-image.image)
## 引入组件
详情请参考微信官方文档小程序自定义组件的[引入方式](https://developers.weixin.qq.com/miniprogram/dev/framework/custom-component/)。引入微信小程序点播 SDK 的代码示例如下：
``` json
{
  "usingComponents": {
    "veplayer": "veplayer-mp-wechat"
  }
}
```
## 使用组件
### 使用播放器组件
按照播放方式的不同，分为 DirectUrl 方式播放和 Vid 方式播放。
#### DirectUrl 方式播放
```wxml
<view>
  <!-- 以下是对小程序播放器组件的引用 -->
  <veplayer
    id="videoContainer"
    showPlayBtn
    autoplay
    src="http://xxxx.mp4"
    logInfo="logInfo"
    bindplay="onPlay"
  />
</view>
```
#### Vid 方式播放
```wxml
<view>
  <!-- 以下是对一个播放器组件的引用 -->
  <veplayer
    id="videoContainer"
    showPlayBtn
    autoplay
    playDomain='https://vod.volcengineapi.com'
    playAuthToken='*****************'
    logInfo="logInfo"
    bindplay="onPlay"
  />
</view>
```

- playDomain 是调用火山引擎视频点播 OpenAPI 的播放域名，您如果做了该接口的代理，可以替换成您自己的播放域名。使用正式 AppID 调试时需要将该地址配置在小程序[服务器域名配置](https://developers.weixin.qq.com/miniprogram/dev/framework/ability/network.html)白名单中。
- playAuthToken 是获取视频播放信息的临时凭证，由业务方服务端通过调用火山服务端 SDK 基于视频 Vid 本地方法生成，具体生成参考[火山引擎视频点播文档](https://www.volcengine.com/docs/4/67350#%E6%9C%8D%E5%8A%A1%E7%AB%AF-sdk)。

对应业务组件中添加日志上报需要的视频信息配置，代码示例如下：
```javascript
// index.js
Component({
  data: {
    src: 'https://xxxx.mp4',
    ...,
    logInfo: {
      vtype: 'MP4',        // [可选]播放类型， 默认为 'MP4'，'HLS' || 'MP4' 
      codecType: 'h264',   // [可选]视频编码类型，默认 h264，'h264' || 'h265'
      sourceType: 'url',   // [可选]播放资源类型，默认 'vid'，'vid' || 'url'
      bitrate: 1334556,    // [可选]视频码率，默认为 0
      vid: '1',            // [可选]sourceType 为 vid 的时候视频 vid
      tag: 'myTag',        // [可选]播放场景
      subtag: 'subtag',    // [可选]二级播放场景
      logger: true,        // [可选] 是否开启 log 打印，默认 false， 开发环境可设置为 true
    }
  }
})
```

### 配置日志采集上报
在组件的属性中传入logInfo，logInfo中需要传入appId，即可开启播放日志的采集上报，除了appId，可以根据业务的需要填入以下所列配置。

| 属性名           | 类型        | 是否必选 | 默认值                      | 说明                                                                                                                      |
|---------------|-----------|------|--------------------------|-------------------------------------------------------------------------------------------------------------------------|
| appId         | number    | 是    | -                        | 应用ID, 可在火山引擎视频点播控制台上获取应用 AppID                                                                                          |
| userId        | string    | 否    | -                        | 用户 ID，强烈建议您使用与业务相关的用户 ID。如不传入，SDK 将随机生成一个值。强烈建议您使用与业务密切相关的用户 ID，以便在播放过程中出现错误时，可以进行单点故障排查，精确定位问题。如果您没有设定用户 ID，组件将随机生成一个。 |
| tag           | string    | 否    | -                        | 业务标签或业务类型，用于标记不同的播放场景，如推荐页、详情页                                                                                          |
| subtag        | string    | 否    | -                        | 子业务标签或业务类型，用于细分播放场景                                                                                                     |
| vtype         | HLS 或 MP4 | 否    | MP4                      | 视频格式                                                                                                                    | 
| codecType     | string    | 否    | h264                     | 视频编码格式                                                                                                                  |
| bitrate       | number    | 否    | 0                        | 视频码率                                                                                                                    |
| logger        | boolean   | 否    | false                    | 是否开启日志打印                                                                                                                |
| appName       | string    | 否    | 视频云小程序                   | 应用名称                                                                                                                    |
| appVersion    | string    | 否    | 1.0.0                    | 应用版本                                                                                                                    |
| channelDomain | string    | 否    | https://mcs.zijieapi.com | 日志上报域名                                                                                                                  |

示例代码如下：
```xml
<view>
  <!-- 以下是对小程序播放器 SDK 的引用 -->
  <veplayer
    id="videoContainer"
    src="{{src}}"
    loop
    logInfo="{{logInfo}}"
  />
</view>
```
```javascript
// index.js
Component({
  data: {
    src: 'https://xxxx.mp4',
    logInfo: {
      appId: xxx,
      tag: 'recommend',
      subtag: 'hot',
    }
  }
})
```


### 查看日志上报数据
视频信息配置完成后，可登录[视频点播控制台](https://console.volcengine.com/vod/welcome/)，选择左侧导航栏[质量平台 > 播放看板](https://console.volcengine.com/vod/quality_control/new_play_dashboard/?Tab=all)，进入**播放看板**页面，选择大盘速览页签，在查询条件中选择在小程序点播 SDK 中配置的各项指标。详细操作说明请见[查看大盘速览](https://www.volcengine.com/docs/4/106096#%E6%9F%A5%E7%9C%8B%E5%A4%A7%E7%9B%98%E9%80%9F%E8%A7%88)。
## 组件属性
小程序播放器封装了 video 原生组件，支持配置大部分的 video 属性。原生组件支持的属性配置详情请参考[微信官方文档](https://developers.weixin.qq.com/miniprogram/dev/component/video.html)。以下列表展示了新增属性及差异化属性。

- 列表中的部分属性以 show- 开头的开关，既影响原生组件，又影响自定义 UI。
- 不在列表中的只影响原生组件。

原生微信 video 组件的属性，如：show-play-btn 这类中划线分割的属性名，需要改写成驼峰式命名showPlayBtn。

| **属性**                    | **类型**                                                                              | **默认值**                                             | **是否必选**  | **说明**                                                                                                                                                                                                             |
|---------------------------|-------------------------------------------------------------------------------------|-----------------------------------------------------|-----------|--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|
| mode                      | 'portrait' &#124; 'landscape'                                                       | landscape                                           | 否         | UI 模式。支持 2 种播放 UI 模式。取值如下：landscape：（默认值）横屏。展示类似抖音等短视频播放 UI 模式。 portrait：竖屏。展示偏向于普通的 PC 视频播放器 UI 模式。                                                                                                               |
| componentId               | String                                                                              |                                                     | 否         | video 组件 ID。通过createVideoContext获取视频 VideoContext。如果不传，随机生成一个 ID，需要通过组件上下文的getContext()方法才能获取视频 VideoContext。                                                                                                      |
| src                       | String                                                                              |                                                     | 是         | 播放视频的资源地址。支持网络路径、本地临时路径、云文件 ID等。                                                                                                                                                                                   |
| controls                  | 'custom' \| 'native'\|'false'\| 'focus' \| 'hidden' \| 'blur' \| 'focus' \| immerse | 'custom'                                            | 否         | custom: 自定义UI；<br/> native: 原生组件UI；false: <br/> 完全关闭播放UI控件（包括自定义UI及原生组件UI）； <br/> focus: 高亮状态；<br/>  hidden： 隐藏状态（禁交互）；<br/> blur: 失去焦点状态；<br/> immerse：半沉浸状态（即半透明状态）， <br/> 播放UI控件指loading状态、播控按钮、进度条、时间显示等。<br/> |
| playAuthToken             | string                                                                              |                                                     | vid方式播放必传 | 获取视频播放信息的临时凭证，由业务方服务端通过调用火山服务端SDK基于视频vid本地服务生成，具体生成参考[火山引擎视频点播文档](https://www.volcengine.com/docs/4/67350#%E6%9C%8D%E5%8A%A1%E7%AB%AF-sdk)                                                                         |
| playDomain                | string                                                                              | https://vod.volcengineapi.com                       | 否         | 调用火山引擎视频点播 OpenAPI 的播放域名，您如果做了该接口的代理，可以替换成您自己的播放域名。使用正式 AppID 调试时需要将该地址配置在小程序[服务器域名配置](https://developers.weixin.qq.com/miniprogram/dev/framework/ability/network.html)白名单中｜                                       |
| duration                  | number                                                                              |                                                     | 否         | 指定视频时长。不会控制实际播放的时长。因此该属性不设置给原始 video 组件，只提供给自定义 UI 使用。                                                                                                                                                             |
| showCenterPlayBtn         | boolean                                                                             | true                                                | 否         | 是否显示视频正中心的播放按钮。                                                                                                                                                                                                    |
| showBottomProgress        | boolean                                                                             | true                                                | 否         | 是否展示底部进度条。                                                                                                                                                                                                         |
| needLoading				           | boolean                                                                             | true                                                | 否         | 是否显示loading,扩展属性,controls=custom的时候生效,v0.1.12之后的版本生效                                                                                                                                                               |
| timeUpdateInterval        | number                                                                              | 400                                                 | 否         | 进度条更新的频率, 用于减少频繁的渲染造成内存升高的问题，单位ms                                                                                                                                                                                  |
| autoBlurTime              | number                                                                              | 15000                                               | 否         | 自动失焦，即播放器在处于激活态用户无操作多长时间隐藏播控                                                                                                                                                                                       |
| interactiveConfig         | object                                                                              | { immersive: false, delay: 10000, focusDelay: 0   } | 否         | 响应式配置：<br/>  immersive： 是否启用半沉浸式 <br/> delay：进入半沉浸状态/隐藏状态的延迟时间，单位ms <br/> focusDelay: 隐藏态进入focus态是否自动切换，单位ms                                                                                                       |
| activeState               | string                                                                              | default                                             | 否         | 当前实例是否是激活状态：<br/>  active：激活状态<br/>  standby：备用状态 <br/>  default：默认状态，即不区分是否激活                                                                                                                                     |
| enableTapActive           | boolean                                                                             | true                                                | 否         | 自定义controls时，即controls不是native时，是否启用点击触发激活（进入focus态）                                                                                                                                                               |
| binduseraction            | eventhandle                                                                         |                                                     | 否         | 用户行为触发，如用户点击暂停、滑动进度条                                                                                                                                                                                               |
| bindplay                  | eventhandle                                                                         |                                                     | 否         | 当开始/继续播放时触发 play 事件。                                                                                                                                                                                               |
| bindpause                 | eventhandle                                                                         |                                                     | 否         | 当暂停播放时触发 pause 事件。                                                                                                                                                                                                 |
| bindended                 | eventhandle                                                                         |                                                     | 否         | 当播放到末尾时触发 ended 事件。                                                                                                                                                                                                |
| bindtimeupdate            | eventhandle                                                                         |                                                     | 否         | 播放进度变化时触发 timeupdate 事件。`event.detail = {currentTime, duration} ` 触发频率 250ms 一次。                                                                                                                                   |
| bindfullscreenchange      | eventhandle                                                                         |                                                     | 否         | 视频进入和退出全屏时触发 fullscreenchange 事件。`event.detail = {fullScreen, direction} ` `direction` 有效值为 `vertical` 或 `horizontal`                                                                                              |
| bindwaiting               | eventhandle                                                                         |                                                     | 否         | 视频出现缓冲时触发 waiting 事件。                                                                                                                                                                                              |
| binderror                 | eventhandle                                                                         |                                                     | 否         | 视频播放出错时触发 error事件。                                                                                                                                                                                                 |
| bindprogress              | eventhandle                                                                         |                                                     | 否         | 加载进度变化时触发 progress 事件，只支持一段加载。`event.detail = { buffered }` ，单位百分比                                                                                                                                                 |
| bindloadedmetadata        | eventhandle                                                                         |                                                     | 否         | 视频元数据加载完成时触发 loadedmetadata 事件。`event.detail = {width, height, duration}`                                                                                                                                          |
| bindcontrolstoggle        | eventhandle                                                                         |                                                     | 否         | 切换 controls 显示隐藏时触发 controlstoggle 事件。`event.detail = {show}`                                                                                                                                                      |
| bindenterpictureinpicture | eventhandle                                                                         |                                                     | 否         | 播放器进入小窗 enterpictureinpicture 事件。                                                                                                                                                                                  |
| bindleavepictureinpicture | eventhandle                                                                         |                                                     | 否         | 播放器退出小窗 leavepictureinpicture 事件。                                                                                                                                                                                  |
| bindseekcomplete          | eventhandle                                                                         |                                                     | 否         | seek 完成时触发 seekcomplete 事件。position 的单位在不同系统上有所区别： iOS单位为 s，Android，单位为 ms。                                                                                                                                        |

## 组件接口
小程序播放器封装了 [VideoContext](https://developers.weixin.qq.com/miniprogram/dev/api/media/video/VideoContext.html)，提供同原生接口一致的 API。代码示例如下所示。
```javascript
const component = this.selectComponent("#videoContainer");
const player = component.getContext()

// 原生接口
player.play()
player.pause()
player.stop()
player.seek(10)
player.sendDanmu(Object data)
player.playbackRate(1)
player.requestFullScreen({ direction: 90 })
player.exitFullScreen()
player.exitPictureInPicture()
player.requestBackgroundPlayback()
player.exitBackgroundPlayback()
```
## 组件事件
微信小程序播放器对外支持 2 种方式的事件监听形式：

- 组件属性 bind 方式事件监听
- 组件对象提供事件订阅的机制进行事件监听

请选择其中一种进行订阅，尽量不要两者混用。这两种方式在组件实例中，被从页面节点树移除(lifetimes -> detached)时，进行事件解绑，您无需单独关注事件泄漏的问题。
### 组件属性 bind 方式事件监听
请参见[组件属性](https://developers.weixin.qq.com/miniprogram/dev/component/video.html)中 bind 开头的事件属性。
### 组件对象提供事件订阅的机制进行事件监听
小程序播放器提供了接口可以获取 player context，并可以对 player 添加事件订阅，从而实现任意时刻对各种播放事件添加/移除监听的功能。代码示例如下所示。
``` javascript
const component = this.selectComponent("#videoContainer");
const player = component.getContext();

// 事件订阅
player.on('error', (e) => {
  console.log('event error:', e)
});
player.on('timeupdate', (e) => {
  const { currentTime, duration } = e.detail;
  console.log('event timeupdate:', currentTime, duration)
});
// ...
```
详细的事件列表如下所示。

| **事件名称**              | **是否可自定义事件** | **说明**                                 |
|-----------------------|--------------|----------------------------------------|
| play                  | 否            | 当开始/继续播放时触发 play 事件。                   |
| pause                 | 否            | 当暂停播放时触发 pause 事件。                     |
| ended                 | 否            | 当播放到末尾时触发 ended 事件。                    |
| timeupdate            | 否            | 播放进度变化时触发。                             |
| fullscreenchange      | 否            | 视频进入和退出全屏时触发 fullscreenchange 事件。      |
| waiting               | 否            | 视频出现缓冲时触发 waiting 事件。                  |
| error                 | 否            | 视频播放出错时触发 error 事件。                    |
| progress              | 否            | 加载进度变化时触发 progress 事件，只支持一段加载。         |
| loadedmetadata        | 否            | 视频元数据加载完成时触发 loadedmetadata 事件。        |
| controlstoggle        | 否            | 切换 controls 显示隐藏时触发 controlstoggle 事件。 |
| enterpictureinpicture | 否            | 播放器进入小窗 enterpictureinpicture 事件。      |
| leavepictureinpicture | 否            | 播放器退出小窗 leavepictureinpicture 事件。      |
| seekcomplete          | 否            | seek 完成时触发 seekcomplete 事件。            |



## uni-app 项目使用

此播放器组件提供的是原生小程序版本，uni-app项目[支持使用小程序自定义组件](https://uniapp.dcloud.net.cn/tutorial/miniprogram-subject.html)，可以按照以下步骤在uni-app项目中使用此播放器组件：

### 1. 在项目中安装依赖
```bash
# npm
npm i veplayer-mp-wechat
npm i veplayer-mp-logger

# yarn 
yarn add veplayer-mp-wechat
yarn add veplayer-mp-logger
```
> HBuilderX创建的项目默认没有`package.json`文件，需要通过初始化命令来创建。
> ```bash
> npm init -y
> ```

### 2. 拷贝组件到项目目录
拷贝`node_modules/veplayer-mp-wechat`到项目小程序组件存放目录`wxcomponents`（0.1.14之后的版本会自动拷贝）。HBuilderX 建立的工程 `ttcomponents` 文件夹在 项目根目录下。vue-cli 建立的工程 `ttcomponents` 文件夹在 `src` 目录下。


### 3. 配置组件引入
在 `pages.json` 对应页面的 style -> usingComponents 引入组件： 可通过uni-app提供的[条件编译](https://uniapp.dcloud.net.cn/tutorial/platform.html#preprocessor)的方式在不同平台上编译使用不同的SDK，抖音小程序播放器SDK对应[veplayer-mp-douyin](https://www.npmjs.com/package/veplayer-mp-douyin)

> 如果是在 vue 组件中使用小程序组件时，注意需要在 `pages.json` 的 `globalStyle` 中配置 `usingComponents`，而不是页面级配置。

``` json
{
	"pages": [
		{
			"path": "pages/index/index",
			"style": {
				// #ifdef MP-WEIXIN
				"usingComponents": {
					"veplayer": "/wxcomponents/veplayer-mp-wechat/dist/index"
				},
				// #endif
				// #ifdef MP-TOUTIAO
				"usingComponents": {
					"veplayer": "/ttcomponents/veplayer-mp-douyin/dist/index"
				},
				// #endif
				"navigationBarTitleText": "uni-app"
			}
		}
	]
}
```

### 4. 组件使用
以vue模板语法示例：
```vue
<!-- 页面模板 (index.vue) -->
<template>
  <view>
    <!-- 在页面中对自定义组件进行引用 -->
    <veplayer
        id="video"
        :src="src"
        controls="custom"
        @play="onPlay"
        @timeupdate="onTimeupdate"
    />
  </view>
</template>

<script>
  export default {
  data() {
    return {
      src: 'https://xx.cdn.com/demo.mp4'
    }
  },

  methods: {
    onPlay(e) {
      // TODO something
      console.log('play event: ', e);
    },

    onTimeupdate(e) {
      // TODO something
      console.log('timeupdate event', e);
    },
  },
}
</script>
```

### 5. 配置日志采集上报
在组件的属性中传入logInfo，logInfo中需要传入appId，即可开启播放日志的采集上报，除了appId，可以根据业务的需要填入以下所列配置。

| 属性名           | 类型        | 是否必选 | 默认值                      | 说明                                                                                                                      |
|---------------|-----------|------|--------------------------|-------------------------------------------------------------------------------------------------------------------------|
| appId         | number    | 是    | -                        | 应用ID, 可在火山引擎视频点播控制台上获取应用 AppID                                                                                          |
| userId        | string    | 否    | -                        | 用户 ID，强烈建议您使用与业务相关的用户 ID。如不传入，SDK 将随机生成一个值。强烈建议您使用与业务密切相关的用户 ID，以便在播放过程中出现错误时，可以进行单点故障排查，精确定位问题。如果您没有设定用户 ID，组件将随机生成一个。 |
| tag           | string    | 否    | -                        | 业务标签或业务类型，用于标记不同的播放场景，如推荐页、详情页                                                                                          |
| subtag        | string    | 否    | -                        | 子业务标签或业务类型，用于细分播放场景                                                                                                     |
| vtype         | HLS 或 MP4 | 否    | MP4                      | 视频格式                                                                                                                    | 
| codecType     | string    | 否    | h264                     | 视频编码格式                                                                                                                  |
| bitrate       | number    | 否    | 0                        | 视频码率                                                                                                                    |
| logger        | boolean   | 否    | false                    | 是否开启日志打印                                                                                                                |
| appName       | string    | 否    | 视频云小程序                   | 应用名称                                                                                                                    |
| appVersion    | string    | 否    | 1.0.0                    | 应用版本                                                                                                                    |
| channelDomain | string    | 否    | https://mcs.zijieapi.com | 日志上报域名                                                                                                                  |

示例代码如下：
```vue
<!-- 页面模板 (index.vue) -->
<template>
  <view>
    <veplayer
        id="videoContainer"
        :src="src"
        loop
        :logInfo="logInfo"
    />
  </view>
</template> 
<script>
  export default {
    data() {
      return {
        src: 'https://xx.cdn.com/demo.mp4',
        logInfo: {
          appId: xxx,
          tag: 'recommend',
          subtag: 'hot',
        }
      }
    },
  }
</script>

```

### 使用播放器组件
API使用，以暂停为例：
```javascript
  const component = this.selectComponent('#video');
  const player = component.getContext();
  if (player) {
    player.pause();
  }
```

订阅事件：
除了通过`@事件名`方式进行监听外，还可以通过组件的`videoContext`以事件订阅的方式动态监听。
```javascript
  const component = this.selectComponent('#video');
  const player = component.getContext();
  if (player) {
    player.on('timeupdate', (data) => {
      const { currentTime, duration } = data.e.detail;
      console.log('event timeupdate:', currentTime, duration)
    });
  }
```

> - 如果是从uni-app的video组件迁移到本组件，不作API使用的更改，则组件属性里通过`componentId`传入`uni.createVideoContext`需要的组件id，API调用同[uni-app组件说明](https://uniapp.dcloud.net.cn/component/video.html)。
> - 需要注意的是通过`createVideoContext`获取的播放器上下文无法使用事件订阅。

注意数据和事件绑定的差异，组件使用时应按照 vue 的方式进行数据和事件绑定：
- 属性绑定从 attr=""，改为 :attr="a"；从 src="http://xx.demo.com/1.mp4" 改为 :src="'http://xx.demo.com/' + vid + '.mp4"
- 事件绑定从 bind:play="onPlay" 改为 @play="onPlay"
- 阻止事件冒泡 从 catch:tap="xx" 改为 @tap.native.stop="xx"
- wx:if 改为 v-if
- wx:for="" wx:key="" 改为v-for="(item,index) in list"
> 详细的小程序转uni-app语法差异可参考文档https://ask.dcloud.net.cn/article/35786。


## Taro 项目使用
Taro 项目支持[使用原生小程序组件](https://taro-docs.jd.com/docs/hybrid)，可以按照以下步骤在Taro项目中使用此播放器组件。

### 1. 在项目中安装依赖
```bash
# npm
npm i veplayer-mp-wechat
npm i veplayer-mp-logger

# yarn 
yarn add veplayer-mp-wechat
yarn add veplayer-mp-logger
```

### 2. 拷贝组件到项目目录
拷贝`node_modules/veplayer-mp-wechat`到项目小程序组件存放目录`wxcomponents`（0.1.14之后的版本会自动拷贝）。

### 3. 配置组件引入
在使用到播放器组件所在页面的`index.config.ts`配置中引入组件：
```typescript
export default definePageConfig({
    navigationBarTitleText: '',
    navigationBarTextStyle: 'black',
    navigationStyle: 'custom',
    disableScroll: true,
    usingComponents: {
        veplayer: '../../wxcomponents/veplayer-mp-wechat/dist/index',
    },
});
```
> 注意保证组件路径配置正确

### 4. 组件使用
以react语法示例在自定义组件中使用播放器组件：
```typescript
const VideoPlayer = ({
       videoComponentId,
       className,
       videoPlayUrl,
       coverUrl,
       controlShow,
       onTimeUpdate,
       onError,
   }) => {
  const handleTimeupdate = (e) => {
      // 注意原生组件事件的event在taro项目中被劫持包装到了e.mpEvent.detail.e中
    const originEvent = e.mpEvent.detail.e;
    const { currentTime, duration } = originEvent.detail;
    // TODO something
    // ...
    onTimeUpdate(currentTime);
  };

  const handleVideoTap = () => {
      // 点击视频
  };
  
  return (
    <veplayer
      id={videoComponentId}
      // 引用原生组件需要使用 class 传参
      class={className}
      src={videoPlayUrl}
      showPlayBtn
      showBottomProgress={false}
      controls={controlShow}
      // 原生组件需要使用小写 autoplay
      autoplay
      onPlay={onPlay}
      onTimeupdate={handleTimeupdate}
      poster={coverUrl}
      onError={onError}
      onTap={handleVideoTap}
    />
);
};
```

### 5. 配置日志采集上报
在组件的属性中传入logInfo，logInfo中需要传入appId，即可开启播放日志的采集上报，除了appId，可以根据业务的需要填入以下所列配置。

| 属性名           | 类型        | 是否必选 | 默认值                      | 说明                                                                                                                      |
|---------------|-----------|------|--------------------------|-------------------------------------------------------------------------------------------------------------------------|
| appId         | number    | 是    | -                        | 应用ID, 可在火山引擎视频点播控制台上获取应用 AppID                                                                                          |
| userId        | string    | 否    | -                        | 用户 ID，强烈建议您使用与业务相关的用户 ID。如不传入，SDK 将随机生成一个值。强烈建议您使用与业务密切相关的用户 ID，以便在播放过程中出现错误时，可以进行单点故障排查，精确定位问题。如果您没有设定用户 ID，组件将随机生成一个。 |
| tag           | string    | 否    | -                        | 业务标签或业务类型，用于标记不同的播放场景，如推荐页、详情页                                                                                          |
| subtag        | string    | 否    | -                        | 子业务标签或业务类型，用于细分播放场景                                                                                                     |
| vtype         | HLS 或 MP4 | 否    | MP4                      | 视频格式                                                                                                                    | 
| codecType     | string    | 否    | h264                     | 视频编码格式                                                                                                                  |
| bitrate       | number    | 否    | 0                        | 视频码率                                                                                                                    |
| logger        | boolean   | 否    | false                    | 是否开启日志打印                                                                                                                |
| appName       | string    | 否    | 视频云小程序                   | 应用名称                                                                                                                    |
| appVersion    | string    | 否    | 1.0.0                    | 应用版本                                                                                                                    |
| channelDomain | string    | 否    | https://mcs.zijieapi.com | 日志上报域名                                                                                                                  |

示例代码如下：
```typescript
const VideoPlayer = ({
       videoComponentId,
       className,
       videoPlayUrl,
       coverUrl,
       controlShow,
       onTimeUpdate,
       onError,
   }) => {
  const handleTimeupdate = (e) => {
      // 注意原生组件事件的event在taro项目中被劫持包装到了e.mpEvent.detail.e中
    const originEvent = e.mpEvent.detail.e;
    const { currentTime, duration } = originEvent.detail;
    // TODO something
    // ...
    onTimeUpdate(currentTime);
  };

  const handleVideoTap = () => {
      // 点击视频
  };
  
  const logInfo = {
    appId: xxx,
    tag: 'recommend',
    subtag: 'hot',
  }
  
  return (
    <veplayer
      id={videoComponentId}
      // 引用原生组件需要使用 class 传参
      class={className}
      src={videoPlayUrl}
      logInfo={logInfo}
      showPlayBtn
      showBottomProgress={false}
      controls={controlShow}
      // 原生组件需要使用小写 autoplay
      autoplay
      onPlay={onPlay}
      onTimeupdate={handleTimeupdate}
      poster={coverUrl}
      onError={onError}
      onTap={handleVideoTap}
    />
);
};
```

API使用，以暂停为例：
```javascript
import Taro, { nextTick } from '@tarojs/taro';

const { page } = Taro.getCurrentInstance();
const videoContext = page?.selectComponent(`#${id}`)?.getContext();
videoContext.play();
```

订阅事件：
除了通过在jsx语法上添加`on+首字母大写事件名`方式进行监听外，还可以通过组件的`videoContext`以事件订阅的方式动态监听，以监听`timeupdate`事件为例
```javascript
import Taro from '@tarojs/taro';

const { page } = Taro.getCurrentInstance();
const videoContext = page?.selectComponent(`#${id}`)?.getContext();
if (player) {
  player.on('timeupdate', (data) => {
    const { currentTime, duration } = data.e.detail;
    console.log('event timeupdate:', currentTime, duration)
  });
}
```
需要注意的是通过jsx语法监听的原生事件event在taro项目中被劫持包装到了e.mpEvent.detail.e中，以监听`timeupdate`事件为例，取数据时参考以下代码：
```typescript
const handleTimeupdate = (e) => {
  // 注意原生组件事件的event在taro项目中被劫持包装到了e.mpEvent.detail.e中
  const originEvent = e.mpEvent.detail.e;
  const { currentTime, duration } = originEvent.detail;
  // TODO something
  // ...
};
```
