# Veplayer小程序播放器

> 小程序播放器抖音原生版本

## 使用前提条件
在**小程序后台-开发-开发设置-服务器域名**中添加以下[域名配置](https://developer.open-douyin.com/docs/resource/zh-CN/mini-app/develop/guide/basic-ability/network)：
- 日志上报域名：`https://mcs.zijieapi.com`

- 播放请求域名（仅vid+playAuthToken播放时需要）：`https://vod.volcengineapi.com`

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


## 安装

```bash
# npm
npm i veplayer-mp-douyin
npm i veplayer-mp-logger

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

## 构建 npm 包
> 请优先了解抖音开放平台官网对于 [npm 功能](https://developer.open-douyin.com/docs/resource/zh-CN/mini-app/develop/framework/npm) 的介绍。

导入项目后，在开发工具编辑器左侧功能栏中，**NPM功能:依赖管理**中添加 npm 包。
<p style="text-align: center">
  <img style="width: 40%; border: 1px solid #dfe2e5;"  src="https://p6-addone.byteimg.com/tos-cn-i-hhc0kcolqq/e6d16b9891254b16881bc55101ae81b5.jpeg~tplv-hhc0kcolqq-image.image" />
</p>


## 引入组件

详情请参考抖音小程序自定义组件的[使用方式](https://developer.open-douyin.com/docs/resource/zh-CN/mini-app/develop/framework/custom-component/component-constructor)。

```json
{
  "usingComponents": {
    "veplayer": "ext://veplayer-mp-douyin/veplayer"
  }
}
```
> 正确使用npm功能需要更新抖音开发者工具到4.1.0以上版本。抖音开发者工具4.1.0 之前的版本需要引用手动拷贝到 components 的包即 "/components/veplayer-mp-douyin/dist/index"

## 使用组件
### 使用播放器组件
按照播放方式的不同，分为 url 方式播放和vid 方式播放：
#### 1. url 方式播放
```ttml
<view>
  <!-- 以下是对小程序播放器组件的引用 -->
  <veplayer
   	id="videoContainer"
    showPlayBtn
    autoplay
    src="http://xxxx.mp4"
    bindplay="onPlay"
  ></veplayer>
</view>
```
#### 2. 短剧方式播放
```ttml
<view>
  <!-- 以下是对小程序播放器组件的引用 -->
  <veplayer
   	id="videoContainer"
    showPlayBtn
    autoplay
    albumId="2342343543645"
    episodeId="877766252"
    bindplay="onPlay"
  ></veplayer>
</view>
```
- `albumId`： 对应原片id
- `episodeId`：对应剧集id

对应业务组件中添加日志上报需要的视频信息配置：

```javascript
// index.js
Component({
  data: {
    src: 'https://xxxx.mp4',
    albumId: '2342343543645',
    episodeId: '877766252'
  }
})
```
### 设置日志配置
在组件的属性中传入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#查看大盘速览)。

## [组件属性](#VideoProps)

小程序播放器对video原生组件进行了封装，因此支持大部分的video属性配置。以下说明列出了新增属性及差异化属性，列出的部分中以 `show-` 开头的开关即影响原生组件又影响自定义UI，不在列表中的只影响原生组件：

| Property                 | Type                                                                                | Default                                           | Required  | Description                                                                                                                                                                                                        |
|--------------------------|-------------------------------------------------------------------------------------|---------------------------------------------------|-----------|--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|
| mode                     | 'portrait' \| 'landscape'                                                           | 'landscape'                                       | 否         | 播放器支持竖屏(portrait)及横屏(landscape)两种播放UI模式。横屏模式偏向于普通的PC视频播放器UI，竖屏视频展示类似抖音等短视频播放模式。                                                                                                                                    |
| src                      | string                                                                              |                                                   | 否         |                                                                                                                                                                                                                    |
| componentId              | string                                                                              |                                                   | NO        | video组件的id，用于通过`createVideoContext`获取视频VideoContext，不传入则会随机生成一个id，此时视频VideoContext仅能通过组件上下文的`getContext`方法获取                                                                                                       |
| 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/> |
| showFullscreenBtn	       | boolean                                                                             |                                                   | 否         | 当开始/继续播放时触发play事件		                                                                                                                                                                                                |
| duration                 | number                                                                              |                                                   | 否         | 根据官方文档说明，duration属性只是控制显示的时长，不会控制实际播放的时长。因此该属性不设置给原始video组件，只提供给自定义UI使用                                                                                                                                            |
| playDomain	              | string                                                                              |                                                   | 否         | 		 调用火山引擎视频点播OpenAPI的接口地址，业务方如果做了该接口的代理，可以替换成业务方的地址                                                                                                                                                                |
| playAuthToken	           | string                                                                              |                                                   | 否         | 获取视频播放信息(包括播放地址，传入此项时不需要传入src)的临时凭证，由业务方服务端通过调用火山服务端SDK本地生成，具体生成方法参考[火山引擎视频点播文档](https://www.volcengine.com/docs/4/67350#%E6%9C%8D%E5%8A%A1%E7%AB%AF-sdk)                                                          |
| 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态）                                                                                                                                                               |
| albumId                  | string                                                                              |                                                   | 短剧方式播放时必填 | 原片id                                                                                                                                                                                                               |
| episodeId                | string                                                                              |                                                   | 短剧方式播放时必填 | 剧集id                                                                                                                                                                                                               |
| cloudType                | number                                                                              | 1                                                 | 否         | 使用cdn类型，1: 抖音云   2: 三方云； 如果不填服务端默认不从CDN上获取链接                                                                                                                                                                       |
| threePartyCloud          | string                                                                              |                                                   | 否         | 三方云链接，当cloud_type为2，即三方云时必传                                                                                                                                                                                        |
| version                  | string                                                                              | '1'                                               | 否         | 废弃字段。为了兼容老版本，请传 1                                                                                                                                                                                                  |
| binduseraction           | eventhandle                                                                         |                                                   | 否         | 用户行为触发，如用户点击暂停、滑动进度条                                                                                                                                                                                               |
| bindplay	                | eventhandle                                                                         |                                                   | 否         | 当开始/继续播放时触发play事件		                                                                                                                                                                                                |
| bindpause	               | eventhandle                                                                         |                                                   | 否         | 当暂停播放时触发 pause 事件	                                                                                                                                                                                                 |
| bindended	               | eventhandle                                                                         |                                                   | 否         | 当播放到末尾时触发 ended 事件		                                                                                                                                                                                               |
| bindtimeupdate		         | eventhandle                                                                         |                                                   | 否         | 播放进度变化时触发，event.detail = {currentTime, duration} 。触发频率 250ms 一次	                                                                                                                                                   |
| bindfullscreenchange		   | eventhandle                                                                         |                                                   | 否         | 视频进入和退出全屏时触发，event.detail = {fullScreen, direction}，direction 有效值为 vertical 或 horizontal                                                                                                                           |
| bindwaiting		            | eventhandle                                                                         |                                                   | 否         | 视频出现缓冲时触发		                                                                                                                                                                                                        |
| binderror		              | eventhandle                                                                         |                                                   | 否         | 视频播放出错时触发			                                                                                                                                                                                                       |
| bindprogress		           | eventhandle                                                                         |                                                   | 否         | 加载进度变化时触发，只支持一段加载。event.detail = {buffered}，百分比			                                                                                                                                                                 |
| bindloadedmetadata		     | eventhandle                                                                         |                                                   | 否         | 视频元数据加载完成时触发。event.detail = {width, height, duration}	                                                                                                                                                             |
| bindplaybackratechange		 | eventhandle                                                                         |                                                   | 否         | 视频倍速改变完成时触发。返回改变后的倍速值。event.detail={playbackRate}。	                                                                                                                                                                |
| bindenterbackground		    | eventhandle                                                                         |                                                   | 否         | 进入小窗播放时触发		                                                                                                                                                                                                        |
| bindclosebackground			   | eventhandle                                                                         |                                                   | 否         | 关闭小窗播放时触发			                                                                                                                                                                                                       |
| bindleavebackground			   | eventhandle                                                                         |                                                   | 否         | 离开小窗进入 app 事件时触发			                                                                                                                                                                                                |
| bindseeking				          | eventhandle                                                                         |                                                   | 否         | 组件内部代理劫持VideoContext，VideoContext.seek 调用后会立即发送该事件，`该事件非video自带事件，只支持 controls="custom"	时才对外发送`	                                                                                                                   |
| bindseekcomplete				     | eventhandle                                                                         |                                                   | 否         | seek 完成时触发 (position iOS 单位 s, Android 单位 ms)			                                                                                                                                                                   |
| bindcontrolstoggle        | eventhandle                                                                         |                                                     | 否         | 切换 controls 显示隐藏时触发 controlstoggle 事件。`event.detail = {show}`                                                                                                                                                      |

PS. 原生组件支持的属性配置请参考[抖音官方文档](https://developer.open-douyin.com/docs/resource/zh-CN/mini-app/develop/component/media-component/video)，注意`show-play-btn`这类中划线分割的属性名需要改写成驼峰式命名`showPlayBtn`。

> 原生组件支持的属性配置请参考[抖音官方文档](https://developer.open-douyin.com/docs/resource/zh-CN/mini-app/develop/component/media-component/video)，注意`show-play-btn`这类中划线分割的属性名需要改写成驼峰式命名`showPlayBtn`。

## [组件接口](#VideoExportAPIs) 

小程序播放器对[VideoContext](https://developer.open-douyin.com/docs/resource/zh-CN/mini-app/develop/api/media/video/video-context/overview)进行了封装，提供同原生接口一致的API。原生接口更多细节可阅读[官网](https://developer.open-douyin.com/docs/resource/zh-CN/mini-app/develop/api/media/video/video-context/overview)

```javascript
let player = null
// 异步获取组件内video的VideoContext
const component = this.selectComponent("#videoContainer", (component) => {
  player = component.getContext()
  // 原生接口
  player.play()
  player.pause()
  player.stop()
  player.seek(10)
  player.requestFullScreen()
  player.exitFullScreen()
  player.setWaterMark({ color: "#FFFF11" })
  player.setMediaVolume({ value: 1})
  player.getMediaVolume(options)
  player.playbackRate(1)
  player.requestFullScreen({ direction: 90 })
  player.exitFullScreen()
});
// 同步获取组件内video的VideoContext，需要保证是在page或者component的ready事件之后才能正常调用
// player = this.selectComponent("#videoContainer").getContext();
// player.play()
// ...
```

## [组件事件](#VideoEvents)

小程序播放器对外支持两种方式的事件订阅形式：
- 组件属性 bind 方式事件监听
- 组件对象提供事件订阅的机制进行事件监听

请选择其中一种进行订阅，尽量不要两者混用。这两种方式在组件实例中，被从页面节点树移除(lifetimes->detached)时，进行事件解绑，您无需单独关注事件泄漏的问题。

### 组件属性 bind 方式事件监听

请参见[组件属性](https://developer.open-douyin.com/docs/resource/zh-CN/mini-app/develop/component/media-component/video/)中 bind 开头的事件属性。

### 组件对象提供事件订阅的机制进行事件监听
小程序播放器提供了接口可以获取player context，并可以对player添加事件订阅。具体方式如下：

```javascript
let player = null
const component = this.selectComponent("#videoContainer", (component) => {
  player = component.getContext()
  // 事件订阅
  player.on('error', (e) => {
    console.log('event error:', e)
  })
  player.on('timeupdate', (e) => {
    const { currentTime, duration } = e.detail;
    console.log('event error:', currentTime, duration)
  })
  // ...
});
```

详细的事件列表: 

| EventName          | CustomEvent | Description                   |
|--------------------|-------------|-------------------------------|
| play               | 否           | 参见属性 bindplay 描述              | 
| pause              | 否           | 参见属性 bindpause 描述             | 
| ended              | 否           | 参见属性 bindended 描述             | 
| timeupdate         | 否           | 参见属性 bindtimeupdate 描述        | 
| fullscreenchange   | 否           | 参见属性 bindfullscreenchange 描述  |  
| waiting            | 否           | 参见属性 bindwaiting 描述           |  
| error              | 否           | 参见属性 binderror 描述             | 
| progress           | 否           | 参见属性 bindprogress 描述          |  
| loadedmetadata     | 否           | 参见属性 bindloadedmetadata 描述    | 
| playbackratechange | 否           | 参见属性 bindplaybackratechange 描述 | 
| enterbackground    | 否           | 参见属性 bindenterbackground 描述   | 
| closebackground    | 否           | 参见属性 bindclosebackground 描述   | 
| leavebackground    | 否           | 参见属性 bindleavebackground 描述   | 
| seeking            | 是           | 参见属性 bindseeking 描述           | 
| seekcomplete       | 否           | 参见属性 bindseekcomplete 描述      | 
| controlstoggle         | 否           | 参见属性 bindcontrolstoggle 描述      | 
| getsource          | 否           | 获取到视频信息,仅短剧播放模式下触发            |
| useraction          | 是           | 用户行为触发，如用户点击暂停、滑动进度条                           |



## uni-app 项目使用

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

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

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

### 2. 拷贝组件到项目目录
拷贝`node_modules/veplayer-mp-douyin`到项目小程序组件存放目录`ttcomponents`（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": "/ttcomponents/veplayer-mp-douyin/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', (e) => {
      const { currentTime, duration } = 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。


## 短剧行业能力
播放器继承了抖音[短剧行业能力](https://bytedance.larkoffice.com/wiki/SG1MwJyWhiqwUxkkZvjcConanue)，使用方法参照以下说明：
### 前提条件
按照[官网文档](https://developer.open-douyin.com/docs/resource/zh-CN/mini-app/develop/guide/industry-ability/industrySDK/)配置行业 SDK 的权限配置。
### 使用组件
短剧行业能力依赖`video-player`,`video-player` 只在 抖音23.0以上版本支持，播放器组件会自动使用 `tt.canIUse('video-player')` 校验当前抖音能否使用。若监测到不支持时，组件会自动降级为`video`组件进行播放，此时请确保传入了正确有效的视频地址，或者引导用户升级抖音版本。


```xml
<veplayer
  id="video"
  albumId="{{aid}}" 
  episodeId="{{eid}}"
  src="{{degradeSrc}}"
  autoplay
  bindgetsource="getSource"
  ...
></veplayer>
```

```javascript
Component({
  // ...
  data: {
    aid: 'x32432w',
    eid: 'xxsddw',
    // 抖音23.0以下版本不支持短剧行业能力时使用的兜底地址
    degradeSrc: 'https://xx.demo.com/d.mp4'
  },
  methods: {
    getSource(e){
      // do something
    },
    playVideo(){
      // do something
      this.player.play()
    }
  }
})
```

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

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

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

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

### 3. 配置组件引入
在使用到播放器组件所在页面的`index.config.ts`配置中引入组件：
```typescript
export default definePageConfig({
    navigationBarTitleText: '',
    navigationBarTextStyle: 'black',
    navigationStyle: 'custom',
    disableScroll: true,
    usingComponents: {
        veplayer: '../../ttcomponents/veplayer-mp-douyin/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
  // ...
};
```
