---
name: "Video"
mode: "component"
versionRequirements:
  - { name: "@ray-js/ray", version: "1.4.24" }
title: "Video - 视频"
---

## Video

> [VERSION] @ray-js/ray >= 1.4.24

### 描述

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

### 属性

| 属性 | 类型 | 必填 | 默认值 | 描述 |
| --- | --- | --- | --- | --- |
| `src` | `string` | 是 | - | 要播放视频的资源地址，支持网络路径 |
| `duration` | `number` | 否 | `0` | 指定视频时长 |
| `controls` | `boolean` | 否 | `true` | 是否显示默认播放控件（播放/暂停按钮、播放进度、时间） |
| `danmuList` | `VideoDanmuItem[]` | 否 | - | 弹幕列表 |
| `danmuBtn` | `boolean` | 否 | `false` | 是否显示弹幕按钮，只在初始化时有效，不能动态变更 |
| `enableDanmu` | `boolean` | 否 | `false` | 是否展示弹幕，只在初始化时有效，不能动态变更 |
| `autoplay` | `boolean` | 否 | `false` | 是否自动播放 |
| `loop` | `boolean` | 否 | `false` | 是否循环播放 |
| `muted` | `boolean` | 否 | `false` | 是否静音播放 |
| `initialTime` | `number` | 否 | `0` | 指定视频初始播放位置 |
| `showFullscreenBtn` | `boolean` | 否 | `true` | 是否显示全屏按钮 |
| `showPlayBtn` | `boolean` | 否 | `true` | 是否显示视频底部控制栏的播放按钮 |
| `showCenterPlayBtn` | `boolean` | 否 | `true` | 是否显示视频中间的播放按钮 |
| `objectFit` | `"contain" \| "fill" \| "cover"` | 否 | `"contain"` | 当视频大小与 video 容器大小不一致时，视频的表现形式 |
| `poster` | `string` | 否 | - | 视频封面的图片网络资源地址 |
| `showMuteBtn` | `boolean` | 否 | `false` | 是否显示静音按钮 |
| `autoPause` | `boolean` | 否 | `true` | 非可视区域是否自动暂停 |
| `onPlay` | `(event: BaseEvent) => void` | 否 | - | 当开始/继续播放时触发 |
| `onPause` | `(event: BaseEvent) => void` | 否 | - | 当暂停播放时触发 |
| `onEnded` | `(event: BaseEvent) => void` | 否 | - | 当播放到末尾时触发 |
| `onWaiting` | `(event: BaseEvent) => void` | 否 | - | 视频出现缓冲时触发 |
| `onError` | `(event: VideoErrorEvent) => void` | 否 | - | 视频播放出错时触发 |
| `onProgress` | `(event: VideoProgressEvent) => void` | 否 | - | 加载进度变化时触发，只支持一段加载 |
| `onLoadedmetadata` | `(event: VideoLoadedmetadataEvent) => void` | 否 | - | 视频元数据加载完成时触发 |
| `onCanplay` | `(event: BaseEvent) => void` | 否 | - | 当浏览器可以播放视频时触发 |
| `onCanplayThrough` | `(event: BaseEvent) => void` | 否 | - | 当浏览器可在不因缓冲而停顿的情况下进行播放时触发 |
| `onPlaying` | `(event: BaseEvent) => void` | 否 | - | 当视频在已因缓冲而暂停或停止后已就绪时触发 |
| `onRateChange` | `(event: BaseEvent) => void` | 否 | - | 当视频的播放速度已更改时触发 |
| `onVolumeChange` | `(event: BaseEvent) => void` | 否 | - | 当音量已更改时触发 |
| `onSeekComplete` | `(event: VideoSeekCompleteEvent) => void` | 否 | - | seek 完成时触发 |

### 引用对象

##### `interface` VideoDanmuItem

| 属性 | 类型 | 描述 |
| --- | --- | --- |
| `text` | `string` | 弹幕文本 |
| `color` | `string` | 弹幕颜色 |
| `time` | `number` | 弹幕出现时间，单位秒 |

##### `interface` BaseEvent

| 属性 | 类型 | 描述 |
| --- | --- | --- |
| `type` | `string` | 事件类型 |
| `timeStamp` | `number` | 页面打开到触发事件所经过的毫秒数 |
| `target` | `Target` | 触发事件的源组件 |
| `currentTarget` | `Target` | 当前组件的一些属性值集合 |
| `mark` | `any` | 事件标记数据 |

##### `interface` VideoErrorEvent

| 属性 | 类型 | 描述 |
| --- | --- | --- |
| `detail` | `VideoErrorDetail` |  |

##### `interface` VideoProgressEvent

| 属性 | 类型 | 描述 |
| --- | --- | --- |
| `detail` | `VideoProgressDetail` |  |

##### `interface` VideoLoadedmetadataEvent

