sample-xmonitor-js 0.0.4 → 1.0.1
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/lib/Monitor.d.ts +26 -38
- package/lib/Monitor.js +30 -18
- package/lib/default/index.d.ts +54 -0
- package/lib/default/index.js +149 -0
- package/lib/index.d.ts +9 -12
- package/lib/index.js +57 -74
- package/lib/txrtc/index.d.ts +38 -0
- package/lib/txrtc/index.js +144 -0
- package/package.json +2 -2
- package/lib/DefaultMonitor.d.ts +0 -19
- package/lib/DefaultMonitor.js +0 -141
package/lib/Monitor.d.ts
CHANGED
|
@@ -8,42 +8,18 @@ export declare interface Setup {
|
|
|
8
8
|
*/
|
|
9
9
|
classify?: string;
|
|
10
10
|
/**
|
|
11
|
-
*
|
|
11
|
+
* 是否开启调试
|
|
12
12
|
*/
|
|
13
|
-
|
|
14
|
-
}
|
|
15
|
-
export declare interface DefaultSetup extends Setup {
|
|
16
|
-
audio?: false;
|
|
13
|
+
debug?: true;
|
|
17
14
|
/**
|
|
18
|
-
*
|
|
19
|
-
* 视频配置信息
|
|
20
|
-
* min: 最小画像宽度 max 最大画像宽度 ideal: 推荐的理想画质宽度
|
|
21
|
-
*
|
|
22
|
-
* user: 前置摄像头 environment:后置摄像头
|
|
23
|
-
* frameRate: 设置帧率 ideal 推荐帧率 max 最大帧率 受限带宽传输时,低帧率可能更适宜 eg: frameRate: { ideal: 10, max: 15 }
|
|
15
|
+
* 其他参数
|
|
24
16
|
*/
|
|
25
|
-
|
|
26
|
-
frameRate: {
|
|
27
|
-
ideal: number;
|
|
28
|
-
max: number;
|
|
29
|
-
};
|
|
30
|
-
facingMode: 'user' | 'environment';
|
|
31
|
-
width: number | {
|
|
32
|
-
min: number;
|
|
33
|
-
ideal: number;
|
|
34
|
-
max: number;
|
|
35
|
-
};
|
|
36
|
-
height: number | {
|
|
37
|
-
min: number;
|
|
38
|
-
ideal: number;
|
|
39
|
-
max: number;
|
|
40
|
-
};
|
|
41
|
-
};
|
|
17
|
+
[key: string]: any;
|
|
42
18
|
}
|
|
43
19
|
declare class Watcher {
|
|
44
20
|
private readonly monitor;
|
|
45
21
|
private readonly driver;
|
|
46
|
-
private readonly
|
|
22
|
+
private readonly type;
|
|
47
23
|
constructor(monitor: Monitor);
|
|
48
24
|
clean(): Promise<unknown>;
|
|
49
25
|
shot(sharpness?: number): Promise<any>;
|
|
@@ -58,7 +34,16 @@ export declare class ScreenTypeError extends Error {
|
|
|
58
34
|
readonly code: string;
|
|
59
35
|
constructor(message: any, code?: any);
|
|
60
36
|
}
|
|
61
|
-
export type
|
|
37
|
+
export type Device = 'screen' | 'camera' | 'mobile';
|
|
38
|
+
export type Provider = 'default' | 'txrtc';
|
|
39
|
+
export type DeviceProvider = 'default:screen' | 'default:camera' | 'default:mobile' | 'txrtc:screen' | 'txrtc:camera' | 'txrtc:mobile';
|
|
40
|
+
export declare class MonitorType {
|
|
41
|
+
readonly provider: Provider;
|
|
42
|
+
readonly device: Device;
|
|
43
|
+
constructor(provider: Provider, device: Device);
|
|
44
|
+
toString(): string;
|
|
45
|
+
static parse(str: DeviceProvider): MonitorType;
|
|
46
|
+
}
|
|
62
47
|
/**
|
|
63
48
|
* cancel 用户取消 不给授权 禁用摄像头
|
|
64
49
|
* start 开始录制
|
|
@@ -68,8 +53,8 @@ export type MonitorType = 'default:desktop' | 'default:camera';
|
|
|
68
53
|
* error 发生错误
|
|
69
54
|
* changed 状态改变
|
|
70
55
|
*/
|
|
71
|
-
export type MonitorEvent = 'cancel' | 'start' | 'playing' | 'pause' | 'shot' | 'stop' | 'error' | 'changed';
|
|
72
|
-
export declare const MonitorEvents: Array<
|
|
56
|
+
export type MonitorEvent = 'cancel' | 'start' | 'playing' | 'pause' | 'shot' | 'stop' | 'error' | 'changed' | 'message';
|
|
57
|
+
export declare const MonitorEvents: Array<MonitorEvent>;
|
|
73
58
|
export type MonitorEventObject = {
|
|
74
59
|
event: MonitorEvent;
|
|
75
60
|
target: Monitor;
|
|
@@ -78,10 +63,7 @@ export type MonitorEventObject = {
|
|
|
78
63
|
};
|
|
79
64
|
export declare class MObject {
|
|
80
65
|
/**
|
|
81
|
-
|
|
82
|
-
*/
|
|
83
|
-
readonly activity: string;
|
|
84
|
-
/**
|
|
66
|
+
/**
|
|
85
67
|
* 所属房间
|
|
86
68
|
*/
|
|
87
69
|
readonly room: string;
|
|
@@ -90,7 +72,7 @@ export declare class MObject {
|
|
|
90
72
|
*/
|
|
91
73
|
readonly id: string;
|
|
92
74
|
private constructor();
|
|
93
|
-
static create({ room, id
|
|
75
|
+
static create({ room, id }: Record<string, any>): MObject;
|
|
94
76
|
toString(): string;
|
|
95
77
|
}
|
|
96
78
|
export interface MonitorEventListener {
|
|
@@ -100,7 +82,7 @@ export type MonitorOptions = {
|
|
|
100
82
|
object: MObject;
|
|
101
83
|
type: MonitorType;
|
|
102
84
|
element: HTMLDivElement;
|
|
103
|
-
setup?:
|
|
85
|
+
setup?: Setup;
|
|
104
86
|
};
|
|
105
87
|
/**
|
|
106
88
|
* 监视器
|
|
@@ -119,12 +101,18 @@ export default class Monitor {
|
|
|
119
101
|
* 启动监控
|
|
120
102
|
*/
|
|
121
103
|
start(): any;
|
|
104
|
+
send(message: string): void;
|
|
122
105
|
/**
|
|
123
106
|
* 停止监控
|
|
124
107
|
*/
|
|
125
108
|
stop(): any;
|
|
126
109
|
addEventListener(event: MonitorEvent, listener: MonitorEventListener): void;
|
|
127
110
|
protected dispatchEvent(event: MonitorEvent, data?: any, error?: any): void;
|
|
111
|
+
switch(option: {
|
|
112
|
+
deviceId?: string;
|
|
113
|
+
useFrontCamera?: boolean;
|
|
114
|
+
[key: string]: any;
|
|
115
|
+
}): Promise<void>;
|
|
128
116
|
removeEventListener(event: MonitorEvent): void;
|
|
129
117
|
}
|
|
130
118
|
export {};
|
package/lib/Monitor.js
CHANGED
|
@@ -2,10 +2,10 @@ import Driver from 'xdriver';
|
|
|
2
2
|
class Watcher {
|
|
3
3
|
constructor(monitor) {
|
|
4
4
|
this.monitor = monitor;
|
|
5
|
-
this.
|
|
5
|
+
this.type = monitor.type;
|
|
6
6
|
let driver = new Driver('x-monitor');
|
|
7
7
|
driver.initialize(() => {
|
|
8
|
-
driver.createTables(['
|
|
8
|
+
driver.createTables(['screen', 'camera'], {
|
|
9
9
|
primaryKey: 'id',
|
|
10
10
|
autoIncrement: true
|
|
11
11
|
});
|
|
@@ -18,7 +18,6 @@ class Watcher {
|
|
|
18
18
|
return this.driver.drop();
|
|
19
19
|
}
|
|
20
20
|
shot(sharpness = 0.3) {
|
|
21
|
-
var _a;
|
|
22
21
|
if (sharpness > 1)
|
|
23
22
|
sharpness = 1;
|
|
24
23
|
if (sharpness < 0)
|
|
@@ -42,16 +41,12 @@ class Watcher {
|
|
|
42
41
|
img.no = this.monitor.no;
|
|
43
42
|
img.name = name;
|
|
44
43
|
img.data = canvas.toDataURL('jpg');
|
|
45
|
-
img.type = this.
|
|
46
|
-
img.classify =
|
|
47
|
-
|
|
48
|
-
if (table.indexOf(':') !== -1) {
|
|
49
|
-
table = table.split(':')[1];
|
|
50
|
-
}
|
|
51
|
-
return this.driver.insert(table, [img]).then(res => img);
|
|
44
|
+
img.type = this.type.device;
|
|
45
|
+
img.classify = this.monitor.options.setup?.classify;
|
|
46
|
+
return this.driver.insert(this.type.device, [img]).then(res => img);
|
|
52
47
|
}
|
|
53
48
|
select() {
|
|
54
|
-
return this.driver.query(this.
|
|
49
|
+
return this.driver.query(this.type.device);
|
|
55
50
|
}
|
|
56
51
|
}
|
|
57
52
|
export class NotSupportError extends Error {
|
|
@@ -66,18 +61,30 @@ export class ScreenTypeError extends Error {
|
|
|
66
61
|
this.code = code;
|
|
67
62
|
}
|
|
68
63
|
}
|
|
64
|
+
export class MonitorType {
|
|
65
|
+
constructor(provider, device) {
|
|
66
|
+
this.provider = provider;
|
|
67
|
+
this.device = device;
|
|
68
|
+
}
|
|
69
|
+
toString() {
|
|
70
|
+
return `${this.provider}:${this.device}`;
|
|
71
|
+
}
|
|
72
|
+
static parse(str) {
|
|
73
|
+
let [type, device] = str.split(':');
|
|
74
|
+
return new MonitorType(type, device);
|
|
75
|
+
}
|
|
76
|
+
}
|
|
69
77
|
export const MonitorEvents = ['cancel', 'start', 'playing', 'pause', 'shot', 'stop', 'error', 'changed'];
|
|
70
78
|
export class MObject {
|
|
71
|
-
constructor(room, id
|
|
72
|
-
this.activity = activity;
|
|
79
|
+
constructor(room, id) {
|
|
73
80
|
this.room = room;
|
|
74
81
|
this.id = id;
|
|
75
82
|
}
|
|
76
|
-
static create({ room, id
|
|
77
|
-
return new MObject(room, id
|
|
83
|
+
static create({ room, id }) {
|
|
84
|
+
return new MObject(room, id);
|
|
78
85
|
}
|
|
79
86
|
toString() {
|
|
80
|
-
return `${this.
|
|
87
|
+
return `${this.room}-${this.id}`;
|
|
81
88
|
}
|
|
82
89
|
}
|
|
83
90
|
/**
|
|
@@ -96,8 +103,7 @@ export default class Monitor {
|
|
|
96
103
|
return this.element.paused;
|
|
97
104
|
}
|
|
98
105
|
shot() {
|
|
99
|
-
|
|
100
|
-
return this.watcher.shot((_a = this.options.setup) === null || _a === void 0 ? void 0 : _a.sharpness).then(img => {
|
|
106
|
+
return this.watcher.shot(this.options.setup?.sharpness).then(img => {
|
|
101
107
|
this.dispatchEvent('shot', img);
|
|
102
108
|
return img;
|
|
103
109
|
});
|
|
@@ -107,6 +113,9 @@ export default class Monitor {
|
|
|
107
113
|
*/
|
|
108
114
|
start() {
|
|
109
115
|
}
|
|
116
|
+
send(message) {
|
|
117
|
+
throw new NotSupportError('不支持发送消息');
|
|
118
|
+
}
|
|
110
119
|
/**
|
|
111
120
|
* 停止监控
|
|
112
121
|
*/
|
|
@@ -123,6 +132,9 @@ export default class Monitor {
|
|
|
123
132
|
}
|
|
124
133
|
console.log(event, data, error);
|
|
125
134
|
}
|
|
135
|
+
async switch(option) {
|
|
136
|
+
throw new NotSupportError('不支持设备切换');
|
|
137
|
+
}
|
|
126
138
|
removeEventListener(event) {
|
|
127
139
|
this.eventPool.delete(event);
|
|
128
140
|
}
|
|
@@ -0,0 +1,54 @@
|
|
|
1
|
+
import Monitor, { Device, MObject, MonitorOptions, Setup } from "../Monitor";
|
|
2
|
+
export interface DefaultSetup extends Setup {
|
|
3
|
+
audio?: false;
|
|
4
|
+
/**
|
|
5
|
+
* [点击文档](https://developer.mozilla.org/zh-CN/docs/Web/API/MediaDevices/getUserMedia)
|
|
6
|
+
* 视频配置信息
|
|
7
|
+
* min: 最小画像宽度 max 最大画像宽度 ideal: 推荐的理想画质宽度
|
|
8
|
+
*
|
|
9
|
+
* user: 前置摄像头 environment:后置摄像头
|
|
10
|
+
* frameRate: 设置帧率 ideal 推荐帧率 max 最大帧率 受限带宽传输时,低帧率可能更适宜 eg: frameRate: { ideal: 10, max: 15 }
|
|
11
|
+
*/
|
|
12
|
+
video?: true | {
|
|
13
|
+
deviceId?: string;
|
|
14
|
+
frameRate?: {
|
|
15
|
+
ideal: number;
|
|
16
|
+
max: number;
|
|
17
|
+
};
|
|
18
|
+
facingMode?: 'user' | 'environment' | {
|
|
19
|
+
exact: "environment";
|
|
20
|
+
};
|
|
21
|
+
width?: number | {
|
|
22
|
+
min: number;
|
|
23
|
+
ideal: number;
|
|
24
|
+
max: number;
|
|
25
|
+
};
|
|
26
|
+
height?: number | {
|
|
27
|
+
min: number;
|
|
28
|
+
ideal: number;
|
|
29
|
+
max: number;
|
|
30
|
+
};
|
|
31
|
+
};
|
|
32
|
+
}
|
|
33
|
+
export default class DefaultMonitor extends Monitor {
|
|
34
|
+
private stream;
|
|
35
|
+
private active;
|
|
36
|
+
constructor(options: MonitorOptions);
|
|
37
|
+
protected getMedia(setup: DefaultSetup): any;
|
|
38
|
+
start(): Promise<any>;
|
|
39
|
+
stop(): Promise<any>;
|
|
40
|
+
static getMonitor(device: Device, object: MObject, element: HTMLDivElement, setup?: Setup): DefaultMonitor;
|
|
41
|
+
}
|
|
42
|
+
export declare class DefaultScreenMonitor extends DefaultMonitor {
|
|
43
|
+
constructor(object: MObject, element: HTMLDivElement, setup?: DefaultSetup);
|
|
44
|
+
start(): Promise<any>;
|
|
45
|
+
protected getMedia(setup: DefaultSetup): any;
|
|
46
|
+
}
|
|
47
|
+
export declare class DefaultCameraMonitor extends DefaultMonitor {
|
|
48
|
+
constructor(object: MObject, element: HTMLDivElement, setup?: DefaultSetup);
|
|
49
|
+
protected getMedia(setup: DefaultSetup): any;
|
|
50
|
+
switch(option: {
|
|
51
|
+
cameraId?: string;
|
|
52
|
+
useFrontCamera?: boolean;
|
|
53
|
+
}): Promise<void>;
|
|
54
|
+
}
|
|
@@ -0,0 +1,149 @@
|
|
|
1
|
+
import Monitor, { MonitorType, NotSupportError, ScreenTypeError } from "../Monitor";
|
|
2
|
+
let win = window;
|
|
3
|
+
const navigator = win.navigator;
|
|
4
|
+
if (!navigator.mediaDevices) {
|
|
5
|
+
navigator["mediaDevices"] = {
|
|
6
|
+
getUserMedia: (constraints) => {
|
|
7
|
+
return navigator.getUserMedia ? new Promise((resolve, reject) => {
|
|
8
|
+
navigator.getUserMedia(constraints, resolve, reject);
|
|
9
|
+
}) : Promise.reject(new NotSupportError('This browser not support getUserMedia'));
|
|
10
|
+
}
|
|
11
|
+
};
|
|
12
|
+
}
|
|
13
|
+
const { mediaDevices } = navigator;
|
|
14
|
+
if (!mediaDevices.getDisplayMedia) {
|
|
15
|
+
mediaDevices.getDisplayMedia = (options) => {
|
|
16
|
+
return Promise.reject(new NotSupportError('This browser not support getDisplayMedia'));
|
|
17
|
+
};
|
|
18
|
+
}
|
|
19
|
+
export default class DefaultMonitor extends Monitor {
|
|
20
|
+
constructor(options) {
|
|
21
|
+
super(options);
|
|
22
|
+
this.active = false;
|
|
23
|
+
}
|
|
24
|
+
getMedia(setup) { }
|
|
25
|
+
async start() {
|
|
26
|
+
if (this.active)
|
|
27
|
+
return;
|
|
28
|
+
let video = document.createElement('video');
|
|
29
|
+
video.setAttribute('autoplay', 'true');
|
|
30
|
+
// 该属性的作用是在ios下video可以播放 否则会显示黑屏
|
|
31
|
+
video.setAttribute('playsinline', '');
|
|
32
|
+
video.style.width = "100%";
|
|
33
|
+
video.style.height = "100%";
|
|
34
|
+
this.options.element?.appendChild(video);
|
|
35
|
+
this.element = video;
|
|
36
|
+
let stream;
|
|
37
|
+
try {
|
|
38
|
+
stream = await this.getMedia({ audio: false, video: true, ...this.options.setup });
|
|
39
|
+
}
|
|
40
|
+
catch (e) {
|
|
41
|
+
/*
|
|
42
|
+
* AbortError[中止错误]
|
|
43
|
+
* 尽管用户和操作系统都授予了访问设备硬件的权利,而且未出现可能抛出NotReadableError异常的硬件问题,但仍然有一些问题的出现导致了设备无法被使用。
|
|
44
|
+
* NotAllowedError[拒绝错误]
|
|
45
|
+
* 用户拒绝了当前的浏览器实例的访问请求;或者用户拒绝了当前会话的访问;或者用户在全局范围内拒绝了所有媒体访问请求。
|
|
46
|
+
* NotFoundError[找不到错误]
|
|
47
|
+
* 找不到满足请求参数的媒体类型。
|
|
48
|
+
* NotReadableError[无法读取错误]
|
|
49
|
+
* 尽管用户已经授权使用相应的设备,操作系统上某个硬件、浏览器或者网页层面发生的错误导致设备无法被访问。
|
|
50
|
+
* OverconstrainedError[无法满足要求错误]
|
|
51
|
+
* 指定的要求无法被设备满足,此异常是一个类型为OverconstrainedError的对象,拥有一个constraint属性,这个属性包含了当前无法被满足的constraint对象,还拥有一个message属性,包含了阅读友好的字符串用来说明情况。
|
|
52
|
+
*SecurityError[安全错误]
|
|
53
|
+
* 在getUserMedia() 被调用的 Document 上面,使用设备媒体被禁止。这个机制是否开启或者关闭取决于单个用户的偏好设置。
|
|
54
|
+
* TypeError[类型错误]
|
|
55
|
+
*constraints 对象未设置[空],或者都被设置为false。
|
|
56
|
+
*
|
|
57
|
+
* */
|
|
58
|
+
if (!(e instanceof NotSupportError)) {
|
|
59
|
+
this.dispatchEvent('error', void 0, e);
|
|
60
|
+
return;
|
|
61
|
+
}
|
|
62
|
+
throw e;
|
|
63
|
+
}
|
|
64
|
+
let { element } = this;
|
|
65
|
+
element.srcObject = stream;
|
|
66
|
+
this.stream = stream;
|
|
67
|
+
let track = stream.getTracks()[0];
|
|
68
|
+
if (this.options.type.device === 'screen' && !/^screen/i.test(track.label)) {
|
|
69
|
+
await this.stop();
|
|
70
|
+
this.dispatchEvent('error', null, new ScreenTypeError('Screen share type error', 'ScreenTypeError'));
|
|
71
|
+
return;
|
|
72
|
+
}
|
|
73
|
+
track.onended = e => {
|
|
74
|
+
this.active = false;
|
|
75
|
+
this.dispatchEvent('cancel');
|
|
76
|
+
};
|
|
77
|
+
element.onloadedmetadata = () => {
|
|
78
|
+
element.play();
|
|
79
|
+
this.dispatchEvent('start');
|
|
80
|
+
};
|
|
81
|
+
element.onplaying = () => {
|
|
82
|
+
this.dispatchEvent('playing');
|
|
83
|
+
this.active = true;
|
|
84
|
+
};
|
|
85
|
+
element.onended = () => {
|
|
86
|
+
this.active = false;
|
|
87
|
+
this.dispatchEvent('stop');
|
|
88
|
+
};
|
|
89
|
+
return track;
|
|
90
|
+
}
|
|
91
|
+
async stop() {
|
|
92
|
+
this.active = false;
|
|
93
|
+
if (this.stream) {
|
|
94
|
+
this.element.pause();
|
|
95
|
+
this.stream.getTracks().forEach((track) => track.stop());
|
|
96
|
+
this.stream = void 0;
|
|
97
|
+
}
|
|
98
|
+
this.element.remove();
|
|
99
|
+
super.stop();
|
|
100
|
+
}
|
|
101
|
+
static getMonitor(device, object, element, setup) {
|
|
102
|
+
if (device === 'screen') {
|
|
103
|
+
return new DefaultScreenMonitor(object, element, setup);
|
|
104
|
+
}
|
|
105
|
+
else if (device === 'camera' || device === 'mobile') {
|
|
106
|
+
return new DefaultCameraMonitor(object, element, setup);
|
|
107
|
+
}
|
|
108
|
+
throw new NotSupportError(`Device ${device} not support`, 'NotSupportError');
|
|
109
|
+
}
|
|
110
|
+
}
|
|
111
|
+
export class DefaultScreenMonitor extends DefaultMonitor {
|
|
112
|
+
constructor(object, element, setup) {
|
|
113
|
+
super({ type: new MonitorType('default', 'screen'), object, element, setup });
|
|
114
|
+
}
|
|
115
|
+
async start() {
|
|
116
|
+
return super.start();
|
|
117
|
+
}
|
|
118
|
+
getMedia(setup) {
|
|
119
|
+
return mediaDevices.getDisplayMedia(setup);
|
|
120
|
+
}
|
|
121
|
+
}
|
|
122
|
+
export class DefaultCameraMonitor extends DefaultMonitor {
|
|
123
|
+
constructor(object, element, setup) {
|
|
124
|
+
super({ type: new MonitorType('default', 'camera'), element, object, setup });
|
|
125
|
+
}
|
|
126
|
+
getMedia(setup) {
|
|
127
|
+
return mediaDevices.getUserMedia(setup);
|
|
128
|
+
}
|
|
129
|
+
async switch(option) {
|
|
130
|
+
await this.stop();
|
|
131
|
+
let video = {
|
|
132
|
+
...this.options.setup?.video,
|
|
133
|
+
deviceId: option.cameraId
|
|
134
|
+
};
|
|
135
|
+
if (typeof video !== 'boolean' && video) {
|
|
136
|
+
if (option.useFrontCamera === true) {
|
|
137
|
+
video.facingMode = 'user';
|
|
138
|
+
}
|
|
139
|
+
else if (option.useFrontCamera === false) {
|
|
140
|
+
video.facingMode = 'environment';
|
|
141
|
+
}
|
|
142
|
+
}
|
|
143
|
+
this.options.setup = {
|
|
144
|
+
...this.options.setup,
|
|
145
|
+
video
|
|
146
|
+
};
|
|
147
|
+
await this.start();
|
|
148
|
+
}
|
|
149
|
+
}
|
package/lib/index.d.ts
CHANGED
|
@@ -1,9 +1,7 @@
|
|
|
1
|
-
import Monitor, {
|
|
1
|
+
import Monitor, { DeviceProvider, MObject, MonitorEvent, MonitorEventListener, MonitorType, Setup } from "./Monitor";
|
|
2
|
+
import { DefaultSetup } from "./default";
|
|
3
|
+
import { TxrtcSetup } from "./txrtc";
|
|
2
4
|
export default class MonitorFactory {
|
|
3
|
-
/**
|
|
4
|
-
* 监控
|
|
5
|
-
*/
|
|
6
|
-
static INSTANCE?: MonitorFactory;
|
|
7
5
|
private readonly monitorMap;
|
|
8
6
|
private readonly pointer;
|
|
9
7
|
private readonly eventPool;
|
|
@@ -23,11 +21,11 @@ export default class MonitorFactory {
|
|
|
23
21
|
* @param {HTMLDivElement} element 视频所在div元素
|
|
24
22
|
* @param {any} setup 监视器相关的参数
|
|
25
23
|
*/
|
|
26
|
-
init(type: MonitorType, element: HTMLDivElement, setup?: Setup): Monitor
|
|
24
|
+
init(type: MonitorType, element: HTMLDivElement, setup?: Setup): Promise<Monitor>;
|
|
27
25
|
/**
|
|
28
26
|
* 启动所有监视器
|
|
29
27
|
*/
|
|
30
|
-
start(interval?: number):
|
|
28
|
+
start(interval?: number): void;
|
|
31
29
|
/**
|
|
32
30
|
* 停用监视器
|
|
33
31
|
*/
|
|
@@ -38,12 +36,11 @@ export declare function reset(): void;
|
|
|
38
36
|
* 初始化监控
|
|
39
37
|
*/
|
|
40
38
|
export declare function getInstance(options?: {
|
|
41
|
-
id:
|
|
42
|
-
room:
|
|
43
|
-
activity: any;
|
|
39
|
+
id: string;
|
|
40
|
+
room: string;
|
|
44
41
|
monitors: Array<{
|
|
45
|
-
|
|
42
|
+
provider: DeviceProvider;
|
|
46
43
|
element: any;
|
|
47
|
-
setup?: DefaultSetup
|
|
44
|
+
setup?: DefaultSetup | Omit<TxrtcSetup, 'roomId' | 'userId'>;
|
|
48
45
|
}>;
|
|
49
46
|
}): MonitorFactory;
|
package/lib/index.js
CHANGED
|
@@ -1,14 +1,6 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
|
|
5
|
-
function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
|
|
6
|
-
function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
|
|
7
|
-
step((generator = generator.apply(thisArg, _arguments || [])).next());
|
|
8
|
-
});
|
|
9
|
-
};
|
|
10
|
-
import { MObject, MonitorEvents } from "./Monitor";
|
|
11
|
-
import { CameraMonitor, DesktopMonitor } from "./DefaultMonitor";
|
|
1
|
+
import { MObject, MonitorEvents, MonitorType, NotSupportError } from "./Monitor";
|
|
2
|
+
import DefaultMonitor from "./default";
|
|
3
|
+
import TxrtcMonitor from "./txrtc";
|
|
12
4
|
export default class MonitorFactory {
|
|
13
5
|
constructor(pointer) {
|
|
14
6
|
this.monitorMap = new Map();
|
|
@@ -35,98 +27,89 @@ export default class MonitorFactory {
|
|
|
35
27
|
* @param {HTMLDivElement} element 视频所在div元素
|
|
36
28
|
* @param {any} setup 监视器相关的参数
|
|
37
29
|
*/
|
|
38
|
-
init(type, element, setup) {
|
|
30
|
+
async init(type, element, setup) {
|
|
39
31
|
let monitor;
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
monitor = new CameraMonitor(this.pointer, element, setup);
|
|
43
|
-
break;
|
|
44
|
-
case "default:desktop":
|
|
45
|
-
monitor = new DesktopMonitor(this.pointer, element, setup);
|
|
46
|
-
break;
|
|
47
|
-
default:
|
|
48
|
-
throw new Error(`Not support monitor type ${type}`);
|
|
32
|
+
if (type.provider === 'default') {
|
|
33
|
+
monitor = DefaultMonitor.getMonitor(type.device, this.pointer, element, setup);
|
|
49
34
|
}
|
|
50
|
-
|
|
35
|
+
else if (type.provider === 'txrtc') {
|
|
36
|
+
monitor = TxrtcMonitor.getMonitor(type.device, this.pointer, element, setup);
|
|
37
|
+
}
|
|
38
|
+
else {
|
|
39
|
+
throw new NotSupportError(`不支持的监视器类型${type.toString()}`, 'not_support');
|
|
40
|
+
}
|
|
41
|
+
for (const evt of MonitorEvents) {
|
|
51
42
|
monitor.addEventListener(evt, event => {
|
|
52
|
-
var _a;
|
|
53
43
|
// 监视器截图
|
|
54
|
-
|
|
44
|
+
this.eventPool.get(evt)?.call(monitor, event);
|
|
55
45
|
});
|
|
56
|
-
}
|
|
57
|
-
this.monitorMap.set(type, monitor);
|
|
46
|
+
}
|
|
47
|
+
this.monitorMap.set(type.toString(), monitor);
|
|
58
48
|
return monitor;
|
|
59
49
|
}
|
|
60
50
|
/**
|
|
61
51
|
* 启动所有监视器
|
|
62
52
|
*/
|
|
63
|
-
start() {
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
53
|
+
start(interval = 10000) {
|
|
54
|
+
if (interval < 5000) {
|
|
55
|
+
throw new Error('定时捕捉画面时间间隔不能少于5秒');
|
|
56
|
+
}
|
|
57
|
+
clearInterval(this.intervalId);
|
|
58
|
+
// 启动timer定时截图
|
|
59
|
+
console.log(`开启定时截图,时间间隔${interval}ms`);
|
|
60
|
+
this.intervalId = setInterval(async () => {
|
|
61
|
+
try {
|
|
62
|
+
// 调用所有监视器截图
|
|
63
|
+
for (let [, monitor] of this.monitorMap) {
|
|
64
|
+
if (monitor.isPaused())
|
|
65
|
+
continue;
|
|
66
|
+
await monitor.shot();
|
|
67
|
+
}
|
|
67
68
|
}
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
yield monitor.start();
|
|
69
|
+
catch (e) {
|
|
70
|
+
console.log(e);
|
|
71
71
|
}
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
continue;
|
|
80
|
-
yield monitor.shot();
|
|
81
|
-
}
|
|
82
|
-
}
|
|
83
|
-
catch (e) {
|
|
84
|
-
console.log(e);
|
|
85
|
-
}
|
|
86
|
-
}), interval);
|
|
87
|
-
});
|
|
72
|
+
}, interval);
|
|
73
|
+
// 启动所有监视器
|
|
74
|
+
for (let monitor of this.monitorMap.values()) {
|
|
75
|
+
console.log(`启动监视器 >>> ${monitor.type.toString()}`);
|
|
76
|
+
monitor.start();
|
|
77
|
+
}
|
|
78
|
+
console.log('所有监视器启动完成');
|
|
88
79
|
}
|
|
89
80
|
/**
|
|
90
81
|
* 停用监视器
|
|
91
82
|
*/
|
|
92
|
-
stop() {
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
}
|
|
99
|
-
});
|
|
83
|
+
async stop() {
|
|
84
|
+
clearInterval(this.intervalId);
|
|
85
|
+
// 启动所有监视器
|
|
86
|
+
for (let [, monitor] of this.monitorMap) {
|
|
87
|
+
await monitor.stop();
|
|
88
|
+
}
|
|
100
89
|
}
|
|
101
90
|
}
|
|
91
|
+
let factory = undefined;
|
|
102
92
|
export function reset() {
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
MonitorFactory.INSTANCE = undefined;
|
|
93
|
+
factory?.stop();
|
|
94
|
+
factory = undefined;
|
|
106
95
|
}
|
|
107
96
|
/**
|
|
108
97
|
* 初始化监控
|
|
109
98
|
*/
|
|
110
99
|
export function getInstance(options) {
|
|
111
|
-
if (!
|
|
100
|
+
if (!factory) {
|
|
112
101
|
if (!options) {
|
|
113
102
|
throw new Error('实例尚未创建,参数不能为空');
|
|
114
103
|
}
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
for (let { element, type, setup } of options.monitors) {
|
|
104
|
+
factory = new MonitorFactory(MObject.create(options));
|
|
105
|
+
Promise.all(options.monitors.map(({ element, provider = 'default:camera', setup }) => {
|
|
118
106
|
if (typeof element === 'string') {
|
|
119
107
|
element = document.getElementById(element);
|
|
120
108
|
}
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
types.push(type);
|
|
126
|
-
}
|
|
127
|
-
factory.init(type, element, setup);
|
|
128
|
-
}
|
|
129
|
-
MonitorFactory.INSTANCE = factory;
|
|
109
|
+
return factory.init(MonitorType.parse(provider), element, setup);
|
|
110
|
+
})).then((monitors) => {
|
|
111
|
+
console.log(monitors);
|
|
112
|
+
});
|
|
130
113
|
}
|
|
131
|
-
return
|
|
114
|
+
return factory;
|
|
132
115
|
}
|
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
import Monitor, { Device, MObject, MonitorOptions, Setup } from "../Monitor";
|
|
2
|
+
import TRTC, { LocalVideoConfig } from "trtc-sdk-v5";
|
|
3
|
+
export interface TxrtcSetup extends Setup {
|
|
4
|
+
userId: string;
|
|
5
|
+
roomId: string;
|
|
6
|
+
sdkAppId: number;
|
|
7
|
+
userSig: string;
|
|
8
|
+
userDefineRecordId?: string;
|
|
9
|
+
}
|
|
10
|
+
export default class TxrtcMonitor extends Monitor {
|
|
11
|
+
private active;
|
|
12
|
+
protected readonly trtc: TRTC;
|
|
13
|
+
protected readonly setup: TxrtcSetup;
|
|
14
|
+
constructor(options: MonitorOptions);
|
|
15
|
+
start(): Promise<any>;
|
|
16
|
+
initEvent(): Promise<Boolean>;
|
|
17
|
+
/**
|
|
18
|
+
* 发送自定义消息
|
|
19
|
+
* @param message
|
|
20
|
+
*/
|
|
21
|
+
send(message: string): void;
|
|
22
|
+
stop(): Promise<any>;
|
|
23
|
+
static getMonitor(device: Device, object: MObject, element: HTMLDivElement, setup?: Setup): TxrtcMonitor;
|
|
24
|
+
}
|
|
25
|
+
export declare class TxrtcScreenMonitor extends TxrtcMonitor {
|
|
26
|
+
constructor(object: MObject, element: HTMLDivElement, setup?: Setup);
|
|
27
|
+
start(): Promise<any>;
|
|
28
|
+
stop(): Promise<any>;
|
|
29
|
+
}
|
|
30
|
+
export declare class TxrtcCameraMonitor extends TxrtcMonitor {
|
|
31
|
+
constructor(object: MObject, element: HTMLDivElement, setup?: Setup);
|
|
32
|
+
start(): Promise<any>;
|
|
33
|
+
/**
|
|
34
|
+
* 切换摄像头
|
|
35
|
+
*/
|
|
36
|
+
switch(option: LocalVideoConfig['option']): Promise<void>;
|
|
37
|
+
stop(): Promise<any>;
|
|
38
|
+
}
|
|
@@ -0,0 +1,144 @@
|
|
|
1
|
+
import Monitor, { MonitorType, NotSupportError, ScreenTypeError } from "../Monitor";
|
|
2
|
+
import TRTC, { LOG_LEVEL } from "trtc-sdk-v5";
|
|
3
|
+
import { CDNStreaming, PublishMode } from 'trtc-sdk-v5/plugins/cdn-streaming';
|
|
4
|
+
export default class TxrtcMonitor extends Monitor {
|
|
5
|
+
constructor(options) {
|
|
6
|
+
super(options);
|
|
7
|
+
this.active = false;
|
|
8
|
+
this.setup = options.setup;
|
|
9
|
+
this.trtc = TRTC.create({ plugins: [CDNStreaming] });
|
|
10
|
+
if (this.setup.debug) {
|
|
11
|
+
TRTC.setLogLevel(LOG_LEVEL.DEBUG);
|
|
12
|
+
}
|
|
13
|
+
}
|
|
14
|
+
async start() {
|
|
15
|
+
let streamId = `${this.setup.roomId}_${this.setup.userId}_${this.type.device}`;
|
|
16
|
+
console.debug(`Start ${this.type.device} TxrtcMonitor with streamId ${streamId}`);
|
|
17
|
+
if (this.active)
|
|
18
|
+
return;
|
|
19
|
+
let publishMode = PublishMode.PublishMainStreamToCDN;
|
|
20
|
+
if (this.type.device === 'screen') {
|
|
21
|
+
publishMode = PublishMode.PublishSubStreamToCDN;
|
|
22
|
+
}
|
|
23
|
+
await this.trtc.startPlugin('CDNStreaming', {
|
|
24
|
+
target: { publishMode, streamId }
|
|
25
|
+
});
|
|
26
|
+
let params = {
|
|
27
|
+
userId: this.setup.userId,
|
|
28
|
+
strRoomId: this.setup.roomId,
|
|
29
|
+
userSig: this.setup.userSig,
|
|
30
|
+
sdkAppId: this.setup.sdkAppId
|
|
31
|
+
};
|
|
32
|
+
if (this.setup.userDefineRecordId) {
|
|
33
|
+
params.userDefineRecordId = this.setup.userDefineRecordId;
|
|
34
|
+
}
|
|
35
|
+
await this.trtc.enterRoom(params);
|
|
36
|
+
}
|
|
37
|
+
async initEvent() {
|
|
38
|
+
return new Promise((resolve) => {
|
|
39
|
+
this.trtc.on(TRTC.EVENT.ERROR, (error) => {
|
|
40
|
+
let err = error;
|
|
41
|
+
if (this.options.type.device === 'screen') {
|
|
42
|
+
err = new ScreenTypeError(error.message, 'ScreenTypeError');
|
|
43
|
+
}
|
|
44
|
+
this.dispatchEvent('error', null, err);
|
|
45
|
+
this.stop();
|
|
46
|
+
resolve(false);
|
|
47
|
+
}).on(TRTC.EVENT.SCREEN_SHARE_STOPPED, () => {
|
|
48
|
+
this.dispatchEvent('cancel');
|
|
49
|
+
this.stop();
|
|
50
|
+
}).on(TRTC.EVENT.TRACK, () => {
|
|
51
|
+
+this.dispatchEvent('start');
|
|
52
|
+
this.active = true;
|
|
53
|
+
this.element = this.options.element.querySelector('video');
|
|
54
|
+
resolve(true);
|
|
55
|
+
}).on(TRTC.EVENT.VIDEO_PLAY_STATE_CHANGED, ({ state }) => {
|
|
56
|
+
if (state === 'STOPPED') {
|
|
57
|
+
this.dispatchEvent('stop');
|
|
58
|
+
}
|
|
59
|
+
else if (state === 'PLAYING') {
|
|
60
|
+
this.dispatchEvent('playing');
|
|
61
|
+
}
|
|
62
|
+
}).on(TRTC.EVENT.CUSTOM_MESSAGE, (message) => {
|
|
63
|
+
let decoder = new TextDecoder('utf-8');
|
|
64
|
+
let payload = decoder.decode(message.data);
|
|
65
|
+
this.dispatchEvent('message', payload);
|
|
66
|
+
});
|
|
67
|
+
});
|
|
68
|
+
}
|
|
69
|
+
/**
|
|
70
|
+
* 发送自定义消息
|
|
71
|
+
* @param message
|
|
72
|
+
*/
|
|
73
|
+
send(message) {
|
|
74
|
+
this.trtc.sendCustomMessage({
|
|
75
|
+
cmdId: Math.ceil(Math.random() * 100),
|
|
76
|
+
data: new TextEncoder().encode(message).buffer
|
|
77
|
+
});
|
|
78
|
+
}
|
|
79
|
+
async stop() {
|
|
80
|
+
this.active = false;
|
|
81
|
+
await this.trtc.exitRoom();
|
|
82
|
+
await this.trtc.destroy();
|
|
83
|
+
super.stop();
|
|
84
|
+
}
|
|
85
|
+
static getMonitor(device, object, element, setup) {
|
|
86
|
+
if (device === 'screen') {
|
|
87
|
+
return new TxrtcScreenMonitor(object, element, setup);
|
|
88
|
+
}
|
|
89
|
+
else if (device === 'camera' || device === 'mobile') {
|
|
90
|
+
return new TxrtcCameraMonitor(object, element, setup);
|
|
91
|
+
}
|
|
92
|
+
throw new NotSupportError(`Device ${device} not support`, 'NotSupportError');
|
|
93
|
+
}
|
|
94
|
+
}
|
|
95
|
+
export class TxrtcScreenMonitor extends TxrtcMonitor {
|
|
96
|
+
constructor(object, element, setup) {
|
|
97
|
+
super({
|
|
98
|
+
type: new MonitorType('txrtc', 'screen'), object, element, setup: {
|
|
99
|
+
...setup,
|
|
100
|
+
userId: object.id,
|
|
101
|
+
roomId: object.room
|
|
102
|
+
}
|
|
103
|
+
});
|
|
104
|
+
}
|
|
105
|
+
async start() {
|
|
106
|
+
await super.start();
|
|
107
|
+
await this.trtc.startScreenShare({ publish: true, view: this.options.element });
|
|
108
|
+
await this.initEvent();
|
|
109
|
+
}
|
|
110
|
+
async stop() {
|
|
111
|
+
await this.trtc.stopScreenShare();
|
|
112
|
+
await super.stop();
|
|
113
|
+
}
|
|
114
|
+
}
|
|
115
|
+
export class TxrtcCameraMonitor extends TxrtcMonitor {
|
|
116
|
+
constructor(object, element, setup) {
|
|
117
|
+
super({
|
|
118
|
+
type: new MonitorType('txrtc', 'camera'), element, object, setup: {
|
|
119
|
+
...setup,
|
|
120
|
+
userId: object.id,
|
|
121
|
+
roomId: object.room
|
|
122
|
+
}
|
|
123
|
+
});
|
|
124
|
+
}
|
|
125
|
+
async start() {
|
|
126
|
+
await super.start();
|
|
127
|
+
await this.trtc.startLocalAudio({ publish: true });
|
|
128
|
+
await this.trtc.startLocalVideo({ publish: true, view: this.options.element });
|
|
129
|
+
await this.initEvent();
|
|
130
|
+
}
|
|
131
|
+
/**
|
|
132
|
+
* 切换摄像头
|
|
133
|
+
*/
|
|
134
|
+
async switch(option) {
|
|
135
|
+
if (option?.cameraId || option?.useFrontCamera) {
|
|
136
|
+
await this.trtc.updateLocalVideo({ option });
|
|
137
|
+
}
|
|
138
|
+
}
|
|
139
|
+
async stop() {
|
|
140
|
+
await this.trtc.stopLocalAudio();
|
|
141
|
+
await this.trtc.stopLocalVideo();
|
|
142
|
+
await super.stop();
|
|
143
|
+
}
|
|
144
|
+
}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "sample-xmonitor-js",
|
|
3
|
-
"version": "
|
|
3
|
+
"version": "1.0.1",
|
|
4
4
|
"description": "",
|
|
5
5
|
"main": "./lib/index",
|
|
6
6
|
"files": [
|
|
@@ -21,7 +21,6 @@
|
|
|
21
21
|
"author": "xs",
|
|
22
22
|
"license": "ISC",
|
|
23
23
|
"devDependencies": {
|
|
24
|
-
"@types/node": "^16.11.15",
|
|
25
24
|
"babel-cli": "^6.26.0",
|
|
26
25
|
"babel-preset-env": "^1.7.0",
|
|
27
26
|
"babel-preset-es2015": "^6.24.1",
|
|
@@ -31,6 +30,7 @@
|
|
|
31
30
|
"webpack-cli": "^4.9.1"
|
|
32
31
|
},
|
|
33
32
|
"dependencies": {
|
|
33
|
+
"trtc-sdk-v5": "^5.8.6",
|
|
34
34
|
"xdriver": "^1.1.1"
|
|
35
35
|
}
|
|
36
36
|
}
|
package/lib/DefaultMonitor.d.ts
DELETED
|
@@ -1,19 +0,0 @@
|
|
|
1
|
-
import Monitor, { DefaultSetup, MObject, MonitorOptions } from "./Monitor";
|
|
2
|
-
declare class DefaultMonitor extends Monitor {
|
|
3
|
-
private stream;
|
|
4
|
-
private active;
|
|
5
|
-
constructor(options: MonitorOptions);
|
|
6
|
-
protected getMedia(setup: DefaultSetup): any;
|
|
7
|
-
start(): Promise<any>;
|
|
8
|
-
stop(): Promise<any>;
|
|
9
|
-
}
|
|
10
|
-
export declare class DesktopMonitor extends DefaultMonitor {
|
|
11
|
-
constructor(object: MObject, element: HTMLDivElement, setup?: DefaultSetup);
|
|
12
|
-
start(): Promise<any>;
|
|
13
|
-
protected getMedia(setup: DefaultSetup): any;
|
|
14
|
-
}
|
|
15
|
-
export declare class CameraMonitor extends DefaultMonitor {
|
|
16
|
-
constructor(object: MObject, element: HTMLDivElement, setup?: DefaultSetup);
|
|
17
|
-
protected getMedia(setup: DefaultSetup): any;
|
|
18
|
-
}
|
|
19
|
-
export {};
|
package/lib/DefaultMonitor.js
DELETED
|
@@ -1,141 +0,0 @@
|
|
|
1
|
-
var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
|
|
2
|
-
function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
|
|
3
|
-
return new (P || (P = Promise))(function (resolve, reject) {
|
|
4
|
-
function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
|
|
5
|
-
function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
|
|
6
|
-
function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
|
|
7
|
-
step((generator = generator.apply(thisArg, _arguments || [])).next());
|
|
8
|
-
});
|
|
9
|
-
};
|
|
10
|
-
import Monitor, { NotSupportError, ScreenTypeError } from "./Monitor";
|
|
11
|
-
let win = window;
|
|
12
|
-
const navigator = win.navigator;
|
|
13
|
-
if (!navigator.mediaDevices) {
|
|
14
|
-
navigator["mediaDevices"] = {
|
|
15
|
-
getUserMedia: (constraints) => {
|
|
16
|
-
return navigator.getUserMedia ? new Promise((resolve, reject) => {
|
|
17
|
-
navigator.getUserMedia(constraints, resolve, reject);
|
|
18
|
-
}) : Promise.reject(new NotSupportError('This browser not support getUserMedia'));
|
|
19
|
-
}
|
|
20
|
-
};
|
|
21
|
-
}
|
|
22
|
-
const { mediaDevices } = navigator;
|
|
23
|
-
if (!mediaDevices.getDisplayMedia) {
|
|
24
|
-
mediaDevices.getDisplayMedia = (options) => {
|
|
25
|
-
return Promise.reject(new NotSupportError('This browser not support getDisplayMedia'));
|
|
26
|
-
};
|
|
27
|
-
}
|
|
28
|
-
class DefaultMonitor extends Monitor {
|
|
29
|
-
constructor(options) {
|
|
30
|
-
super(options);
|
|
31
|
-
this.active = false;
|
|
32
|
-
let video = document.createElement('video');
|
|
33
|
-
video.setAttribute('autoplay', 'true');
|
|
34
|
-
// 该属性的作用是在ios下video可以播放 否则会显示黑屏
|
|
35
|
-
video.setAttribute('playsinline', '');
|
|
36
|
-
video.style.width = "100%";
|
|
37
|
-
video.style.height = "100%";
|
|
38
|
-
options.element.appendChild(video);
|
|
39
|
-
this.element = video;
|
|
40
|
-
}
|
|
41
|
-
getMedia(setup) { }
|
|
42
|
-
start() {
|
|
43
|
-
return __awaiter(this, void 0, void 0, function* () {
|
|
44
|
-
if (this.active)
|
|
45
|
-
return;
|
|
46
|
-
let stream;
|
|
47
|
-
try {
|
|
48
|
-
stream = yield this.getMedia(Object.assign({ audio: false, video: true }, this.options.setup));
|
|
49
|
-
}
|
|
50
|
-
catch (e) {
|
|
51
|
-
/*
|
|
52
|
-
* AbortError[中止错误]
|
|
53
|
-
* 尽管用户和操作系统都授予了访问设备硬件的权利,而且未出现可能抛出NotReadableError异常的硬件问题,但仍然有一些问题的出现导致了设备无法被使用。
|
|
54
|
-
* NotAllowedError[拒绝错误]
|
|
55
|
-
* 用户拒绝了当前的浏览器实例的访问请求;或者用户拒绝了当前会话的访问;或者用户在全局范围内拒绝了所有媒体访问请求。
|
|
56
|
-
* NotFoundError[找不到错误]
|
|
57
|
-
* 找不到满足请求参数的媒体类型。
|
|
58
|
-
* NotReadableError[无法读取错误]
|
|
59
|
-
* 尽管用户已经授权使用相应的设备,操作系统上某个硬件、浏览器或者网页层面发生的错误导致设备无法被访问。
|
|
60
|
-
* OverconstrainedError[无法满足要求错误]
|
|
61
|
-
* 指定的要求无法被设备满足,此异常是一个类型为OverconstrainedError的对象,拥有一个constraint属性,这个属性包含了当前无法被满足的constraint对象,还拥有一个message属性,包含了阅读友好的字符串用来说明情况。
|
|
62
|
-
*SecurityError[安全错误]
|
|
63
|
-
* 在getUserMedia() 被调用的 Document 上面,使用设备媒体被禁止。这个机制是否开启或者关闭取决于单个用户的偏好设置。
|
|
64
|
-
* TypeError[类型错误]
|
|
65
|
-
*constraints 对象未设置[空],或者都被设置为false。
|
|
66
|
-
*
|
|
67
|
-
* */
|
|
68
|
-
if (!(e instanceof NotSupportError)) {
|
|
69
|
-
this.dispatchEvent('error', void 0, e);
|
|
70
|
-
return;
|
|
71
|
-
}
|
|
72
|
-
throw e;
|
|
73
|
-
}
|
|
74
|
-
let { element } = this;
|
|
75
|
-
element.srcObject = stream;
|
|
76
|
-
this.stream = stream;
|
|
77
|
-
let track = stream.getTracks()[0];
|
|
78
|
-
if (this.options.type === 'default:desktop' && !/^screen/i.test(track.label)) {
|
|
79
|
-
yield this.stop();
|
|
80
|
-
this.dispatchEvent('error', null, new ScreenTypeError('Screen share type error', 'ScreenTypeError'));
|
|
81
|
-
return;
|
|
82
|
-
}
|
|
83
|
-
track.onended = e => {
|
|
84
|
-
this.active = false;
|
|
85
|
-
this.dispatchEvent('cancel');
|
|
86
|
-
};
|
|
87
|
-
element.onloadedmetadata = () => {
|
|
88
|
-
element.play();
|
|
89
|
-
this.dispatchEvent('start');
|
|
90
|
-
};
|
|
91
|
-
element.onplaying = () => {
|
|
92
|
-
this.dispatchEvent('playing');
|
|
93
|
-
this.active = true;
|
|
94
|
-
};
|
|
95
|
-
element.onended = () => {
|
|
96
|
-
this.active = false;
|
|
97
|
-
this.dispatchEvent('stop');
|
|
98
|
-
};
|
|
99
|
-
return track;
|
|
100
|
-
});
|
|
101
|
-
}
|
|
102
|
-
stop() {
|
|
103
|
-
const _super = Object.create(null, {
|
|
104
|
-
stop: { get: () => super.stop }
|
|
105
|
-
});
|
|
106
|
-
return __awaiter(this, void 0, void 0, function* () {
|
|
107
|
-
this.active = false;
|
|
108
|
-
if (this.stream) {
|
|
109
|
-
this.element.pause();
|
|
110
|
-
this.stream.getTracks().forEach((track) => track.stop());
|
|
111
|
-
this.stream = void 0;
|
|
112
|
-
}
|
|
113
|
-
this.element.remove();
|
|
114
|
-
_super.stop.call(this);
|
|
115
|
-
});
|
|
116
|
-
}
|
|
117
|
-
}
|
|
118
|
-
export class DesktopMonitor extends DefaultMonitor {
|
|
119
|
-
constructor(object, element, setup) {
|
|
120
|
-
super({ type: 'default:desktop', object, element, setup });
|
|
121
|
-
}
|
|
122
|
-
start() {
|
|
123
|
-
const _super = Object.create(null, {
|
|
124
|
-
start: { get: () => super.start }
|
|
125
|
-
});
|
|
126
|
-
return __awaiter(this, void 0, void 0, function* () {
|
|
127
|
-
return _super.start.call(this);
|
|
128
|
-
});
|
|
129
|
-
}
|
|
130
|
-
getMedia(setup) {
|
|
131
|
-
return mediaDevices.getDisplayMedia(setup);
|
|
132
|
-
}
|
|
133
|
-
}
|
|
134
|
-
export class CameraMonitor extends DefaultMonitor {
|
|
135
|
-
constructor(object, element, setup) {
|
|
136
|
-
super({ type: 'default:camera', element, object, setup });
|
|
137
|
-
}
|
|
138
|
-
getMedia(setup) {
|
|
139
|
-
return mediaDevices.getUserMedia(setup);
|
|
140
|
-
}
|
|
141
|
-
}
|