kwai-player-web
如何使用
播放组件的属性、API 及事件参考了 HTMLVideoElement 的实现。
需要参考的文档:
Demo 与 API 文档
播放组件提供 React 组件,vue2/vue3 组件,原生 js 方式接入
支持格式
H.264 | HEVC | AV1 | KVC3 | KVC4 | |
---|---|---|---|---|---|
flv + flv 切片 | 支持 | wasm 解码器 + 浏览器解码器 | 浏览器解码 | x | x |
mp4 | 支持 | wasm 解码器 + 浏览器解码器 | 浏览器解码 | wasm 解码器 | wasm 解码器 |
HLS | 支持 | wasm 解码器 + 浏览器解码器 | x | wasm 解码器 | wasm 解码器 |
裸流 | 支持 | wasm 解码器 + 浏览器解码器 | x | wasm 解码器 | wasm 解码器 |
webRTC 直播 | 支持 | - | - | - | - |
面向普通用户的场景不推荐使用 wasm 解码器。如果要使用 HEVC/AV1 编码,推荐采用混合 manifest方案。
CORS
视频资源必须允许 GET 请求,且包含CORS响应头。
视频资源
通过播放组件的 src 传入的视频资源可以是以下几种类型:
- 基础媒体描述
- 视频 URL
- File / Blob
- 多码率 KwaiManifest(快手私有协议)
- 直播多码率 manifest(快手私有协议)
- 混合编码媒体描述
- 混合封装格式媒体描述
/**
* 基础媒体描述,可以输入url、File或者快手私有Manifest
* @public
*/
export type BaseMediaDescription =
| string
| Blob
| KwaiManifest
| FlvAbrManifest
| FlvMultipartManifest
| HLSManifest;
/**
* 混合编码媒体描述
* 输入不同编码的视频源,SDK会根据浏览器解码能力选择一组播放,目前支持h264/hevc/av1
* @example
* 混合输入HEVC和H264示例
* ```
* {
* hevc: BaseMediaDescription,
* h264: BaseMediaDescription,
* }
* ```
*/
export type MixCodecMediaDescription = Partial<
Record<CodecType, BaseMediaDescription>
> &
Record<string, any>;
/**
* 混合封装格式媒体描述
* 参考HTMLSourceElement定义
* @example
* 输入flv流和hls流,在大部分情况都会播放flv格式的流,在iOS上会播放hls的流
* ```
* [
* {src: "http://xxxx/xxx.flv"},
* {src: "http://xxxx/xxx.m3u8"}
* ]
* ```
* @see {@link https://developer.mozilla.org/en-US/docs/Web/API/HTMLSourceElement}
* @public
*/
export type MixContainerMediaDescription = {
src: BaseMediaDescription | MixCodecMediaDescription,
type?: string,
} & Record<string, any>;
混合封装格式媒体描述
功能类似 HTMLVideoElement 中使用 HTMLSourceElement,一次传入多种格式的源,自动选择合适的流
src 格式: [{ src: 视频 URL/manifest, type?: mimeType }, { src: 视频 URL/manifest, type?: mimeType }]
type 为可选值,参考文档:MIME types
// 移动端H5直播示例
[
{ src: 'http://xxx/1.flv', type: 'video/x-flv' },
{ src: 'http://xxx/1.m3u8', type: 'application/vnd.apple.mpegURL' },
];
// 以上示例会在大部分android中播放flv源,ios中播放hls
混合编码媒体描述
混和编码媒体描述的子项为基础媒体描述。默认仅使用浏览器解码
- 当基础描述为"多码率 KwaiManifest / 直播多码率 manifest"时,播放组件会根据浏览器解码能力把他们混合为一个 manifet 进行播放;
- 当基础描述为"视频 URL / File / Blob"时,播放组件会根据浏览器解码能力选择其中一个子项;
各编码类型的视频资源必须是统一封装格式
播放组件会按照 av1 > hevc > h264 的优先级进行选择
// 传入url示例
{
h264: 'http://xxx/264.mp4', // 必选
hevc: 'http://xxx/hevc.mp4', // 可选
av1: 'http://xxx/av1.mp4' // 可选
}
传入多码率 manifest 资源时,最终会形成类似以下形式的新 manifest
资源质量 | 编码类型 |
---|---|
4k | h264 |
1080P 60fps | h264 |
1080P 30fps | hevc/av1 |
720P 60fps | hevc/av1 |
540P | hevc/av1 |
播放 HEVC/KVC 说明
浏览器不支持 HEVC/KVC 解码时,会采用 wasm 解码器。
采用 wasm 解码器时,上层业务是无感知的。
wasm 解码器兼容性:
chrome 67+
wasm 解码器性能优化
播放组件在使用 wasm 解码器器时支持多线程解码及 SIMD,且会根据浏览器能力开启对应的加速解码功能。
多线程解码用到了 SharedArrayBuffer,chrome 92+需要对播放页增加两个响应头,推荐添加
Cross-Origin-Embedder-Policy: require-corp
Cross-Origin-Opener-Policy: same-origin
播放页中的部分标签可能需要添加crossorigin属性
页面增加这两个头会导致无法加载跨域资源。以下是以图片为例的解决方案。
- 解决方案 A:在图片的响应头中添加:Cross-Origin-Resource-Policy: cross-origin;
- 解决方案 B:img 标签中增加 crossorigin 属性
插件
播放组件实现了一整套的插件系统,水印、控制条等都通过插件实现
自定义插件
通过集成 PluginModule 实现一个插件,例如水印插件
import KwaiPlayer, { PluginModule } from '@ks-video/kwai-player-web';
export default class WaterMarkPlugin extends PluginModule {
name = 'WaterMarkPlugin';
private player: KwaiPlayer | undefined;
private container: HTMLDivElement | undefined;
beforeInstall(): void {}
afterInstall(player: KwaiPlayer, options: { domid?: '' }): void {
this.player = player;
const main = this.player.getMainContainer();
const watermark = main?.querySelector(
options.domid || '[kwai-player-watermark=""]'
) as HTMLElement;
if (watermark) {
this.container = this.player.createSubContainer();
this.container?.appendChild(watermark);
}
}
beforeUninstall(player: KwaiPlayer): void {
this.container && player?.removeSubContainer(this.container);
this.player = undefined;
this.container = undefined;
}
afterUninstall(): void {}
changePosition(x, y) {}
}
注册销毁插件
KwaiPlayer.register(WaterMarkPlugin); //注册
KwaiPlayer.deregister(WaterMarkPlugin); //注销
插件传参
new KwaiPlayer('#player-1', {
plugins: {
WaterMarkPlugin: false,// 当前实例关闭水印插件
WaterMarkPlugin: {
id:'domid'
}, // 传入domid
}
}
调用插件
const plugin = player.getPluginInstance('ChromeControlsPlugin');
plugin.changePosition(100, 200);