<!-- START doctoc generated TOC please keep comment here to allow auto update -->
<!-- DON'T EDIT THIS SECTION, INSTEAD RE-RUN doctoc TO UPDATE -->
**Table of Contents**  *generated with [DocToc](https://github.com/thlorenz/doctoc)*

- [简介](#%E7%AE%80%E4%BB%8B)
  - [功能列表](#%E5%8A%9F%E8%83%BD%E5%88%97%E8%A1%A8)
  - [音视频格式支持](#%E9%9F%B3%E8%A7%86%E9%A2%91%E6%A0%BC%E5%BC%8F%E6%94%AF%E6%8C%81)
  - [浏览器适配](#%E6%B5%8F%E8%A7%88%E5%99%A8%E9%80%82%E9%85%8D)
    - [桌面端浏览器](#%E6%A1%8C%E9%9D%A2%E7%AB%AF%E6%B5%8F%E8%A7%88%E5%99%A8)
    - [Android端浏览器](#android%E7%AB%AF%E6%B5%8F%E8%A7%88%E5%99%A8)
    - [iOS端浏览器](#ios%E7%AB%AF%E6%B5%8F%E8%A7%88%E5%99%A8)
  - [H5 功能说明](#h5-%E5%8A%9F%E8%83%BD%E8%AF%B4%E6%98%8E)
- [快速开始](#%E5%BF%AB%E9%80%9F%E5%BC%80%E5%A7%8B)
  - [如何使用](#%E5%A6%82%E4%BD%95%E4%BD%BF%E7%94%A8)
    - [NPM方式接入](#npm%E6%96%B9%E5%BC%8F%E6%8E%A5%E5%85%A5)
    - [导出包类型](#%E5%AF%BC%E5%87%BA%E5%8C%85%E7%B1%BB%E5%9E%8B)
  - [组件示例](#%E7%BB%84%E4%BB%B6%E7%A4%BA%E4%BE%8B)
    - [原生库](#%E5%8E%9F%E7%94%9F%E5%BA%93)
    - [React](#react)
    - [Vue2](#vue2)
    - [Vue3](#vue3)
    - [需要参考的文档：](#%E9%9C%80%E8%A6%81%E5%8F%82%E8%80%83%E7%9A%84%E6%96%87%E6%A1%A3)
  - [Server-side-rendering (SSR)](#server-side-rendering-ssr)
  - [CORS](#cors)
  - [播放H.265/KVC/VVC说明](#%E6%92%AD%E6%94%BEh265kvcvvc%E8%AF%B4%E6%98%8E)
    - [wasm解码器兼容性：](#wasm%E8%A7%A3%E7%A0%81%E5%99%A8%E5%85%BC%E5%AE%B9%E6%80%A7)
    - [wasm解码器性能优化](#wasm%E8%A7%A3%E7%A0%81%E5%99%A8%E6%80%A7%E8%83%BD%E4%BC%98%E5%8C%96)
- [插件](#%E6%8F%92%E4%BB%B6)
  - [插件使用](#%E6%8F%92%E4%BB%B6%E4%BD%BF%E7%94%A8)
    - [向插件传入配置](#%E5%90%91%E6%8F%92%E4%BB%B6%E4%BC%A0%E5%85%A5%E9%85%8D%E7%BD%AE)
    - [获取插件实例](#%E8%8E%B7%E5%8F%96%E6%8F%92%E4%BB%B6%E5%AE%9E%E4%BE%8B)
    - [获取所有插件实例](#%E8%8E%B7%E5%8F%96%E6%89%80%E6%9C%89%E6%8F%92%E4%BB%B6%E5%AE%9E%E4%BE%8B)
  - [内置插件说明](#%E5%86%85%E7%BD%AE%E6%8F%92%E4%BB%B6%E8%AF%B4%E6%98%8E)
    - [I18nPlugin](#i18nplugin)
    - [LoggerPlugin](#loggerplugin)
    - [WaterMarkPlugin（水印）](#watermarkplugin%E6%B0%B4%E5%8D%B0)
      - [原生库 示例](#%E5%8E%9F%E7%94%9F%E5%BA%93-%E7%A4%BA%E4%BE%8B)
      - [Vue 示例](#vue-%E7%A4%BA%E4%BE%8B)
      - [React 示例](#react-%E7%A4%BA%E4%BE%8B)
    - [ControlsPlugin](#controlsplugin)
    - [PlayInfoPlugin](#playinfoplugin)
    - [PrefetchPlugin](#prefetchplugin)
    - [PreviewPlugin](#previewplugin)
    - [HotkeyPlugin](#hotkeyplugin)
    - [RotatePlugin](#rotateplugin)
    - [AlphaVideoPlugin](#alphavideoplugin)
      - [API](#api)
        - [active](#active)
      - [type](#type)
  - [自定义插件](#%E8%87%AA%E5%AE%9A%E4%B9%89%E6%8F%92%E4%BB%B6)
    - [利用钩子](#%E5%88%A9%E7%94%A8%E9%92%A9%E5%AD%90)
    - [注册销毁插件](#%E6%B3%A8%E5%86%8C%E9%94%80%E6%AF%81%E6%8F%92%E4%BB%B6)
    - [插件实现示例](#%E6%8F%92%E4%BB%B6%E5%AE%9E%E7%8E%B0%E7%A4%BA%E4%BE%8B)
- [API](#api-1)
  - [原生库属性](#%E5%8E%9F%E7%94%9F%E5%BA%93%E5%B1%9E%E6%80%A7)
    - [src](#src)
    - [controls](#controls)
    - [showInfoPanel](#showinfopanel)
    - [productName](#productname)
    - [bizData](#bizdata)
    - [disableHotkey](#disablehotkey)
    - [disableDownload](#disabledownload)
    - [disableAdaptive](#disableadaptive)
    - [currentLevel](#currentlevel)
    - [nextLevel](#nextlevel)
    - [audioTrack](#audiotrack)
    - [totalVideoFrames](#totalvideoframes)
    - [currentVideoFrame](#currentvideoframe)
    - [showProgress](#showprogress)
  - [API](#api-2)
    - [constructor(id: string, data?: Partial<KwaiPlayer.KwaiPlayerData>)](#constructorid-string-data-partialkwaiplayerkwaiplayerdata)
    - [destroy(): void](#destroy-void)
    - [isFullscreen(): boolean;](#isfullscreen-boolean)
    - [requestFullscreen: (type?: "window" | "system" | undefined) => void;](#requestfullscreen-type-window--system--undefined--void)
    - [exitFullscreen: (type?: "window" | "system" | undefined) => void;](#exitfullscreen-type-window--system--undefined--void)
    - [requestPictureInPicture(): Promise<PictureInPictureWindow> | undefined;](#requestpictureinpicture-promisepictureinpicturewindow--undefined)
    - [screenshot(): Promise<ImageData | void>](#screenshot-promiseimagedata--void)
    - [refresh(): void;](#refresh-void)
    - [getPluginInstance<pluginLabel extends keyof PluginMap>(label: string | pluginLabel): PluginMap[pluginLabel] | undefined;](#getplugininstancepluginlabel-extends-keyof-pluginmaplabel-string--pluginlabel-pluginmappluginlabel--undefined)
    - [KwaiPlayer.register(plugin: typeof PluginModule, method: RegisterMethod = 'append');](#kwaiplayerregisterplugin-typeof-pluginmodule-method-registermethod--append)
    - [KwaiPlayer.deregister(plugin: typeof PluginModule | string);](#kwaiplayerderegisterplugin-typeof-pluginmodule--string)
    - [createSubContainer(layer = KwaiPlayerLayer.DEFAULT): HTMLDivElement](#createsubcontainerlayer--kwaiplayerlayerdefault-htmldivelement)
  - [原生js组件事件](#%E5%8E%9F%E7%94%9Fjs%E7%BB%84%E4%BB%B6%E4%BA%8B%E4%BB%B6)
    - [manifestparsed](#manifestparsed)
    - [levelswitching](#levelswitching)
    - [levelswitched](#levelswitched)
    - [levelswitchplaying](#levelswitchplaying)
    - [levelswitchfailed](#levelswitchfailed)
    - [audiotrackswitching](#audiotrackswitching)
    - [audiotrackswitched](#audiotrackswitched)
  - [React组件与原生js组件差异](#react%E7%BB%84%E4%BB%B6%E4%B8%8E%E5%8E%9F%E7%94%9Fjs%E7%BB%84%E4%BB%B6%E5%B7%AE%E5%BC%82)
    - [React事件对应表](#react%E4%BA%8B%E4%BB%B6%E5%AF%B9%E5%BA%94%E8%A1%A8)
  - [Vue组件与原生js组件差异](#vue%E7%BB%84%E4%BB%B6%E4%B8%8E%E5%8E%9F%E7%94%9Fjs%E7%BB%84%E4%BB%B6%E5%B7%AE%E5%BC%82)
    - [在页面中引入](#%E5%9C%A8%E9%A1%B5%E9%9D%A2%E4%B8%AD%E5%BC%95%E5%85%A5)
- [错误码](#%E9%94%99%E8%AF%AF%E7%A0%81)

<!-- END doctoc generated TOC please keep comment here to allow auto update -->

# 简介

快手Web播放组件基于HTML5的[HTMLVideoElement(\<video \/>)](https://developer.mozilla.org/zh-CN/docs/Web/API/HTMLVideoElement)。

提供适配Vue2/Vue3/React/原生JS的多个版本接入。

同时支持桌面端和移动端浏览器环境。

npm：https://www.npmjs.com/package/@kwai-video-team/kwai-player-web

Demo和文档：https://s2-10895.kwimgs.com/kos/nlav10895/kwaiplayer-web/index.html

## 功能列表

| 功能点          | 功能说明                                                                     |
| :-------------- | :--------------------------------------------------------------------------- |
| 支持协议        | 支持 FLV、HLS、MP4、WebRTC、裸流 等丰富的音视频格式                          |
| 播放-URL        | 支持网络视频的 URL 方式播放                                                  |
| 播放-Manifest   | 支持快手协议，更多咨询问题请联系我们。                                       |
| 播放-本地文件   | 本地文件方式播放                                                             |
| 播放-videoID    | 支持vid播放（开发中）                                                        |
| 基本功能        | 支持开始、结束、暂停、自动播放、循环播放、断点续播、重播、倍速等播放控制功能 |
| 清晰度切换-手动 | 支持开始、结束、暂停、自动播放、循环播放、断点续播、重播、倍速等播放控制功能 |
| 清晰度切换-平滑 | 配合GOP对齐HLS/快手协议，支持无停顿平滑切换                                  |
| 清晰度切换-自动 | 配合GOP对齐HLS/快手协议，支持根据网速自动切换清晰度                          |
| 预览图          | 支持预览图功能                                                               |
| 弹幕防挡        | 支持弹幕防挡                                                                 |
| 水印            | 支持在播放组件中添加自定义水印                                               |
| H.265支持       | 快手web端265解决方案                                                         |
| 自定义启播时间  | 支持自定义视频开启播放的时间                                                 |
| 多实例          | 支持在一个界面添加多个播放器同时播放                                         |
| 边下边播        | 支持视频播放的同时缓存下载后面的内容                                         |
| HLS标准加密     | 支持基于 HLS 提供的 AES encryption 方案，使用密钥对视频数据加密              |
| DRM             | widevine                                                                     |
| 逐帧播放        | MP4支持上下帧逐帧播放                                                        |

## 音视频格式支持

| 协议          | H.264 |       H.265       | H.266 |    AV1     |  KVC  |  AAC  |  MP3  | Opus  |
| ------------- | :---- | :---------------: | :---: | :--------: | :---: | :---: | :---: | :---: |
| flv + flv切片 | 支持  | 依赖浏览器 + wasm |   x   | 依赖浏览器 |   x   |   x   | 支持  |   x   |
| mp4           | 支持  | 依赖浏览器 + wasm | wasm  | 依赖浏览器 | wasm  | wasm  | 支持  | 支持  |
| HLS           | 支持  | 依赖浏览器 + wasm |   x   |     x      | wasm  |   x   | 支持  |   -   |
| 裸流          | 支持  | 依赖浏览器 + wasm |   x   | 依赖浏览器 | wasm  |   x   |   -   |   -   |
| webRTC直播    | 支持  |         -         |   x   |     -      |   -   |   -   |   -   |   -   |

YUV支持: 8bit/10bit yuv420p/yuv422p/yuv444p。YUV文件命名需要符合模板：name_WxH_FPS_BITDEPTH_CHROMA.yuv。

> 面向普通用户的场景不推荐使用wasm解码器。如果要使用H.265/AV1编码，推荐采用快手web端H.265整体解决方案，更多咨询问题请联系我们。

## 浏览器适配

### 桌面端浏览器

| 浏览器      | MP4  |  FLV  |  HLS  |
| ----------- | :--- | :---: | :---: |
| Chrome 39+  | 支持 | 支持  | 支持  |
| Edge win10  | 支持 | 支持  | 支持  |
| IE11+       | 支持 | 支持  | 支持  |
| Firefox 42+ | 支持 | 支持  | 支持  |
| Safari 8+   | 支持 | 支持  | 支持  |

### Android端浏览器

| 浏览器     | MP4  |  FLV  |  HLS  |
| ---------- | :--- | :---: | :---: |
| Chrome 39+ | 支持 | 支持  | 支持  |
| 微信       | 支持 | 支持  | 支持  |
| Edge       | 支持 | 支持  | 支持  |

### iOS端浏览器

| 浏览器 | MP4  |  FLV   |  HLS  |
| ------ | :--- | :----: | :---: |
| Chrome | 支持 | 不支持 | 支持  |
| 微信   | 支持 | 不支持 | 支持  |
| Safari | 支持 | 不支持 | 支持  |
| Edge   | 支持 | 不支持 | 支持  |

## H5 功能说明

| 功能     | 桌面端                                                                                                                                                                                             | Android                        | iOS                                                                           |
| -------- | :------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | :----------------------------- | :---------------------------------------------------------------------------- |
| 全屏     | 支持                                                                                                                                                                                               | 不支持                         | 1. iOS 10以下版本的Safari浏览器无法禁止视频自动全屏播放;<br>2. 仅支持网页全屏 |
| 自动播放 | 播放组件会按照以下规则尝试自动播放：有声音自动播放，失败后尝试静音自动播放，失败后不自动播放。<br>1. Chrome遵循以下播放规则:https://developer.chrome.com/blog/autoplay/<br>2. Safari依赖浏览器设置 | 策略同桌面端                   | 策略同桌面端                                                                  |
| 音量     | 支持                                                                                                                                                                                               | 依赖设备音量                   | 依赖设备音量                                                                  |
| 倍速     | 支持                                                                                                                                                                                               | 部分移动端浏览器不支持设置倍速 | 不支持                                                                        |

# 快速开始

播放组件提供原生js组件，React组件，Vue2/Vue3组件。可以通过NPM使用或者在页面引入的方式引入。

## 如何使用

### NPM方式接入

```js
npm i @ks-video/kwai-player-web

import KwaiPlayer from '@ks-video/kwai-player-web';
player = new KwaiPlayer('#player', {
    src: 'http://xxxx.mp4',
    autoplay: true,
    productName: 'KPN', // 用于区分上报
});

// 上报数据如果不是国内生产环境，需要设置上报插件环境，查看LoggerPlugin插件的说明

```


### 导出包类型

**推荐使用** 默认导出（full）或各框架对应的导出包含了大部分常用插件，
基础导出（basic）减少了基本控件以外的插件，对于不需要使用过多功能的情况使用

| 类型             | npm引用                              | 备注                                | ES5 UMD | ES6 UMD | ES6 Module |
| ---------------- | ------------------------------------ | ----------------------------------- | ------- | ------- | ---------- |
| 完整版-原生库    | @ks-video/kwai-player-web            | 包含完整功能，原生库                | ✓       | ✕       | ✓          |
| 完整版-Vue2版本  | @ks-video/kwai-player-web/vue2       | 包含完整功能，vue2版本              | ✓       | ✕       | ✓          |
| 完整版-Vue3版本  | @ks-video/kwai-player-web/vue3       | 包含完整功能，vue3版本              | ✕       | ✓       | ✓          |
| 完整版-React版本 | @ks-video/kwai-player-web/react      | react                               | ✓       | ✕       | ✓          |
| 小包版-原生库    | @ks-video/kwai-player-web/mini       | 不包含控制条的最小功能包,原生库     | ✓       | ✕       | ✓          |
| 小包版-vue2      | @ks-video/kwai-player-web/vue2-mini  | 不包含控制条的最小功能包，vue2版本  | ✓       | ✕       | ✓          |
| 小包版-vue3      | @ks-video/kwai-player-web/vue3-mini  | 不包含控制条的最小功能包 vue3版本   | ✕       | ✓       | ✓          |
| 小包版-react     | @ks-video/kwai-player-web/react-mini | 不包含控制条的最小功能包，react版本 | ✓       | ✕       | ✓          |
| 基础版-原生库    | @ks-video/kwai-player-web/basic      | 包含控制条的最小功能包，原生库      | ✓       | ✕       | ✓          |

> 各包包含插件情况、详见插件文档

## 组件示例

### 原生库
```js
import KwaiPlayer from '@ks-video/kwai-player-web';

player = new KwaiPlayer('#player', {
    src: 'http://xxxx.mp4',
    autoplay: true,
});

```

```html
<body>
  <div id="player"></div>
</body>
```

### React

```js
import KwaiPlayerReact from '@ks-video/kwai-player-web/react';

function App() {
    const videoRef = useRef(null);

    useEffect(() => {
        if (videoRef.current) {
        videoRef.current.play();
        }
    }, [videoRef]);

    function onLoadedMetadata(){
        const duration = videoRef?.current?.duration//总时长
        const videoheight = videoRef?.current?.videoHeight//视频资源的高度
        const videowidth = videoRef?.current?.videoWidth//视频资源的宽度
        console.log(duration, videoheight, videowidth)
    }

    function onerror(val){
        console.log(val)
    }
    function onTimeUpdate() {
        console.log(videoRef?.current?.currentTime);//打印当前时间
    }

    return (
        <div className="App">
            <KwaiPlayerReact
                className="kwai-player-react"
                ref={videoRef}
                src={'http://xxxx.mp4'}
                autoPlay={true}
                controls={true}
                onTimeUpdate={onTimeUpdate}
                preload="auto"
                onError={onerror}
                onLoadedMetadata={onLoadedMetadata}
            ></KwaiPlayerReact>
        </div>
    );
}
```

### Vue2
```js
import KwaiPlayerVue2 from '@ks-video/kwai-player-web/vue2';
import poster from '../xxxx@2x.png'
export default {
    name: 'App',
    data() {
        return {
            src: 'http://xxxx.mp4',
            autoplay: true,
            controls:true,
            loop:true,
            poster:poster
        };
    },
    components: {
        'kwai-player-vue2': KwaiPlayerVue2,
    },
    methods:{
        error(val){
            console.log(val)
        },
        loadedmetadata(){
            let  duration = this.$refs['videoRef'].getDuration()
            let  videoheight = this.$refs['videoRef'].getVideoHeight()
            let  videowidth = this.$refs['videoRef'].getVideoWidth()
        },
        timeupdate(){
            console.log(this.$refs['videoRef'].getCurrentTime())//当前时间
        }
    }
};
```

```html
<kwai-player-vue2
    class="player"
    :src="src"
    :controls="controls"
    :autoplay="autoplay"
    :loop="loop"
    :poster="poster"
    @error="error"
    @loadedmetadata="loadedmetadata"
    @timeupdate="timeupdate"
>
</kwai-player-vue2>
```

### Vue3

```js
import KwaiPlayerVue3 from '@ks-video/kwai-player-web/vue3';
import poster from '../xxxx@2x.png'
import {ref} from'vue'
export default {
    name: "demo",
    components: {
        'kwai-player-vue3': KwaiPlayerVue3,
    },
    setup(){
        const src = ref('https://playurl')
        const autoplay = ref(true)
        const controls = ref(true)
        const loop = ref(true)

        const videoRef = ref(null)
        const timeupdate = ()=>{
            console.log(videoRef._value.getCurrentTime())//当前时间
        }
        const loadedmetadata = ()=>{
            const duration = videoRef._value.getDuration()
            const videoheight = videoRef._value.getVideoHeight()
            const videowidth = videoRef._value.getVideoWidth()
        }
        const error = (val)=>{
            console.log(val)
        }
        return {
            videoRef,
            src,
            autoplay,
            controls,
            poster,
            timeupdate,
            loadedmetadata,
            error
        }
    }
}

```

```html
<kwai-player-vue3
    class="player" 
    :src="src" 
    :controls="controls" 
    :autoplay="autoplay"
    :loop="loop"
    :poster="poster"
    @error="error"
    @loadedmetadata="loadedmetadata"
    @timeupdate="timeupdate"
/>
```


### 需要参考的文档：

播放组件的属性、API及事件参考了HTMLVideoElement的实现。

1. [HTMLVideoElement](https://developer.mozilla.org/zh-CN/docs/Web/API/HTMLVideoElement)
2. [HTMLMediaElement](https://developer.mozilla.org/zh-CN/docs/Web/API/HTMLMediaElement)

## Server-side-rendering (SSR)

可以安全地在Node中require此库

## CORS

视频资源必须允许GET请求，且包含[CORS](https://developer.mozilla.org/zh-CN/docs/Web/HTTP/Access_control_CORS)响应头。

## 播放H.265/KVC/VVC说明

> 面向普通用户的场景不推荐使用wasm解码器。如果要使用H.265/AV1编码，推荐采用快手web端H.265整体解决方案，更多咨询问题请联系我们。

浏览器不支持H.265/KVC/VVC解码时，会采用wasm解码器。

采用wasm解码器时，上层业务是无感知的。

### wasm解码器兼容性：

chrome 67+

### wasm解码器性能优化

播放组件在使用wasm解码器器时支持多线程解码及SIMD，且会根据浏览器能力开启对应的加速解码功能。

多线程解码用到了SharedArrayBuffer，chrome 92+需要对播放页增加两个响应头，推荐添加

```
Cross-Origin-Embedder-Policy: require-corp
Cross-Origin-Opener-Policy: same-origin
```

[chrome 92相关说明](https://developer.chrome.com/blog/enabling-shared-array-buffer/)

[Cross-Origin-Opener-Policy](https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Cross-Origin-Opener-Policy)

[Cross-Origin-Embedder-Policy](https://developer.mozilla.org/zh-CN/docs/Web/HTTP/Headers/Cross-Origin-Embedder-Policy)

播放页中的部分标签可能需要添加[crossorigin](https://developer.mozilla.org/zh-CN/docs/Web/HTML/Attributes/crossorigin)属性

> 页面增加这两个头会导致无法加载跨域资源。以下是以图片为例的解决方案。
> 
> 1. 解决方案A：在图片的响应头中添加：Cross-Origin-Resource-Policy: cross-origin;
> 2. 解决方案B：img标签中增加crossorigin属性

# 插件

播放组件实现了插件系统，用与解耦功能，增加各功能之间的组合能力。

播放组件已内置了很多插件，如**控制条**、**水印**、**信息面板**等插件。

> 播放组件中已经生成了多个版本的插件组合产物

| 插件名称          | 功能         | 完整版 | 小包版 | 基础版 |
| ----------------- | ------------ | ------ | ------ | ------ |
| I18nPlugin        | 国际化       | ✓      | ✓      | ✕      |
| PlayInfoPlugin    | 信息面板     | ✓      | ✓      | ✓      |
| ControlsPlugin    | 控制条       | ✓      | ✕      | ✓      |
| LoggerPlugin      | 日志上报     | ✓      | ✓      | ✓      |
| WaterMarkPlugin   | 水印         | ✓      | ✕      | ✕      |
| PrefetchPlugin    | 预热         | ✓      | ✕      | ✕      |
| PreviewPlugin     | 进度条预览图 | ✓      | ✕      | ✕      |
| HotkeyPlugin      | 快捷键       | ✓      | ✕      | ✕      |
| RotatePlugin      | 旋转画面     | ✓      | ✕      | ✕      |
| AlphaVideoPlugin  | 透明视频     | ✓      | ✕      | ✕      |

## 插件使用

### 向插件传入配置

通过player的plugins参数传入配置

数据格式：

```
{
    '插件名称': Record<string, any>
}
```

示例：
```
import { KwaiPlayer } from '@ks-video/kwai-player-web';

// 示例，设置语言插件为英文
new KwaiPlayer('#player-1', {
    plugins: {
        I18nPlugin: {
            lang: 'en',
        }
    }
}
```

### 获取插件实例

```ts

const plugin = player.getPluginInstance('I18nPlugin');
```

### 获取所有插件实例

```ts

const plugin = player.getAllPlugins();
```

## 内置插件说明

### I18nPlugin

多语言功能，默认包含中英，根据浏览器语言自动切换

参数：
plugins: {
    I18nPlugin: {
        lang?: string   // 选择语言名
        langDict?: {    // 多语言字典
            lang: string,   // 语言名
            map: Record<string, Record<string, string>> // 字典内容，区分插件 Record<插件名, Record<字典key, 字典value>>
        }[],
    }
}

```ts
import { KwaiPlayer } from '@ks-video/kwai-player-web;

new KwaiPlayer('#player-1', {
  plugins: {
    I18nPlugin: {
      lang: 'en'
    }
  }
}
```

通过传入插件配置的方式新增语言

```ts

import { ControlsPluginLabel, LangDict, ControlsLangDictKey } from '@ks-video/kwai-player-web;

const langDict:LangDict = {
    {
        lang: 'en',  // 指定语言
        map: {
            [ControlsPluginLabel]: {    // 用于控制条插件
                [ControlsLangDictKey.PLAY]: 'Play', // 指定对应key显示的文字
                [ControlsLangDictKey.PAUSE]: 'Pause',
            }
        }
    }
};

new KwaiPlayer('#player-1', {
    plugins: {
        I18nPlugin: {
            langDict,
        }
    }
}
```

### LoggerPlugin

播放组件数据上报


### WaterMarkPlugin（水印）

可以通过在播放器容器中增加子元素的方式添加水印

> 水印<div>必须包含属性 kwai-player-watermark

#### 原生库 示例

```html
<style>
  .wm {
    background-repeat: repeat;
    background-image: url(data:image/svg+xml;base64,.......);
  }
</style>
<div id="player">
  <div class="wm" kwai-player-watermark></div>
</div>
```

#### Vue 示例

```js
<style>
.wm {
    background-repeat: repeat;
    background-image: url(data:image/svg+xml;base64,.......)
}
</style>


<kwai-player-vue2
    class="player"
    :src="src"
    :autoplay="autoplay"
>
    <div className="wm" kwai-player-watermark></div>
</kwai-player-vue2>
```

#### React 示例

```js
<style>
.wm {
    background-repeat: repeat;
    background-image: url(data:image/svg+xml;base64,.......)
}
</style>


<KwaiPlayerReact
    className="kwai-player-react"
    src={src}
    autoPlay={true}
>
    <div className="wm" kwai-player-watermark="true"></div>
</KwaiPlayerReact>
```


### ControlsPlugin

实现了默认控制条 UI 交互

参数：
```
plugins: {
    ControlsPlugin: {
        danmakuControls?: DanmakuControlsPos,       // 弹幕插件在非全屏时显示的位置 / 依赖弹幕插件
        danmakuControlsFull?: DanmakuControlsPos,   // 弹幕插件在全屏时的显示位置 / 依赖弹幕插件
        showBottomButtonBar?: boolean,              // 是否按时下方播放按钮
        showProgress?: boolean,                     // 是否显示进度条
        showTime?: boolean,                         // 是否显示播放时间
        showWindowFullScreen?: boolean,             // 是否显示窗口全屏按钮
        seekMode?: 'onDragChange' | 'onDragEnd',    // seek 模式，拖动进度条实时seek/拖动进度条完成时seek
        showProgressTime?: boolean,                 // 是否在进度条上显示时间，默认不显示
        showPlaybackRate?: boolean,                 // 是否展示倍速功能
        showContextMenu?: boolean,                  // 是否展示右键菜单功能
        stateChange?: (data: StateChangeData) => void,              // UI状态回调
    }
}

type StateChangeData = { type: 'controlsVisibility', value: boolean }; // 控制条显示隐藏状态变化

```


### PlayInfoPlugin

提供播放信息面板

### PrefetchPlugin

提供播放地址链接预热功能，用于不自动播放且不预加载情况下的起播速度

### PreviewPlugin

增加控制条上的预览画面，需要指定预览图地址；需要配合streamlake服务使用

```ts
import { KwaiPlayer } from '@ks-video/kwai-player-web;

const player = new KwaiPlayer('#player-1' {
    src: 'xxx',
    previewUrl: 'xxxx', // 设置预览图url
});
```

### HotkeyPlugin

可利用键盘快进快退、暂停播放、音量高低调节

| 键位       | 单击                                                          | 长按                                |
| ---------- | ------------------------------------------------------------- | ----------------------------------- |
| ArrowRight | 前进 10s                                                      | 3 倍速                              |
| ArrowLeft  | 回退进度的两百分之 1 秒(若大于 10s 则为 10s、小于 5s 则为 5s) | 每 100ms 出发一次回退（时长如单击） |
| ArrowUp    | 增加音量的 5%                                                 | 每 100ms 增加音量的 5%              |
| ArrowDown  | 减少音量的 5%                                                 | 每 100ms 减少音量的 5%              |
| Space      | 播放/暂停                                                     | --                                  |


### RotatePlugin

画面旋转插件

参数：
```
// 配置类型
type OptionType = 'mirror' | 'counterClockwise' | 'clockwise';
type OptionValue = 'pc' | 'mobile' | 'always';

type OptionShow = OptionValue | Record<OptionType, OptionValue>;

type RotatePluginOption = {
  showInPlayBar?: OptionShow,
  showInContextMenu?: OptionShow,
  svgRaw?: {
    mirror?: string,
    counterClockwise?: string,
    clockwise?: string,
  }
}

// 配置传入
plugins: {
    AlphaVideoPlugin: RotatePluginOption,
}

```

### AlphaVideoPlugin

透明视频插件，支持透明视频的播放

参数：
```
plugins: {
    AlphaVideoPlugin: {
        active?: boolean,                           // 是否启动。默认：undefined，自动识别
        type?: undefined | "2:1" | "1:1",           // 透明视频类型。默认：undefined，自动识别
    }
}
```

#### API

##### active

set: 是否启动。默认：undefined，自动识别

#### type

set: 透明视频类型。默认：undefined，自动识别

可选值：undefined | "2:1" | "1:1"


## 自定义插件

可以自定义插件

+ 插件名唯一，注册同名插件仅最后一次注册生效，故可采用这种方法替换已有插件。
  + 例如：自定义名称为ControlsPlugin的插件，注册在完整包中，会替换默认的播控UI
+ 自定义插件实现需要继承PluginModule或其他基础插件的抽象类
+ 自定义插件需要在实例化之前完成注册
+ 注册方法仅需要执行一次
+ 注销方法和销毁播放器无关，正常情况不需要调用


播放组件中的DOM分为以下三层，添加子容器需要指定一个层级，从下向上依次为VIDEO/VIDEO_INTERACTIVE/DEFAULT

### 利用钩子

- 挂载前

```ts
beforeInstall(player: IKwaiPlayer, options?: any): void
```

数据准备完成，还未开始实例化播放内核前触发

- 挂载后

```ts
afterInstall(player: IKwaiPlayer, options?: any): void
```

实例化播放内核后触发

- 销毁前

```ts
beforeUninstall(player: IKwaiPlayer): void
```

销毁播放内核前触发

- 销毁后

```ts
afterUninstall(player: IKwaiPlayer): void
```

销毁播放内核后触发

### 注册销毁插件

实现一个插件后需要在**KwaiPlayer**对象上注册

1. 注册插件方法只用调用一次
2. 销毁播放器不需要调用注销

```ts
KwaiPlayer.register(WaterMarkPlugin); //注册
KwaiPlayer.deregister(WaterMarkPlugin); //注销
```

### 插件实现示例

```ts
import { IKwaiPlayer, KwaiPlayerEvent, PluginModule } from '@ks-video/kwai-player-web';

// 新插件替换已有的logger插件
// export default class ExamplePlugin extends LoggerPluginModule {

// 新插件与已有插件共存
export default class ExamplePlugin extends PluginModule {

    private _player: IKwaiPlayer | undefined;

    /**
     * 播放器实例化前钩子
     * @param player 播放器实例
     * @param options 实例化播放器时指定的当前插件的参数
     */
    public beforeInstall(player: IKwaiPlayer, options?: any | undefined): void {
        this._player = player;

        console.log('beforeInstall', options);

        // 播放事件处理
        this._player.on(KwaiPlayerEvent.REPORT, this._onReport);

        // 切换视频事件处理
        this._player.on(KwaiPlayerEvent.ATTRIBUTE_CHANGE_SRC, this._onSrcChange);

    }

    /**
     * 播放器实例化后钩子
     * @param player 播放器实例
     * @param options 实例化播放器时指定的当前插件的参数
     */
    public afterInstall(_player: IKwaiPlayer, _options?: any): void {
        console.log('afterInstall');
    }

    /**
     * 播放器销毁前钩子
     * @param player 播放器实例
     */
    public beforeUninstall(_player: IKwaiPlayer): void {
        console.log('beforeUninstall');
    }

    /**
     * 播放器销毁后钩子
     * @param player 播放器实例
     */
    public afterUninstall(_player: IKwaiPlayer): void {
        console.log('afterUninstall');
        this._player?.off(KwaiPlayerEvent.REPORT, this._onReport);
        this._player?.off(KwaiPlayerEvent.ATTRIBUTE_CHANGE_SRC, this._onSrcChange);
    }

    /**
     * 插件id，获取插件，传入参数等操作的标识
     * 同名插件只会同时存在一个
     */
    public getLabel(): string {
        // LoggerPluginLabel
        return 'ExamplePlugin';
    }

    private _onReport = (e: { type: string, value: any }): void => {
    }

    private _onSrcChange = (): void => {

    }
}

```

# API

播放组件提供原生js方式接入，React组件方式接入，Vue2/Vue3组件方式接入。原生js、React、Vue的API和事件名称有差异，需要注意。

播放器的属性、API及事件参考了HTMLVideoElement的实现。

需要参考的文档：

1. [HTMLVideoElement](https://developer.mozilla.org/zh-CN/docs/Web/API/HTMLVideoElement)
2. [HTMLMediaElement](https://developer.mozilla.org/zh-CN/docs/Web/API/HTMLMediaElement)

## 原生库属性

**以下属性同HTMLVideoElement**

| 属性                    | 定义                 | 备注 |
| :---------------------- | :------------------- | ---- |
| crossOrigin             | 跨域设置             |      |
| preload                 | 当前视频预加载设置   |      |
| defaultPlaybackRate     | 默认播放速度         |      |
| playbackRate            | 播放速度             |      |
| autoplay                | 自动播放             |      |
| loop                    | 循环播放开关         |      |
| controls                | 播放控件显示开关     |      |
| volume                  | 音量                 |      |
| muted                   | 静音                 |      |
| defaultMuted            | 默认静音             |      |
| poster                  | 封面图               |      |
| disablePictureInPicture | 画中画是否可用开关   |      |
| playsinline             | 手机H5小窗播放开关   |      |
| buffered                | 缓存范围             | 只读 |
| duration                | 视频时长             | 只读 |
| ended                   | 是否播放结束         | 只读 |
| error                   | 错误信息             | 只读 |
| played                  | 已播放范围           | 只读 |
| readyState              | 视频状态             | 只读 |
| seekable                | 可seek范围           | 只读 |
| seeking                 | 是否处于seek状态中   | 只读 |
| networkState            | 当前视频加载网络状态 | 只读 |
| paused                  | 是否暂停状态         | 只读 |
| videoWidth              | 视频源宽             | 只读 |
| videoHeight             | 视频源高             | 只读 |

**暂未实现的属性**

+ audioTracks
+ currentSrc 只读
+ initialTime 只读
+ mediaGroup
+ mediaKeys
+ moz*
+ sinkId
+ textTracks
+ videoTracks
+ width
+ height

> width/height暂不支持，需要使用样式控制

**与HTMLVideoElement有差异的属性**

### src

可传入视频URL、manifest JSON、File。可传入空字符串进入停止状态

### controls

依赖插件: ControlsPlugin

定义同HTMLVideoElement，用于控制播放控件，可选值有不同

+ controls可选值说明
  + false：关闭播放控件，如果需要自定义播放控件请使用该选项
  + true：使用默认播放控件
  + 'default'：使用默认播放控件

### showInfoPanel

依赖插件: PlayInfoPlugin

get: 返回是否显示信息面板

set: 设置是否显示信息面板

### productName

依赖插件: LoggerPlugin

业务名，用于从上报数据中区分业务

### bizData

依赖插件: LoggerPlugin

业务数据，会加入到上报中

```ts
type BizData = {
  resourceId?: string | number, // 资源ID
  userId?: string | number, // 用户id
  photoId?: string,     // yoda上报
  activityTag?: string, // yoda上报
  // eslint-disable-next-line @typescript-eslint/no-explicit-any
  request?: { header: Record<string, any> },
  secretId?: string, // 不会加入上报
  secretKey?: string, // 不会加入上报
  isVip?: boolean | number,
} & Record<string, unknown>;
```

### disableHotkey

依赖插件: HotkeyPlugin

get: 返回当前热键功能是否开启

set: 设置当前热键功能是否开启

### disableDownload

依赖插件: ControlsPlugin

controls===‘origin’时是否使下载功能可用

### disableAdaptive

自适应码率是否可用，默认：true

> 以上已实现的可写属性均可在构造函数中传入

### currentLevel

get: 返回当前正在加载的流index

set: 立即切换至指定的流index

设置为-1，切换至自动码率

### nextLevel

get: 返回下一个加载的流index

set: 下一个切换的视频流index

设置为-1，切换至自动码率

### audioTrack

get: 返回当前的音频轨index

set: 立即切换至指定的音频轨index

### totalVideoFrames

get: 返回当前播视频总帧数

### currentVideoFrame

get: 返回当前播放位置对应的帧index

set: seek至指定帧

### showProgress

get: 设置是否显示进度条

set: 获取当前是否显示进度条

> totalVideoFrames>0时可用

## API

**以下API同HTMLVideoElement**

+ load()
+ play()
+ pause()
+ requestPictureInPicture();


**以下API暂未实现**

+ ms*
+ canPlayType()
+ captureStream()
+ fastSeek()
+ setMediaKeys()
+ setSinkId()

**与HTMLVideoElement有差异的API**

### constructor(id: string, data?: Partial<KwaiPlayer.KwaiPlayerData>)

构造函数

参数说明：

+ id: 播放器容器id
+ data: 播放器参数，与HTMLVideoElement相同的API定义也可同data传入

```js
type KwaiPlayerData = {
    src: any;
    crossOrigin?: string;
    preload?: string;
    defaultPlaybackRate?: number;
    playbackRate?: number;
    autoplay?: boolean;
    loop?: boolean;
    controls?: boolean | string;
    volume?: number;
    muted?: boolean;
    defaultMuted?: boolean;
    poster?: string;
    disablePictureInPicture?: boolean;
    disableDownload?: boolean;
    disableAdaptive?: boolean;
    playsinline?: boolean;
    plugins: { [key in string]: object }; // 参见插件说明
};
```

### destroy(): void

销毁

### isFullscreen(): boolean;

是否全屏

### requestFullscreen: (type?: "window" | "system" | undefined) => void;

请求全屏
```type?: "window" | "system"``` 窗口全屏 | 系统全屏

### exitFullscreen: (type?: "window" | "system" | undefined) => void;

退出全屏
```type?: "window" | "system" | undefined``` 窗口全屏 | 系统全屏 | 自动

### requestPictureInPicture(): Promise<PictureInPictureWindow> | undefined;

进入画中画

### screenshot(): Promise<ImageData | void>

截图

### refresh(): void;

刷新，重新加载视频

### getPluginInstance<pluginLabel extends keyof PluginMap>(label: string | pluginLabel): PluginMap[pluginLabel] | undefined;

获取插件实例


***
> 以下API用于自定义插件

### KwaiPlayer.register(plugin: typeof PluginModule, method: RegisterMethod = 'append');

注册插件

使用场景：
+ 替换现有包中的组件，例如更换UI，使用其他播控UI插件
+ 自定义插件，更多查看自定义插件说明

参数：
plugin: 插件
method: 添加位置，放在最前或者最后，prepend/append，插件注册的顺序会影响到钩子调用的顺序

更多查看插件自定义组件部分内容

### KwaiPlayer.deregister(plugin: typeof PluginModule | string);

注销插件

更多查看插件自定义组件说明

### createSubContainer(layer = KwaiPlayerLayer.DEFAULT): HTMLDivElement

创建一个子容器，用于在播放器中添加DOM

参数:
layer 添加层级

```ts
enum KwaiPlayerLayer {
  VIDEO = 'video',  // 视频内容层，例如视频画面，水印，全景视频渲染画面
  VIDEO_INTERACTIVE = 'videoInteractive',   // 视频交互层，如弹幕
  DEFAULT = 'default',  // 播控层，如播放组件，视频信息面板
}
```

## 原生js组件事件

**以下事件同HTMLVideoElement**

| 属性           | 定义                           | 备注 |
| -------------- | :----------------------------- | ---- |
| abort          | 资源未完全加载时触发，非错误   |      |
| canplay        | 可播时                         |      |
| canplaythrough | 可播时，估计已加载足够数据     |      |
| durationchange | 视频总时长变更                 |      |
| emptied        | 媒体源设置为空时               |      |
| ended          | 播放结束                       |      |
| error          | 发生错误                       |      |
| loadeddata     | 当前播放位置视频帧加载完成     |      |
| loadedmetadata | metadata加载完成               |      |
| loadstart      | 开始加载                       |      |
| pause          | 进入暂停状态 puased转为true时  |      |
| play           | 进入播放状态 puased转为false时 |      |
| playing        | 播放准备开始时                 |      |
| progress       | 加载资源                       |      |
| ratechange     | 播放速度变更                   |      |
| resize         | 视频源尺寸变更                 |      |
| seeked         | seek完成                       |      |
| seeking        | seek开始                       |      |
| stalled        | 尝试获取数据但是为取到时触发   |      |
| suspend        | 加载数据被挂起                 |      |
| timeupdate     | 播放时间变更                   |      |
| volumechange   | 音量变更                       |      |
| waiting        | 缺少数据导致播放暂停           |      |

**与HTMLVideoElement有差异的事件**

> 以下事件与多清晰度相关
### manifestparsed

+ 定义：manifest解析成功事件
+ 数据：  

```js
{
    levels: {
        width: 640, // 宽，可选
        height: 360, // 高，可选
        qualityType: "360"
        qualityLabel: "标清"
    }[], // 可用流列表
    currentLevel: 3, // 当前流index,
    audioTracks?: {
        lang: 'en', // 语言
        qualityLabel: '',
        qualityType: '',
    }[], // 可用音频轨
    audioTrack?: 0, // 当前音频轨index
}
```

### levelswitching

+ 定义：开始进行码率切换
+ 数据：
  
```js
  { 
	  bitrate: 460560, // 码率
	  smooth: true, // 是否平滑切换
      auto: false, // 是否自动
      level: 1, // level下标
      id: 1, // 切换操作id
  }
  ```

### levelswitched

+ 定义：码率切换成功事件
+ 数据：
  
```js
{ 
	bitrate: 460560, // 码率
	smooth: true, // 是否平滑切换
    auto: false, // 是否自动
    level: 1， // level下标
    id: 1, // 切换操作id
}
```

### levelswitchplaying

+ 定义：码率切换开始播放，切换至自动码率时无此事件
+ 数据：
  
```js
{ 
	bitrate: 460560, // 码率
	smooth: true, // 是否平滑切换
    auto: false, // 是否自动
    level: 1， // level下标
    id: 1, // 切换操作id
}
```

### levelswitchfailed

+ 定义：切换清晰度失败

### audiotrackswitching

+ 定义：音频轨开始切换
+ 数据：

```js
{
    level: 0,   // 音频轨id
    smooth: false,  // 是否平滑切换
    auto: false,    // 是否自动切换
    id: 1           // 切换操作id
}
```

### audiotrackswitched

+ 定义：音频轨切换完成
+ 数据：

```js
{
    level: 0,   // 音频轨id
    smooth: false,  // 是否平滑切换
    auto: false,    // 是否自动切换
    id: 1           // 切换操作id
}
```


## React组件与原生js组件差异

API相同

### React事件对应表

| React组件事件         | 对应事件            |
| --------------------- | :------------------ |
| onAbout               | abort               |
| onCanplay             | canplay             |
| onCanplayThrough      | canplaythrough      |
| onDurationChange      | durationchange      |
| onEmptied             | emptied             |
| onEnded               | ended               |
| onError               | error               |
| onLoadedData          | loadeddata          |
| onLoadedMetadata      | loadedmetadata      |
| onLoadStart           | loadstart           |
| onPause               | pause               |
| onPlay                | play                |
| onPlaying             | playing             |
| onProgress            | progress            |
| onRateChange          | ratechange          |
| onResize              | resize              |
| onSeeked              | seeked              |
| onSeeking             | seeking             |
| onStalled             | stalled             |
| onSuspend             | suspend             |
| onTimeUpdate          | timeupdate          |
| onVolumeChange        | volumechange        |
| onWaiting             | waiting             |
| onManifestParsed      | manifestparsed      |
| onLevelSwitching      | levelswitching      |
| onLevelSwitched       | levelswitched       |
| onLevelSwitchPlaying  | levelswitchplaying  |
| onLevelSwitchFailed   | levelswitchfailed   |
| onAudioTrackSwitching | audiotrackswitching |
| onAudioTrackSwitched  | audiotrackswitched  |

## Vue组件与原生js组件差异

事件相同

**以下props同HTMLVideoElement**

+ crossOrigin   //是否设置跨域
+ preload   //是否预加载    
+ defaultPlaybackRate  //设置默认播放倍速
+ playbackRate  //修改播放倍速
+ autoplay   //是否设置视频播自动播放
+ loop      //是否在视频播放结束的时候，自动返回视频开始的地方，继续播放
+ controls   //是否在视频底部使用默认面板 包括控制音量，跨帧，暂停/播放等
+ volume     //设置音量
+ muted     //设置音量是否静音
+ defaultMuted  //设置音量是否默认静音
+ poster      //视频播放之前，作为海报展示的图片
+ disablePictureInPicture    //是否禁用画中画选项
+ playsinline    //指明视频将内联（inline）播放，即在元素的播放区域内
+ src    //播放URL或者manifest内容

**Vue组件属性对照表**

| Vue组件 API                                             | 原生js组件属性                                    |
| ------------------------------------------------------- | :------------------------------------------------ |
| getError                                                | error                                             |
| getNetworkState                                         | networkState                                      |
| getBuffered                                             | buffered                                          |
| getReadyState                                           | readyState                                        |
| getSeeking                                              | seeking                                           |
| getDuration                                             | duration                                          |
| getPaused                                               | paused                                            |
| getSeekable                                             | seekable                                          |
| getEnded                                                | ended                                             |
| getVideoWidth                                           | videoWidth                                        |
| getVideoHeight                                          | videoHeight                                       |
| getSrc / setSrc                                         | src                                               |
| getCrossOrigin / setCrossOrigin                         | crossOrigin                                       |
| getPreload / setPreload                                 | preload                                           |
| getCurrentTime / setCurrentTime                         | currentTime                                       |
| getDefaultPlaybackRate / setDefaultPlaybackRate         | defaultPlaybackRate                               |
| getPlaybackRate / setPlaybackRate                       | playbackRate                                      |
| getAutoplay / setAutoplay                               | autoplay                                          |
| getLoop / setLoop                                       | loop                                              |
| getControls / setControls                               | controls                                          |
| getVolume / setVolume                                   | volume                                            |
| getMuted / setMuted                                     | muted                                             |
| getDefaultMuted / setDefaultMuted                       | defaultMuted                                      |
| getPoster / setPoster                                   | poster                                            |
| getDisablePictureInPicture / setDisablePictureInPicture | disablePictureInPicture                           |
| getPlaysinline / setPlaysinline                         | playsinline + webkit-playsinline + x5-playsinline |

### 在页面中引入

+ 引入js
```html
<script src="https://cdn.jsdelivr.net/npm/@kwai-video-team/kwai-player-web/full/kwai-player-web-full.js"></script>
```


+ 提供挂载元素
```html
<body>
  <div id="player"></div>
</body>
```
+ 实例化
```html
<script>
player = new KwaiPlayer.default('#player', {
    src: 'http://xxxx.mp4',
    autoplay: true,
});
</script>
```

可以根据需要引入不同包
```html
<script src="https://cdn.jsdelivr.net/npm/@kwai-video-team/kwai-player-web/full/kwai-player-web-full.js"></script>
<script src="https://cdn.jsdelivr.net/npm/@kwai-video-team/kwai-player-web/vue2/kwai-player-web-vue2.js"></script>
<script src="https://cdn.jsdelivr.net/npm/@kwai-video-team/kwai-player-web/vue3/kwai-player-web-vue3.js"></script>
<script src="https://cdn.jsdelivr.net/npm/@kwai-video-team/kwai-player-web/react/kwai-player-web-react.js"></script>
```

# 错误码

播放组件错误说明

| code      | 定义                                                    |                |
| :-------- | :------------------------------------------------------ | :------------- |
| 10xx      | 流加载错误                                              | 网络错误       |
| 1000      | 流加载错误且无http status code，加载资源的跨域头不正确  | 网络错误       |
| 1001      | 流加载错误400                                           | 网络错误       |
| 1002      | 流加载错误401                                           | 网络错误       |
| 1003      | 流加载错误403                                           | 网络错误       |
| 1004      | 流加载错误404                                           | 网络错误       |
| 1005      | 流加载错误4xx                                           | 网络错误       |
| 1006      | 流加载错误5xx                                           | 网络错误       |
| 1007      | 流加载错误，连接超时                                    | 网络错误       |
| 1008      | 流加载错误，数据超时                                    | 网络错误       |
| 1009      | 流加载出错，传输过程中失败                              | 网络错误       |
| 11xx      | hlsManifestLoadError HLS manifest加载错误               | 网络错误       |
| 12xx      | hlsLevelLoadError HLS level加载错误                     | 网络错误       |
| 13xx      | hls音频track playlist加载失败                           | 网络错误       |
| 14xx      | hls key加载失败 网络错误                                | 网络错误       |
| 15xx      | drm license加载失败                                     | 网络错误       |
| 16xx      | 解码库加载失败                                          | 网络错误       |
| 100       | canNotSeek无法seek                                      |                |
| 101       | video触发错误 且未取到MediaError.code                   |                |
| 102       | 不支持的协议                                            |                |
| 103       | 传入配置错误                                            |                |
| 106       | seek至指定帧失败                                        |                |
| 107       | 传入Src为空                                             |                |
| 111       | video触发错误 对应MediaError.code 1                     | 参考MediaError |
| 112       | video触发错误 对应MediaError.code 2                     | 参考MediaError |
| 113       | video触发错误 对应MediaError.code 3                     | 参考MediaError |
| 114       | video触发错误 对应MediaError.code 4                     | 参考MediaError |
| 200       | mediaSourceError 初始化MSE错误，MediaSource未定义时触发 |                |
| 201       | addSourceBufferError MSE增加SourceBuffer失败            |                |
| 202       | sourceBufferError MSE的SourceBuffer触发错误             |                |
| 203       | endOfStreamError MSE结束流错误                          |                |
| 204       | appendBufferError MSE填充buffer错误                     |                |
| 205       | SourceBuffer changeType 错误                            |                |
| 301       | 解封装错误                                              |                |
| 302       | 重新封装错误                                            |                |
| 303       | remuxAllocError 重新封装alloc mdat存储错误              |                |
| 304       | remux worker报错                                        |                |
| 305       | 未找到解封装器                                          |                |
| 400       | manifestParsingError manifest解析错误                   |                |
| 401       | levelSwitchError HLS level切换错误                      |                |
| 500~506   | 加密视频解密错误                                        |                |
| 600       | wasm解码库加载失败                                      |                |
| 601       | wasm解码库启动失败                                      |                |
| 602       | wasm解码库渲染失败                                      |                |
| 603       | wasm解码时WebGL发生错误                                 |                |
| 604       | wasm解码不支持                                          |                |
| 1011~1019 | webRTC直播错误                                          |                |

错误码111~114 参考[MediaError code说明](https://developer.mozilla.org/en-US/docs/Web/API/MediaError/code)，

