@havue/ws-video-manager 1.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +3 -0
- package/dist/types/src/hooks/useVideoPlay.d.ts +73 -0
- package/dist/types/src/index.d.ts +5 -0
- package/dist/types/src/loader/index.d.ts +2 -0
- package/dist/types/src/loader/websocket-loader.d.ts +62 -0
- package/dist/types/src/manager/index.d.ts +144 -0
- package/dist/types/src/render/drawer.d.ts +44 -0
- package/dist/types/src/render/index.d.ts +105 -0
- package/dist/ws-video-manager.mjs +8132 -0
- package/dist/ws-video-manager.umd.js +8135 -0
- package/package.json +41 -0
package/README.md
ADDED
|
@@ -0,0 +1,73 @@
|
|
|
1
|
+
import type { Ref, MaybeRef } from 'vue';
|
|
2
|
+
import type { RenderConstructorOptionType, VideoInfo } from '../render';
|
|
3
|
+
import { type WsVideoManager } from '../manager';
|
|
4
|
+
export type CanvasResizeOption = {
|
|
5
|
+
/** 是否启用自动更新canvas width 和 height属性,默认为true */
|
|
6
|
+
enable?: boolean;
|
|
7
|
+
/** 设置canvas width 和 height时,
|
|
8
|
+
* 缩放的比例,即元素实际尺寸乘以scale,
|
|
9
|
+
* 放大是为了画面更清晰
|
|
10
|
+
* 默认 1
|
|
11
|
+
*/
|
|
12
|
+
scale?: number;
|
|
13
|
+
/** 限制canvas width最大值,默认1920 */
|
|
14
|
+
maxWidth?: number;
|
|
15
|
+
/** 限制canvas height最大值,默认1080 */
|
|
16
|
+
maxHeight?: number;
|
|
17
|
+
};
|
|
18
|
+
export type ParamsOptions = {
|
|
19
|
+
/** websocket 地址 */
|
|
20
|
+
wsUrl: MaybeRef<string | undefined>;
|
|
21
|
+
/** 是否播放视频 */
|
|
22
|
+
isReady: MaybeRef<boolean>;
|
|
23
|
+
/** 使用的WsVideoManager 实例 默认为wsVideoPlayer */
|
|
24
|
+
wsVideoPlayerIns?: WsVideoManager;
|
|
25
|
+
/** 视频渲染到的canvas元素, 不传会返回一个元素引用变量:canvasRef */
|
|
26
|
+
target?: MaybeRef<HTMLCanvasElement | undefined>;
|
|
27
|
+
/** 是否自动更新canvas width和height属性的配置, 默认为 DEFAULT_RESIZE_OPTIONS */
|
|
28
|
+
canvasResize?: MaybeRef<CanvasResizeOption | undefined>;
|
|
29
|
+
/** 视口中元素不可见时断开连接, 默认为true */
|
|
30
|
+
closeOnHidden?: MaybeRef<boolean>;
|
|
31
|
+
/** 自定义Render配置 */
|
|
32
|
+
renderOptions?: MaybeRef<Partial<RenderConstructorOptionType>>;
|
|
33
|
+
};
|
|
34
|
+
export declare const DEFAULT_RESIZE_OPTIONS: Readonly<{
|
|
35
|
+
enable: true;
|
|
36
|
+
scale: 1;
|
|
37
|
+
maxWidth: 1920;
|
|
38
|
+
maxHeight: 1080;
|
|
39
|
+
}>;
|
|
40
|
+
export type ReturnType = {
|
|
41
|
+
/** canvas引用 */
|
|
42
|
+
canvasRef: Ref<HTMLCanvasElement | undefined>;
|
|
43
|
+
/** 是否静音 */
|
|
44
|
+
isMuted: Ref<boolean>;
|
|
45
|
+
/** 是否暂停 */
|
|
46
|
+
isPaused: Ref<boolean>;
|
|
47
|
+
/** 视频信息 */
|
|
48
|
+
videoInfo: Ref<VideoInfo>;
|
|
49
|
+
/** 已经连接的WebSocket地址列表 */
|
|
50
|
+
linkedWsUrlList: Ref<string[]>;
|
|
51
|
+
/** 视频流地址是否已添加 */
|
|
52
|
+
isLinked: Ref<boolean>;
|
|
53
|
+
/** 是否达到websocket拉流数最大值 */
|
|
54
|
+
isReachConnectLimit: Ref<boolean>;
|
|
55
|
+
/** 暂停其他WebSocket视频流的音频播放 */
|
|
56
|
+
pauseOtherAudio: () => void;
|
|
57
|
+
/** 设置当前WebSocket视频流的音频是否暂停 */
|
|
58
|
+
setAudioMutedState: (muted: boolean) => void;
|
|
59
|
+
/** 暂停其他WebSocket视频流的视频播放 */
|
|
60
|
+
pauseOtherVideo: () => void;
|
|
61
|
+
/** 设置当前WebSocket视频流的视频是否暂停 */
|
|
62
|
+
setOneVideoPausedState: (paused: boolean) => void;
|
|
63
|
+
/** 设置所有WebSocket视频流的视频是否暂停 */
|
|
64
|
+
setAllVideoPausedState: (paused: boolean) => void;
|
|
65
|
+
/** 刷新当前WebSocket视频流的时间,如果连接断开会进行重连 */
|
|
66
|
+
refresh: () => void;
|
|
67
|
+
};
|
|
68
|
+
/**
|
|
69
|
+
* websocket视频流播放
|
|
70
|
+
* @param {ParamsOptions} options 配置项
|
|
71
|
+
* @returns
|
|
72
|
+
*/
|
|
73
|
+
export declare function useVideoPlay(options: ParamsOptions): ReturnType;
|
|
@@ -0,0 +1,62 @@
|
|
|
1
|
+
/** 心跳配置 */
|
|
2
|
+
type HeartbeatConfigType = {
|
|
3
|
+
/** 只发送一次 */
|
|
4
|
+
once: boolean;
|
|
5
|
+
/** 心跳消息 */
|
|
6
|
+
message: string;
|
|
7
|
+
/** 时间间隔 */
|
|
8
|
+
interval?: number;
|
|
9
|
+
};
|
|
10
|
+
/** 重连配置 */
|
|
11
|
+
type InterruptConfigType = {
|
|
12
|
+
/** 是否重连 */
|
|
13
|
+
reconnect: boolean;
|
|
14
|
+
/** 最大重连次数 */
|
|
15
|
+
maxReconnectTimes: number;
|
|
16
|
+
/** 每次重连延时 */
|
|
17
|
+
delay: number;
|
|
18
|
+
};
|
|
19
|
+
export type WebSocketOptionsType = {
|
|
20
|
+
/** WebSocket 子协议 WebSocket(url: string, protocols: string | string[]) */
|
|
21
|
+
protocols?: string | string[];
|
|
22
|
+
/** WebSocket 连接所传输二进制数据的类型 */
|
|
23
|
+
binaryType?: WebSocket['binaryType'];
|
|
24
|
+
heartbeat?: HeartbeatConfigType;
|
|
25
|
+
interrupt?: InterruptConfigType;
|
|
26
|
+
};
|
|
27
|
+
type EventType = {
|
|
28
|
+
open: Event;
|
|
29
|
+
message: MessageEvent;
|
|
30
|
+
close: CloseEvent;
|
|
31
|
+
error: Event;
|
|
32
|
+
reconnect: undefined;
|
|
33
|
+
};
|
|
34
|
+
declare class WebSocketLoader {
|
|
35
|
+
private _url;
|
|
36
|
+
private _protocols;
|
|
37
|
+
private _binaryType;
|
|
38
|
+
private _ws;
|
|
39
|
+
private _heartbeatConfig;
|
|
40
|
+
private _heartbeatTimer;
|
|
41
|
+
private _eventMap;
|
|
42
|
+
private _isManualClose;
|
|
43
|
+
private _interruptConfig;
|
|
44
|
+
private _interruptReconnectTimes;
|
|
45
|
+
private _interruptReconnectTimer;
|
|
46
|
+
constructor(url: string, options?: WebSocketOptionsType);
|
|
47
|
+
get isConnecting(): boolean;
|
|
48
|
+
private triggerEvents;
|
|
49
|
+
private bindWebSocketEvents;
|
|
50
|
+
private startHeartbeat;
|
|
51
|
+
private stopHeartbeat;
|
|
52
|
+
private innerReconnect;
|
|
53
|
+
open(): void;
|
|
54
|
+
close(): void;
|
|
55
|
+
reconnect(): void;
|
|
56
|
+
destroy(): void;
|
|
57
|
+
on<T extends keyof EventType>(eventName: T, callback: (event: EventType[T]) => void): void;
|
|
58
|
+
off<T extends keyof EventType>(eventName: T, callback: (event: EventType[T]) => void): void;
|
|
59
|
+
clear<T extends keyof EventType>(eventName: T): void;
|
|
60
|
+
sendMessage(message: string): void;
|
|
61
|
+
}
|
|
62
|
+
export default WebSocketLoader;
|
|
@@ -0,0 +1,144 @@
|
|
|
1
|
+
import type { WebSocketOptionsType } from '../loader/websocket-loader';
|
|
2
|
+
import type { RenderConstructorOptionType, VideoInfo } from '../render';
|
|
3
|
+
import { EventBus } from '@havue/shared';
|
|
4
|
+
import { RenderEventsEnum, AudioState, VideoState } from '../render';
|
|
5
|
+
export type WsVideoManaCstorOptionType = {
|
|
6
|
+
/** 预监流连接数量限制, 移动端默认10个,pc端默认32个 */
|
|
7
|
+
connectLimit?: number;
|
|
8
|
+
/** WebSocketLoader 实例配置 */
|
|
9
|
+
wsOptions?: WebSocketOptionsType;
|
|
10
|
+
/**
|
|
11
|
+
* websocket重连时,重新解析视频编码方式,
|
|
12
|
+
* 默认 true
|
|
13
|
+
*/
|
|
14
|
+
reparseMimeOnReconnect?: boolean;
|
|
15
|
+
/** Render 实例配置 */
|
|
16
|
+
renderOptions?: Partial<RenderConstructorOptionType>;
|
|
17
|
+
/**
|
|
18
|
+
* 是否使用WebGL,
|
|
19
|
+
* 默认 false,
|
|
20
|
+
* WebGL在不同游览器,以及受限于显存,不能同时创建过多WebGL上下文,一般8-16个 */
|
|
21
|
+
useWebgl?: boolean;
|
|
22
|
+
};
|
|
23
|
+
export declare enum EventEnums {
|
|
24
|
+
WS_URL_CHANGE = "wsUrlChange",
|
|
25
|
+
SOCKET_CLOSE = "socketClose",
|
|
26
|
+
CONNECT_LIMIT = "connectLimit"
|
|
27
|
+
}
|
|
28
|
+
type Events = {
|
|
29
|
+
[EventEnums.WS_URL_CHANGE]: (urls: string[]) => void;
|
|
30
|
+
[RenderEventsEnum.AUDIO_STATE_CHANGE]: (url: string, state: AudioState) => void;
|
|
31
|
+
[RenderEventsEnum.VIDEO_INFO_UPDATE]: (url: string, info: VideoInfo) => void;
|
|
32
|
+
[RenderEventsEnum.VIDEO_STATE_CHANGE]: (url: string, state: VideoState) => void;
|
|
33
|
+
[EventEnums.SOCKET_CLOSE]: (url: string) => void;
|
|
34
|
+
[EventEnums.CONNECT_LIMIT]: () => void;
|
|
35
|
+
};
|
|
36
|
+
export declare const WsVideoManagerEventEnums: typeof EventEnums & typeof RenderEventsEnum;
|
|
37
|
+
export declare class WsVideoManager extends EventBus<Events> {
|
|
38
|
+
/** socket连接 渲染相关对应信息 */
|
|
39
|
+
private _wsInfoMap;
|
|
40
|
+
private _option;
|
|
41
|
+
private _reqAnimationID;
|
|
42
|
+
constructor(options?: WsVideoManaCstorOptionType);
|
|
43
|
+
get linkedUrlList(): string[];
|
|
44
|
+
get connectLimit(): number;
|
|
45
|
+
private _setAnimate;
|
|
46
|
+
/**
|
|
47
|
+
* 添加socket实例
|
|
48
|
+
* @param url socket地址
|
|
49
|
+
* @returns
|
|
50
|
+
*/
|
|
51
|
+
private _addSocket;
|
|
52
|
+
/**
|
|
53
|
+
* 绑定render事件
|
|
54
|
+
* @param url 连接地址
|
|
55
|
+
* @param render Render实例
|
|
56
|
+
*/
|
|
57
|
+
private _bindRenderEvent;
|
|
58
|
+
/**
|
|
59
|
+
* 销毁socket实例
|
|
60
|
+
* @param url socket地址
|
|
61
|
+
*/
|
|
62
|
+
private _removeSocket;
|
|
63
|
+
/**
|
|
64
|
+
* 绑定socket事件
|
|
65
|
+
* @param url 连接地址
|
|
66
|
+
* @param socket WebSocketLoader实例
|
|
67
|
+
*/
|
|
68
|
+
private _bindSocketEvent;
|
|
69
|
+
private _emitWsUrlListChange;
|
|
70
|
+
/**
|
|
71
|
+
* url对应的 socket实例是否已存在
|
|
72
|
+
* @param url socket地址
|
|
73
|
+
* @returns boolean
|
|
74
|
+
*/
|
|
75
|
+
private _isSocketExist;
|
|
76
|
+
/**
|
|
77
|
+
* 添加url对应socket,以及需要绘制的canvas元素
|
|
78
|
+
* @param canvas canvas元素
|
|
79
|
+
* @param url socket url地址
|
|
80
|
+
*/
|
|
81
|
+
addCanvas(canvas: HTMLCanvasElement, url: string, renderOptions?: Partial<RenderConstructorOptionType>): void;
|
|
82
|
+
/**
|
|
83
|
+
* 初始化canvas背景
|
|
84
|
+
* @param canvas canvas元素
|
|
85
|
+
* @returns
|
|
86
|
+
*/
|
|
87
|
+
/**
|
|
88
|
+
* 删除canvas元素
|
|
89
|
+
* @param canvas canvas元素
|
|
90
|
+
*/
|
|
91
|
+
removeCanvas(canvas: HTMLCanvasElement): void;
|
|
92
|
+
/**
|
|
93
|
+
* 返回canvas是否已经添加过
|
|
94
|
+
* @param canvas canvas元素
|
|
95
|
+
* @returns boolean
|
|
96
|
+
*/
|
|
97
|
+
isCanvasExist(canvas: HTMLCanvasElement): boolean;
|
|
98
|
+
/** 设置全部render静音状态 */
|
|
99
|
+
setAllVideoMutedState(muted: boolean): void;
|
|
100
|
+
/** 更新单个render实例的配置 */
|
|
101
|
+
updateRenderOptions(url: string, options?: Partial<RenderConstructorOptionType>): void;
|
|
102
|
+
/**
|
|
103
|
+
* 设置单个render静音状态
|
|
104
|
+
* @param url
|
|
105
|
+
* @param muted boolean 是否静音
|
|
106
|
+
*/
|
|
107
|
+
setOneMutedState(url: string, muted: boolean): void;
|
|
108
|
+
/**
|
|
109
|
+
* 获取url对应render video元素是否静音
|
|
110
|
+
* @param url socket地址
|
|
111
|
+
*/
|
|
112
|
+
getOneMutedState(url: string): boolean;
|
|
113
|
+
/**
|
|
114
|
+
* 单个解除静音,其他未静音的变成静音,只播放一个
|
|
115
|
+
* @param url socket地址
|
|
116
|
+
*/
|
|
117
|
+
playOneAudio(url: string): void;
|
|
118
|
+
/**
|
|
119
|
+
* 设置单个render是否继续处理ws数据
|
|
120
|
+
* @param url
|
|
121
|
+
*/
|
|
122
|
+
setOneVideoPausedState(url: string, paused: boolean): void;
|
|
123
|
+
/** 设置全部render是否继续处理ws数据 */
|
|
124
|
+
setAllVideoPausedState(paused: boolean): void;
|
|
125
|
+
/**
|
|
126
|
+
* 获取url对应render video元素是否继续播放
|
|
127
|
+
* @param url socket地址
|
|
128
|
+
*/
|
|
129
|
+
getOneVideoPausedState(url: string): boolean;
|
|
130
|
+
/**
|
|
131
|
+
* 单个视频继续播放,其他暂停处理数据
|
|
132
|
+
* @param url socket地址
|
|
133
|
+
*/
|
|
134
|
+
playOneVideo(url: string): void;
|
|
135
|
+
/**
|
|
136
|
+
* 刷新socket,以及播放时间
|
|
137
|
+
*/
|
|
138
|
+
refresh(url?: string): void;
|
|
139
|
+
/**
|
|
140
|
+
* 销毁
|
|
141
|
+
*/
|
|
142
|
+
destroy(): void;
|
|
143
|
+
}
|
|
144
|
+
export {};
|
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* 绘制视频到canvas中
|
|
3
|
+
*/
|
|
4
|
+
declare class CanvasDrawer {
|
|
5
|
+
private _canvas;
|
|
6
|
+
private _useGl;
|
|
7
|
+
private _ctx2d;
|
|
8
|
+
private _gl;
|
|
9
|
+
private _program;
|
|
10
|
+
private _positionBuffer;
|
|
11
|
+
private _texCoordBuffer;
|
|
12
|
+
private _texture;
|
|
13
|
+
private _positionLocation;
|
|
14
|
+
private _texCoordLocation;
|
|
15
|
+
private _textureLocation;
|
|
16
|
+
private _glReady;
|
|
17
|
+
constructor(canvas: HTMLCanvasElement, useWebgl?: boolean);
|
|
18
|
+
private init2d;
|
|
19
|
+
/**
|
|
20
|
+
* 初始化 webgl
|
|
21
|
+
*/
|
|
22
|
+
private initGl;
|
|
23
|
+
/**
|
|
24
|
+
* 创建着色器源码
|
|
25
|
+
*/
|
|
26
|
+
private createShaderSource;
|
|
27
|
+
/**
|
|
28
|
+
* 创建着色器
|
|
29
|
+
*/
|
|
30
|
+
private createShader;
|
|
31
|
+
/**
|
|
32
|
+
* 创建着色器程序
|
|
33
|
+
*/
|
|
34
|
+
private createProgram;
|
|
35
|
+
/**
|
|
36
|
+
* 绘制
|
|
37
|
+
*/
|
|
38
|
+
draw(video: HTMLVideoElement): void;
|
|
39
|
+
/**
|
|
40
|
+
* 销毁
|
|
41
|
+
*/
|
|
42
|
+
destroy(): void;
|
|
43
|
+
}
|
|
44
|
+
export { CanvasDrawer };
|
|
@@ -0,0 +1,105 @@
|
|
|
1
|
+
import { EventBus } from '@havue/shared';
|
|
2
|
+
export type RenderConstructorOptionType = {
|
|
3
|
+
/** 当前播放currentTime和最新视频时长最多相差 秒数,默认0.3s */
|
|
4
|
+
liveMaxLatency: number;
|
|
5
|
+
/** 最多缓存ws传输的未处理的buffer数据大小, 默认200kb */
|
|
6
|
+
maxCacheBufByte: number;
|
|
7
|
+
/** 最多存储的时间,用于清除在currentTime之前x秒时间节点前的buffer数据, 默认10s */
|
|
8
|
+
maxCache: number;
|
|
9
|
+
};
|
|
10
|
+
export declare const WS_VIDEO_RENDER_DEFAULT_OPTIONS: Readonly<{
|
|
11
|
+
liveMaxLatency: 0.3;
|
|
12
|
+
maxCacheBufByte: number;
|
|
13
|
+
maxCache: 10;
|
|
14
|
+
}>;
|
|
15
|
+
export declare enum AudioState {
|
|
16
|
+
NOTMUTED = "notmuted",
|
|
17
|
+
MUTED = "muted"
|
|
18
|
+
}
|
|
19
|
+
export declare enum VideoState {
|
|
20
|
+
PLAY = "play",
|
|
21
|
+
PAUSE = "pause"
|
|
22
|
+
}
|
|
23
|
+
export type VideoInfo = {
|
|
24
|
+
width: number;
|
|
25
|
+
height: number;
|
|
26
|
+
};
|
|
27
|
+
export declare enum RenderEventsEnum {
|
|
28
|
+
AUDIO_STATE_CHANGE = "audioStateChange",
|
|
29
|
+
VIDEO_STATE_CHANGE = "videoStateChange",
|
|
30
|
+
VIDEO_INFO_UPDATE = "videoInfoUpdate"
|
|
31
|
+
}
|
|
32
|
+
export type RenderEvents = {
|
|
33
|
+
[RenderEventsEnum.AUDIO_STATE_CHANGE]: (s: AudioState) => void;
|
|
34
|
+
[RenderEventsEnum.VIDEO_STATE_CHANGE]: (s: VideoState) => void;
|
|
35
|
+
[RenderEventsEnum.VIDEO_INFO_UPDATE]: (info: VideoInfo) => void;
|
|
36
|
+
};
|
|
37
|
+
export declare class Render extends EventBus<RenderEvents> {
|
|
38
|
+
/** video元素 */
|
|
39
|
+
private _videoEl;
|
|
40
|
+
/** pixi.js 实例 */
|
|
41
|
+
/** mp4box 实例 */
|
|
42
|
+
private _mp4box;
|
|
43
|
+
/** 接收到的socket消息 视频数据buffer数组 */
|
|
44
|
+
private _bufsQueue;
|
|
45
|
+
/** MediaSource 实例 */
|
|
46
|
+
private _mediaSource;
|
|
47
|
+
/** SourceBuffer 实例 */
|
|
48
|
+
private _sourceBuffer;
|
|
49
|
+
/** 用于MediaSource的mimeType */
|
|
50
|
+
private _mimeType;
|
|
51
|
+
/** 是否暂停播放 */
|
|
52
|
+
private _paused;
|
|
53
|
+
private _options;
|
|
54
|
+
private _cacheAnimationID;
|
|
55
|
+
constructor(options?: Partial<RenderConstructorOptionType>);
|
|
56
|
+
get muted(): boolean;
|
|
57
|
+
set muted(val: boolean);
|
|
58
|
+
set paused(paused: boolean);
|
|
59
|
+
get paused(): boolean;
|
|
60
|
+
get videoEl(): HTMLVideoElement | undefined;
|
|
61
|
+
/** 更新实例配置 */
|
|
62
|
+
updateOptions(option?: Partial<RenderConstructorOptionType>): void;
|
|
63
|
+
/**
|
|
64
|
+
* 添加视频流buffer数据
|
|
65
|
+
* @param buf
|
|
66
|
+
*/
|
|
67
|
+
appendMediaBuffer(bufs: Array<ArrayBuffer & {
|
|
68
|
+
fileStart: number;
|
|
69
|
+
}>): void;
|
|
70
|
+
/**
|
|
71
|
+
* mp4box解析完成
|
|
72
|
+
* @param info mp4box解析信息
|
|
73
|
+
*/
|
|
74
|
+
private _onMp4boxReady;
|
|
75
|
+
/**
|
|
76
|
+
* 初始化视频元素
|
|
77
|
+
*/
|
|
78
|
+
private _setupVideo;
|
|
79
|
+
/**
|
|
80
|
+
* 是否支持Media Source Extention
|
|
81
|
+
* @returns boolean
|
|
82
|
+
*/
|
|
83
|
+
isSupportMSE(): boolean;
|
|
84
|
+
/**
|
|
85
|
+
* 初始化MSE
|
|
86
|
+
* @returns
|
|
87
|
+
*/
|
|
88
|
+
private _setupMSE;
|
|
89
|
+
/**
|
|
90
|
+
* 将_bufsQueue中的数据添加到SourceBuffer中
|
|
91
|
+
* @returns
|
|
92
|
+
*/
|
|
93
|
+
private _cache;
|
|
94
|
+
/**
|
|
95
|
+
* 刷新播放时间为最新
|
|
96
|
+
*/
|
|
97
|
+
refresh(): void;
|
|
98
|
+
/** 重置解析的视频mime type */
|
|
99
|
+
resetMimeType(): void;
|
|
100
|
+
private destroyMediaSource;
|
|
101
|
+
/**
|
|
102
|
+
* 销毁
|
|
103
|
+
*/
|
|
104
|
+
destroy(): void;
|
|
105
|
+
}
|