| 属性 | 类型 | 描述 |
| --- | --- | --- |
| `detail` | `VideoLoadedmetadataDetail` |  |

##### `interface` VideoSeekCompleteEvent

| 属性 | 类型 | 描述 |
| --- | --- | --- |
| `detail` | `VideoSeekCompleteDetail` |  |

##### `interface` Target

| 属性 | 类型 | 描述 |
| --- | --- | --- |
| `id` | `string` | 事件源组件的id |
| `dataset` | `Record<string, unknown>` | 事件源组件上的 `dataset` 自定义属性组成的集合 |

##### `interface` VideoErrorDetail

| 属性 | 类型 | 描述 |
| --- | --- | --- |
| `errMsg` | `string` | 错误信息 |

##### `interface` VideoProgressDetail

| 属性 | 类型 | 描述 |
| --- | --- | --- |
| `buffered` | `number` | 缓冲百分比 |

##### `interface` VideoLoadedmetadataDetail

| 属性 | 类型 | 描述 |
| --- | --- | --- |
| `width` | `number` | 视频宽度 |
| `height` | `number` | 视频高度 |
| `duration` | `number` | 视频时长 |

##### `interface` VideoSeekCompleteDetail

| 属性 | 类型 | 描述 |
| --- | --- | --- |
| `position` | `number` | 播放位置（iOS 单位为秒，Android 为毫秒，具体以端为准） |


### 示例代码

#### 基础用法

```tsx
import React from 'react';
import { Video, View } from '@ray-js/ray';

export default function () {
  return (
    <View style={{ padding: '20px' }}>
      <Video
        src="https://images.tuyacn.com/rms-static/602542e0-48f8-11f1-95db-cfd3b8132c07-1778036702734.mp4"
        controls
        style={{ width: '100%', height: '200px' }}
        onPlay={() => console.log('开始播放')}
        onPause={() => console.log('暂停播放')}
        onEnded={() => console.log('播放结束')}
      />
    </View>
  );
}
```

#### 播放配置

```tsx
import React from 'react';
import { Video, View } from '@ray-js/ray';

export default function () {
  return (
    <View style={{ padding: '20px' }}>
      <Video
        src="https://images.tuyacn.com/rms-static/602542e0-48f8-11f1-95db-cfd3b8132c07-1778036702734.mp4"
        poster="https://vjs.zencdn.net/v/oceans.png"
        controls
        autoplay={false}
        loop
        muted
        initialTime={5}
        objectFit="cover"
        showFullscreenBtn
        showPlayBtn
        showCenterPlayBtn={false}
        showMuteBtn
        autoPause
        style={{ width: '100%', height: '200px' }}
        onError={(e) => console.log('播放错误:', e.detail.errMsg)}
        onWaiting={() => console.log('缓冲中')}
      />
    </View>
  );
}
```

#### 弹幕与事件

```tsx
import React from 'react';
import { Video, View } from '@ray-js/ray';

export default function () {
  return (
    <View style={{ padding: '20px' }}>
      <Video
        src="https://images.tuyacn.com/rms-static/602542e0-48f8-11f1-95db-cfd3b8132c07-1778036702734.mp4"
        controls
        enableDanmu
        danmuBtn
        danmuList={[
          { text: '精彩', color: '#ff0000', time: 1 },
          { text: '好看', color: '#00ff00', time: 3 },
          { text: '太棒了', color: '#0000ff', time: 5 },
        ]}
        style={{ width: '100%', height: '200px' }}
        onPlay={() => console.log('开始播放')}
        onPause={() => console.log('暂停')}
        onEnded={() => console.log('播放结束')}
        onProgress={(e) => console.log('缓冲:', e.detail.buffered + '%')}
        onLoadedmetadata={(e) => console.log('元数据:', e.detail.width, 'x', e.detail.height, '时长:', e.detail.duration)}
        onSeekComplete={(e) => console.log('seek 完成:', e.detail.position)}
      />
    </View>
  );
}
```


### 相关链接

相关 API: [createVideoContext](/cn/miniapp/develop/miniapp/api/media/video/createVideoContext)

<DemoBlock 
  githubUrl="https://github.com/Tuya-Community/tuya-miniapp-demo/tree/master/rayVideo" 
  qrCodeUrl="/images/qrCode/rayVideo.png" 
  lang="zh">
</DemoBlock>

### 常见问题

#### Video 默认宽高和格式

1. `video` 默认宽度 300px、高度 225px，可通过 tyss 设置宽高。
2. `video` 支持三种视频格式：MP4、WebM、Ogg。
   - MP4 = MPEG 4 文件使用 H264 视频编解码器和 AAC 音频编解码器
   - WebM = WebM 文件使用 VP8 视频编解码器和 Vorbis 音频编解码器
   - Ogg = Ogg 文件使用 Theora 视频编解码器和 Vorbis 音频编解码器

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

可通过`onTimeupdate` 获取视频播放时长。
