---
name: "video"
mode: "component"
versionRequirements:
  - { name: "基础库", version: "2.10.0" }
title: "video - 视频"
---

## video

> [VERSION] 基础库 >= 2.10.0

### 描述

视频组件，支持播放控件、弹幕与全屏。

### 属性

| 属性 | 类型 | 必填 | 默认值 | 描述 |
| --- | --- | --- | --- | --- |
| `src` | `string` | 是 | - | 视频资源地址 |
| `poster` | `string` | 否 | - | 封面图片地址 |
| `controls` | `boolean` | 否 | `true` | 是否显示默认播放控件 |
| `duration` | `number` | 否 | `0` | 指定视频时长 |
| `autoplay` | `boolean` | 否 | `false` | 是否自动播放 |
| `loop` | `boolean` | 否 | `false` | 是否循环播放 |
| `muted` | `boolean` | 否 | `false` | 是否静音播放 |
| `initial-time` | `number` | 否 | `0` | 初始化播放位置，单位秒 |
| `object-fit` | `string` | 否 | `"contain"` | 当视频大小与 video 容器大小不一致时的表现，可选值：contain 包含，fill 填充，cover 覆盖 |
| `danmu-list` | `any[]` | 否 | `[]` | 弹幕列表 |
| `danmu-btn` | `boolean` | 否 | `false` | 是否显示弹幕按钮 |
| `enable-danmu` | `boolean` | 否 | `false` | 是否展示弹幕 |
| `show-fullscreen-btn` | `boolean` | 否 | `true` | 是否显示全屏按钮 |
| `show-play-btn` | `boolean` | 否 | `true` | 是否显示视频底部控制栏的播放按钮 |
| `show-mute-btn` | `boolean` | 否 | `false` | 是否显示静音按钮 |
| `show-center-play-btn` | `boolean` | 否 | `true` | 是否显示视频中间的播放按钮 |
| `auto-pause` | `boolean` | 否 | `true` | 是否在离开页面时自动暂停 |

#### 事件

| 事件名 | 类型 | 描述 |
| --- | --- | --- |
| `play` | `(event: Object) => void` | 开始/继续播放时触发 |
| `pause` | `(event: Object) => void` | 暂停时触发 |
| `ended` | `(event: Object) => void` | 播放结束时触发 |
| `timeupdate` | `(event: VideoTimeupdateEvent) => void` | 播放进度变化时触发 |
| `waiting` | `(event: Object) => void` | 视频出现缓冲时触发 |
| `error` | `(event: VideoErrorEvent) => void` | 视频播放出错时触发 |
| `progress` | `(event: VideoProgressEvent) => void` | 加载进度变化时触发 |
| `loadedmetadata` | `(event: VideoLoadedmetadataEvent) => void` | 视频元数据加载完成时触发 |
| `seekcomplete` | `(event: Object) => void` | seek 完成时触发 |

**play 的回调参数对象**

| 字段 | 类型 | 说明 |
| --- | --- | --- |
| `type` | `"play"` |  |

**pause 的回调参数对象**

| 字段 | 类型 | 说明 |
| --- | --- | --- |
| `type` | `"pause"` |  |

**ended 的回调参数对象**

| 字段 | 类型 | 说明 |
| --- | --- | --- |
| `type` | `"ended"` |  |

**VideoTimeupdateEvent**

| 字段 | 类型 | 说明 |
| --- | --- | --- |
| `type` | `"timeupdate"` | 事件类型 |
| `detail` | `VideoTimeupdateDetail` | 事件数据 |

**waiting 的回调参数对象**

| 字段 | 类型 | 说明 |
| --- | --- | --- |
| `type` | `"waiting"` |  |

**VideoErrorEvent**

| 字段 | 类型 | 说明 |
| --- | --- | --- |
| `type` | `"error"` | 事件类型 |
| `detail` | `VideoErrorDetail` | 事件数据 |

**VideoProgressEvent**

| 字段 | 类型 | 说明 |
| --- | --- | --- |
| `type` | `"progress"` | 事件类型 |
| `detail` | `VideoProgressDetail` | 事件数据 |

**VideoLoadedmetadataEvent**

