视频点播为抖音小程序播放场景提供播放器 SDK 和滑动切换组件,助您实现需要的业务功能。
具体效果如下:
https://mcs.zijieapi.com
。操作截图示例如下。说明
视频资源的 CDN 域名不需要添加到域名配置中。
运行以下命令添加依赖:
# npm npm i veplayer-mp-douyin // 播放器 SDK npm i veplayer-mp-swiper-douyin // 滑动切换组件 # yarn yarn add veplayer-mp-douyin // 播放器 SDK yarn add veplayer-mp-swiper-douyin // 滑动切换组件
说明
构建前,请先了解抖音开放平台官网对于 npm 功能的介绍。
在抖音开发者工具编辑器左侧功能栏 NPM功能:依赖管理中点击 npm 构建。
在页面的 JSON 文件中引入 SDK 和组件。详情请参考抖音小程序自定义组件的使用方式。
{ "usingComponents": { "veplayer": "ext://veplayer-mp-douyin/veplayer" // 播放器 SDK "veplayer-swiper": "ext://veplayer-mp-swiper-douyin/veplayer-swiper", // 滑动切换组件容器 "veplayer-swiper-item": "ext://veplayer-mp-swiper-douyin/veplayer-swiper-item" // 滑动切换组件播放器容器 } }
注意
如果您使用的是抖音开发者工具 4.1.0 之前的版本,请注意其 npm 功能存在缺陷。您需要手动将 node_modules
下的 veplayer-mp-douyin
复制到 components
内,并删掉 package.json
中的 veplayer-mp-douyin
依赖。之后,您需要更新组件引用路径为 /components/veplayer-mp-douyin/dist/index
。
按照如下示例代码在项目中引用播放器 SDK。
<view> <!-- 以下是对小程序播放器 SDK 的引用 --> <veplayer id="videoContainer" src="{{src}}" muted loop logInfo="{{logInfo}}" /> </view>
您需要在对应应业务组件中添加日志上报所需的配置,如下表所示:
属性名 | 类型 | 是否必选 | 默认值 | 说明 |
---|---|---|---|---|
appId | Number | 是 | - | 应用 ID。可在火山引擎视频点播控制台上获取应用 ID,具体步骤请见创建应用。 |
userId | String | 否 | - | 用户 ID。强烈建议您使用与业务密切相关的用户 ID,以便在播放过程中出现错误时,可以进行单点故障排查,精确定位问题。如果您没有设定用户 ID,SDK 将随机生成一个值。 |
tag | String | 否 | - | 业务标签或业务类型,用于标记不同的播放场景,如推荐页、详情页。 |
subTag | String | 否 | - | 子业务标签或业务类型,用于细分播放场景。 |
vtype | HLS 或 MP4 | 否 | MP4 | 视频格式 |
codecType | String | 否 | h264 | 视频编码格式 |
bitrate | Number | 否 | 0 | 视频码率 |
appName | String | 否 | 小程序 | 应用名称 |
appVersion | String | 否 | 1.0.0 | 应用版本 |
示例代码如下:
// index.js Component({ data: { src: 'https://xxxx.mp4', // 配置日志上报 logInfo: { appId: xxx, userId: "xxx", tag: 'recommend', subtag: 'hot', } } })
视频信息配置完成后,如需查看日志上报数据,可以按以下操作步骤进行:
说明
我们只收集 Android 和 iOS 真机上运行的小程序播放数据。通常数据存在 5-10 分钟的延时。如果长时间看不到数据,可能是因为您通过开发者工具模拟器或桌面端微信播放的小程序数据被过滤掉了。
滑动切换组件包含以下两个部分:
veplayer-swiper
: 基于抖音小程序开放平台的 swiper 开发,可作为轮播视图的容器。veplayer-swiper-item
: 基于抖音小程序开放平台的 swiper-item 开发,可作为播放器的容器。在 player/index.ttml
文件引用 veplayer-swiper
和 veplayer-swiper-item
组件。请注意以下参数的设置:
index
:播放列表的序号。current
:swiper
激活项,需要与 veplayer-swiper
的 current
保持一致。videoId
:为播放器内原生 video
组件的 ID,也对应小程序播放器 SDK 的 componentId
属性。videoId
作用是在切换视频时实现自动播放的效果,因此请确保在播放列表中,每一项的 videoId
是唯一的。此外,为了实现用户第一次进入播放页面时以及选集后自动播放视频,推荐将播放器的 autoplay
属性设置为 autoplay="{{index === current}}"
。
示例代码如下:
<veplayer-swiper current="{{current}}" class="swiper" bindchange="onChange" bindanimationfinish="onAnimationfinish" bindtransition="onTransition" > <block tt:for="{{list}}" tt:for-item="item" tt:for-index="index" > <veplayer-swiper-item videoId="{{item.vid}}" poster="{{item.poster}}" index="{{index}}" current="{{current}}" preloadSrc="{{item.src}}" > <view slot="video" style="width: 100%; height:100%; position: relative"> <veplayer src="{{item.src}}" poster="{{item.poster}}" autoplay="{{index === current}}" componentId="{{item.vid}}" playBtnPosition="bottom" enableProgressGesture="{{true}}" enablePlayGesture="{{true}}" bindended="onEnded" bindplay="onPlay" bindpause="onPause" ></veplayer> <!-- 业务功能点赞 --> <view style="right: 20px; top:50%; position: absolute; color: #fff">❤️</view> </view> </veplayer-swiper-item> </block> </veplayer-swiper>
在 player/index.js
文件中,您需要监听 veplayer-swiper
的 change
事件,更新 current
的值。示例代码如下:
const videoList = [ { vid: 'v0ddfag10001c*****k63casl9ed0', poster: 'https://demo.video.com/poster.jpg', src: 'https://demo.video.com/video.mp4', des: '', }, // ... ]; Component({ data: { current: 0, list: VideoList }, onChange(e) { // 监听 veplayer-swiper 的 change 事件,更新 current 的值 this.setData({ current: e.detail.detail.current }); }, })
您可以监听 onEnded
事件。在该事件的回调函数中,设置 veplayer-swiper
和veplayer-swiper-item
这两个组件的 current
属性。这样一来,播放完当前集之后,小程序就会自动播放下一集。
示例代码如下:
<veplayer slot="video" src="{{item.src}}" poster="{{item.poster}}" autoplay="{{index === current}}" componentId="{{item.vid + item.src}}" playBtnPosition="bottom" enableProgressGesture="{{true}}" enablePlayGesture="{{true}}" bindended="onEnded" ></veplayer>
onEnded() { const { current, list } = this.data; if (current + 1 < list.length) { // 设置 swiper 的 current 属性 this.setData({ current: current + 1 }); } else { tt.showToast({ title: '看完了!', duration: 2000, }); } }
如果您希望实现在剧集列表中通过点击剧集按钮来使播放器跳转至特定剧集,可设置veplayer-swiper
的 current
属性。
示例代码如下:
onSelectChange(e) { this.setData({ // 设置指定剧集的序号跳转到指定剧集 current: target }); }
播放器 SDK 继承了抖音小程序 video-player 组件提供的短剧行业能力,方便开发者通过抖音小程序内容库对短剧内容进行送审。
video-player
组件。video-player
只在抖音 23.8 以上版本支持。播放器组件会自动使用 tt.canIUse('video-player')
校验用户的抖音版本能否支持 video-player
组件。在项目中引用播放器 SDK 时,传入album-id
(原片 ID)和 episode-id
(剧集 ID)。播放器 SDK 会通过这两个 ID 从抖音小程序内容库中获取视频播放地址。
示例代码如下:
<veplayer id="video" tt:ref="refHandler" album-id="{{aid}}" episode-id="{{eid}}" autoplay="{{true}}" bindgetsource="getSource" ... ></veplayer>
在对应业务组件中添加播放配置,示例代码如下:
Component({ // ... data: { aid: 'x32432w', eid: 'xxsddw', // 抖音 23.8 以下版本不支持短剧行业能力时使用的兜底地址 degradeSrc: 'https://xx.demo.com/d.mp4' }, methods: { refHandler(ref) { this.player = ref; }, getSource(e){ // do something }, playVideo(){ // do something const videoContext = this.player.media; videoContext.play() } } })
注意
index.json
里用相对路径引用 npm 包。video-player
覆盖率是 50%,不符合平台要求,将会被封禁支付能力。album-id
应修改为 albumId
。initialData
错误,请在项目的 page.json
文件中添加 "component2": false
配置。播放器 SDK 封装了抖音原生 video
视频组件,支持配置大部分的 video
属性。原生 video
视频组件支持的属性详见抖音官方文档。
下表展示播放器 SDK 的新增属性及差异化属性。
说明
show-
开头的开关,既影响原生 video
视频组件,又影响自定义 UI。video
视频组件。video
视频组件的属性,如 show-play-btn
这类中划线分割的属性名,需要改写成驼峰式命名 showPlayBtn
。属性 | 类型 | 默认值 | 是否必选 | 说明 |
---|---|---|---|---|
mode | 'portrait' | 'landscape' |
| 否
|
disableLogVerify | Boolean |
| 否 | 关闭日志配置验证。取值如下:
|
componentId | String | 无 | 否 | video 组件 ID。
|
logInfo | Object | 无 | 否 | 日志上报时用到的视频信息。 |
src | String | 无 | 否 | 播放视频的资源地址。支持网络路径、本地临时路径、云文件 ID 等。 |
album-id | String | 无 | 否 | 原片 ID。接入抖音小程序短剧行业能力时必传。 |
episode-id | String | 无 | 否 | 剧集 ID。接入抖音小程序短剧行业能力时必传。 |
cloud-type | Number | 1 | 否 | CDN 类型。接入抖音小程序短剧行业能力时可传。取值如下:
|
three-party-cloud | String | 无 | 否 | 三方云链接。当 |
controls | 'custom' | 'native' | 'false' | 'focus'
说明
|
playBtnPosition | 'center' | 'bottom' | 'center-bottom' | bottom
|
duration | Number | 无 | 否 | 指定视频时长。 说明 不会控制实际播放的时长。因此该属性不设置给原生 |
showFullscreenBtn | Boolean |
| 否 | 是否展示全屏播放按钮。取值如下:
|
needLoading | Boolean |
| 否 | 是否显示 loading 加载标识。 说明
|
isShowDataLoading | Boolean |
| 否 | 是否展示数据加载标识,即获取地址时展示 loading。取值如下:
|
loadingText | String | 无 | 否 | 设置数据加载标识的文字描述。 |
veDebugger | Boolean |
| 否 | 用于开启内置日志打印。取值如下:
|
allowNullSource | Boolean |
| 否 | 是否允许空资源起播。取值如下:
说明
|
timeUpdateInterval | Number | 400 | 否 | 进度条更新的频率,单位为 ms。用于减少频繁的渲染造成内存升高的问题。 |
autoBlurTime | Number | 15000 | 否 | 自动失焦,即播放器在处于激活态,用户无操作多长时间隐藏播控。 |
interactiveConfig |
|
| 否 | 响应式配置。取值如下:
|
enableTapActive | Boolean | true | 否 | 是否启用点击触发激活(进入 focus 态) 说明 当自定义 |
bindplay | eventhandle | 否 | 当开始/继续播放时触发 | |
bindpause | eventhandle | 否 | 当暂停播放时触发 | |
bindended | eventhandle | 否 | 当播放到末尾时触发 | |
bindtimeupdate | eventhandle | 否 | 播放进度变化时触发
| |
bindfullscreenchange | eventhandle | 否 | 视频进入和退出全屏时触发
| |
bindwaiting | eventhandle | 否 | 视频出现缓冲时触发 | |
binderror | eventhandle | 否 | 视频播放出错时触发 | |
bindprogress | eventhandle | 否 | 加载进度变化时触发
| |
bindloadedmetadata | eventhandle | 否 | 视频元数据加载完成时触发
| |
bindplaybackratechange | eventhandle | 否 | 视频倍速改变完成时触发。返回改变后的倍速值。
| |
bindenterbackground | eventhandle | 否 | 进入小窗播放时触发。 | |
bindclosebackground | eventhandle | 否 | 关闭小窗播放时触发。 | |
bindleavebackground | eventhandle | 否 | 离开小窗进入 app 事件时触发 | |
bindseekcomplete | eventhandle | 否 | seek 完成时触发 说明
| |
binduseraction | eventhandle | 否 | 用户行为触发。例如,用户点击暂停、滑动进度条。 |
播放器 SDK 封装了 VideoContext,提供同原生接口一致的 API。示例代码如下所示。
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() // ...
播放器 SDK 提供两种方式进行事件监听:
bind
属性对组件进行事件监听。我们建议您在使用时,选择其中一种方式进行事件订阅,而不是同时使用两种方式。这两种方式都已在组件实例中实现了组件从页面节点树移除(lifetimes->detached)时的事件解绑,因此,您无需单独处理事件泄漏的问题。
bind
属性对组件进行事件监听请参见组件属性中 bind
开头的事件属性。
播放器 SDK 提供接口用于获取 player context。您可为 player
添加事件订阅,从而实现任意时刻对各种播放事件添加和移除监听。示例代码如下:
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) }) ... });
详细的事件列表如下所示。
事件名称 | 是否可自定义事件 | 说明 |
---|---|---|
play | 否 | 当开始/继续播放时触发 |
pause | 否 | 当暂停播放时触发 |
ended | 否 | 当播放到末尾时触发 |
timeupdate | 否 | 播放进度变化时触发 |
fullscreenchange | 否 | 视频进入和退出全屏时触发 |
waiting | 否 | 视频出现缓冲时触发 |
error | 否 | 视频播放出错时触发 |
progress | 否 | 加载进度变化时触发 |
loadedmetadata | 否 | 视频元数据加载完成时触发 |
playbackratechange | 否 | 视频倍速改变完成时触发。返回改变后的倍速值。 |
enterbackground | 否 | 进入小窗播放时触发。 |
closebackground | 否 | 关闭小窗播放时触发。 |
leavebackground | 否 | 离开小窗进入 app 事件时触发。 |
seekcomplete | 否 | Seek 完成时触发 |
controlstoggle | 否 | 切换 |
useraction | 是 | 用户行为触发,如用户点击暂停、滑动进度条。 |
veplayer-swiper
组件属性属性名 | 类型 | 默认值 | 必填 | 说明 |
---|---|---|---|---|
current | Number |
| 是 | 当前选中视频所在滑块的索引。 |
duration | Number |
| 否 | 滑动动画时长,单位为 ms。 |
easingFunction | String |
| 否 | Swiper 切换缓动动画类型,有效值:
|
vertical | Boolean |
| 否 | 竖直方向。取值如下:
|
showLoadingWhenChange | Boolean |
| 否 | 切换选集时是否展示 Loading。取值如下:
|
loadingText | String | "" | 否 | 切换选集的 Loading 文案。 |
indicatorDots | Boolean |
| 否 | 是否显示面板指示点。取值如下:
说明 播放场景中建议不传入此参数。 |
indicatorColor | Color | rgba(0, 0, 0, .3) | 否 | 指示点颜色。 说明 播放场景中建议不传入此参数。 |
indicatorActiveColor | Color | rgba(0, 0, 0, 0) | 否 | 当前选中的指示点颜色。 说明 播放场景中建议不传入此参数。 |
autoplay | Boolean |
| 否 | 是否自动切换。取值如下:
说明 播放场景中建议不传入此参数。 |
currentItemId | String | "" | 否 | 当前选中滑块的组件 ID。 说明
|
interval | Number |
| 否 | 自动切换时间间隔,单位为 ms。 说明 播放场景中建议不传入此参数。 |
previousMargin | String | "" | 否 | 前边距,可以用露出前一项的一小部分,支持 px 和 rpx,默认单位为 px。 说明 播放场景中建议不传入此参数。 |
nextMargin | String | "" | 否 | 后边距,可用于露出后一项的一小部分,支持 px 和 rpx,默认单位为 px。 说明 播放场景中建议不传入此参数。 |
displayMultipleItems | Number |
| 否 | 同时显示的滑块数量。 说明 播放场景中建议不传入此参数。 |
circular | Boolean |
| 否 | 是否循环播放(首尾衔接) 说明 播放场景中建议不传入此参数。 |
bindchange | EventHandle | 否 |
| |
bindanimationfinish | EventHandle | 否 | 动画结束时会触发 | |
bindtransition | EventHandle | 否 | wiper-item 产生位移时触发 |
说明
在播放场景(例如微短剧场景)中,建议不要传入 indicatorDots
、indicatorColor
、indicatorActiveColor
、autoplay
、currentItemId
、interval
、previousMargin
、nextMargin
、displayMultipleItems
和 circular
属性,使用滑动切换组件的默认值即可。
veplayer-swiper-item
组件属性属性名 | 类型 | 默认值 | 必填 | 说明 |
---|---|---|---|---|
videoId | String | 是 | 视频 ID,对应播放器 SDK 的 | |
index | Number |
| 是 | 当前 |
current | Number |
| 是 | 当前 |
itemId | String | 否 | 该 | |
poster | String | 否 | 用于不渲染播放器时兜底的封面图。 | |
preloadSrc | String | 否 | 视频预加载路径。值同该 说明
| |
preloadNum | Number |
| 否 | 多实例预加载的数目,即最多同时加载的播放器数目。 说明 (推荐)保持默认值不做修改。 |
veplayer-swiper-item
组件插槽veplayer-swiper-item
组件提供了两个具名插槽 slot:
video
插槽:此插槽用于放置播放器。对于播放器类型没有限制,但请确保播放器的原生 video
属性必须绑定一个唯一 ID。这个 ID 需要传递给 veplayer-swiper-item
的 videoId
属性,用于控制视频的播放与暂停。placeholder
插槽:此插槽用于播放器未渲染时的占位。如果你没有设置此插槽,那么默认会使用封面图片地址 poster
作为占位图。