| 字段 | 类型 | 说明 |
| --- | --- | --- |
| `type` | `"loadedmetadata"` | 事件类型 |
| `detail` | `VideoLoadedmetadataDetail` | 事件数据 |

**seekcomplete 的回调参数对象**

| 字段 | 类型 | 说明 |
| --- | --- | --- |
| `type` | `"seekcomplete"` |  |

### 示例代码

#### 基础用法

*index.tyml*

```xml
<video
  src="{{videoSrc}}"
  controls="{{true}}"
  class="video"
  bindplay="onPlay"
  bindpause="onPause"
  bindended="onEnded"
/>
```

*index.tyss*

```css
.video {
  width: 100%;
  height: 400rpx;
}
```

*index.js*

```javascript
Page({
  data: {
    videoSrc: 'https://images.tuyacn.com/rms-static/602542e0-48f8-11f1-95db-cfd3b8132c07-1778036702734.mp4',
  },
  onPlay() {
    console.log('开始播放');
  },
  onPause() {
    console.log('暂停播放');
  },
  onEnded() {
    console.log('播放结束');
  },
});
```

#### 播放配置与封面

*index.tyml*

```xml
<video
  src="{{videoSrc}}"
  poster="{{posterUrl}}"
  controls="{{true}}"
  autoplay="{{false}}"
  loop="{{true}}"
  muted="{{true}}"
  initial-time="{{5}}"
  object-fit="cover"
  show-fullscreen-btn="{{true}}"
  show-play-btn="{{true}}"
  show-center-play-btn="{{false}}"
  show-mute-btn="{{true}}"
  class="video"
  binderror="onError"
  bindwaiting="onWaiting"
/>
```

*index.tyss*

```css
.video {
  width: 100%;
  height: 400rpx;
}
```

*index.js*

```javascript
Page({
  data: {
    videoSrc: 'https://images.tuyacn.com/rms-static/602542e0-48f8-11f1-95db-cfd3b8132c07-1778036702734.mp4',
    posterUrl: 'https://vjs.zencdn.net/v/oceans.png',
  },
  onError(e) {
    console.log('播放错误:', e.detail.errMsg);
  },
  onWaiting() {
    console.log('缓冲中');
  },
});
```

#### 弹幕与事件

*index.tyml*

```xml
<video
  src="{{videoSrc}}"
  controls="{{true}}"
  enable-danmu="{{true}}"
  danmu-btn="{{true}}"
  danmu-list="{{danmuList}}"
  class="video"
  bindprogress="onProgress"
  bindloadedmetadata="onLoadedmetadata"
  bindseekcomplete="onSeekComplete"
/>
```

*index.tyss*

```css
.video {
  width: 100%;
  height: 400rpx;
}
```

*index.js*

```javascript
Page({
  data: {
    videoSrc: 'https://images.tuyacn.com/rms-static/602542e0-48f8-11f1-95db-cfd3b8132c07-1778036702734.mp4',
    danmuList: [
      { text: '精彩', color: '#ff0000', time: 1 },
      { text: '好看', color: '#00ff00', time: 3 },
      { text: '太棒了', color: '#0000ff', time: 5 },
    ],
  },
  onProgress(e) {
    console.log('缓冲:', e.detail.buffered + '%');
  },
  onLoadedmetadata(e) {
    console.log('元数据:', e.detail.width, 'x', e.detail.height, '时长:', e.detail.duration);
  },
  onSeekComplete() {
    console.log('seek 完成');
  },
});
```


### 相关文档

- 相关 API：[ty.createVideoContext](/cn/miniapp/develop/miniapp/api/media/video/createVideoContext)

### 注意事项

1. `video` 默认宽度 300px、高度 225px，可通过 tyss 设置宽高。

2. `video` 支持三种视频格式：MP4、WebM、Ogg。

- MP4 = MPEG 4 文件使用 H264 视频编解码器和 AAC 音频编解码器
- WebM = WebM 文件使用 VP8 视频编解码器和 Vorbis 音频编解码器
- Ogg = Ogg 文件使用 Theora 视频编解码器和 Vorbis 音频编解码器

### 常见问题

#### 如何获取视频播放进度？

可通过`bind:timeupdate` 获取视频播放时长。
