camstreamerlib 4.0.0-beta.2 → 4.0.0-beta.4
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/cjs/CamOverlayAPI.js +176 -0
- package/cjs/CamOverlayDrawingAPI.js +235 -0
- package/cjs/CamOverlayPainter/Frame.js +301 -0
- package/{CamOverlayPainter → cjs/CamOverlayPainter}/Painter.d.ts +14 -3
- package/cjs/CamOverlayPainter/Painter.js +171 -0
- package/cjs/CamOverlayPainter/ResourceManager.js +46 -0
- package/cjs/CamScripterAPI.js +70 -0
- package/cjs/CamScripterAPICameraEventsGenerator.js +162 -0
- package/cjs/CamStreamerAPI.js +65 -0
- package/{CamSwitcherAPI.d.ts → cjs/CamSwitcherAPI.d.ts} +3 -3
- package/cjs/CamSwitcherAPI.js +350 -0
- package/{CamSwitcherEvents.d.ts → cjs/CamSwitcherEvents.d.ts} +1 -1
- package/cjs/CamSwitcherEvents.js +67 -0
- package/cjs/CreatePackage.js +106 -0
- package/{VapixAPI.d.ts → cjs/VapixAPI.d.ts} +9 -9
- package/cjs/VapixAPI.js +462 -0
- package/cjs/VapixEvents.js +88 -0
- package/cjs/errors/errors.js +79 -0
- package/cjs/events/AxisCameraStationEvents.js +48 -0
- package/cjs/events/GenetecAgent.js +123 -0
- package/cjs/index.d.ts +11 -0
- package/cjs/index.js +31 -0
- package/cjs/internal/Digest.js +42 -0
- package/cjs/internal/ProxyClient.js +44 -0
- package/{internal → cjs/internal}/common.d.ts +0 -1
- package/cjs/internal/common.js +27 -0
- package/cjs/internal/constants.js +4 -0
- package/cjs/internal/transformers.js +32 -0
- package/cjs/internal/utils.js +46 -0
- package/cjs/internal/versionCompare.js +53 -0
- package/cjs/node/DefaultClient.js +54 -0
- package/cjs/node/HttpRequestSender.js +89 -0
- package/cjs/node/HttpServer.js +96 -0
- package/cjs/node/WsClient.js +149 -0
- package/cjs/node/WsEventClient.js +22 -0
- package/cjs/node/index.d.ts +2 -0
- package/cjs/node/index.js +7 -0
- package/cjs/types/CamOverlayAPI.js +47 -0
- package/cjs/types/CamScripterAPI.js +20 -0
- package/cjs/types/CamStreamerAPI.js +28 -0
- package/cjs/types/CamSwitcherAPI.js +137 -0
- package/cjs/types/CamSwitcherEvents.js +62 -0
- package/{types → cjs/types}/VapixAPI.d.ts +40 -61
- package/cjs/types/VapixAPI.js +130 -0
- package/cjs/types/common.js +14 -0
- package/cjs/web/DefaultClient.js +20 -0
- package/cjs/web/WsClient.js +62 -0
- package/cjs/web/index.d.ts +2 -0
- package/cjs/web/index.js +7 -0
- package/esm/CamOverlayAPI.d.ts +31 -0
- package/esm/CamOverlayDrawingAPI.d.ts +86 -0
- package/{CamOverlayDrawingAPI.js → esm/CamOverlayDrawingAPI.js} +6 -3
- package/esm/CamOverlayPainter/Frame.d.ts +96 -0
- package/esm/CamOverlayPainter/Painter.d.ts +48 -0
- package/{CamOverlayPainter → esm/CamOverlayPainter}/Painter.js +4 -1
- package/esm/CamOverlayPainter/ResourceManager.d.ts +14 -0
- package/{CamOverlayPainter → esm/CamOverlayPainter}/ResourceManager.js +6 -10
- package/esm/CamScripterAPI.d.ts +19 -0
- package/esm/CamScripterAPICameraEventsGenerator.d.ts +74 -0
- package/{CamScripterAPICameraEventsGenerator.js → esm/CamScripterAPICameraEventsGenerator.js} +6 -3
- package/esm/CamStreamerAPI.d.ts +16 -0
- package/esm/CamSwitcherAPI.d.ts +48 -0
- package/{CamSwitcherAPI.js → esm/CamSwitcherAPI.js} +19 -23
- package/esm/CamSwitcherEvents.d.ts +18 -0
- package/{CamSwitcherEvents.js → esm/CamSwitcherEvents.js} +1 -1
- package/esm/CreatePackage.d.ts +1 -0
- package/esm/VapixAPI.d.ts +66 -0
- package/{VapixAPI.js → esm/VapixAPI.js} +20 -16
- package/esm/VapixEvents.d.ts +43 -0
- package/{VapixEvents.js → esm/VapixEvents.js} +3 -3
- package/esm/errors/errors.d.ts +34 -0
- package/esm/events/AxisCameraStationEvents.d.ts +9 -0
- package/esm/events/GenetecAgent.d.ts +174 -0
- package/esm/index.d.ts +11 -0
- package/esm/index.js +11 -0
- package/esm/internal/Digest.d.ts +4 -0
- package/{internal → esm/internal}/Digest.js +6 -6
- package/esm/internal/ProxyClient.d.ts +11 -0
- package/esm/internal/common.d.ts +39 -0
- package/{internal → esm/internal}/common.js +0 -3
- package/esm/internal/constants.d.ts +1 -0
- package/esm/internal/transformers.d.ts +5 -0
- package/esm/internal/utils.d.ts +11 -0
- package/esm/internal/versionCompare.d.ts +6 -0
- package/esm/node/DefaultClient.d.ts +15 -0
- package/{node → esm/node}/DefaultClient.js +1 -1
- package/esm/node/HttpRequestSender.d.ts +28 -0
- package/esm/node/HttpServer.d.ts +21 -0
- package/{node → esm/node}/HttpServer.js +1 -1
- package/esm/node/WsClient.d.ts +39 -0
- package/esm/node/WsEventClient.d.ts +13 -0
- package/esm/node/index.d.ts +2 -0
- package/esm/node/index.js +2 -0
- package/esm/types/CamOverlayAPI.d.ts +188 -0
- package/esm/types/CamScripterAPI.d.ts +67 -0
- package/esm/types/CamStreamerAPI.d.ts +139 -0
- package/esm/types/CamSwitcherAPI.d.ts +814 -0
- package/esm/types/CamSwitcherEvents.d.ts +491 -0
- package/esm/types/VapixAPI.d.ts +1683 -0
- package/{types → esm/types}/VapixAPI.js +10 -12
- package/esm/types/common.d.ts +37 -0
- package/esm/web/DefaultClient.d.ts +6 -0
- package/esm/web/WsClient.d.ts +13 -0
- package/esm/web/index.d.ts +2 -0
- package/esm/web/index.js +2 -0
- package/package.json +6 -5
- package/README.md +0 -97
- /package/{CamOverlayAPI.d.ts → cjs/CamOverlayAPI.d.ts} +0 -0
- /package/{CamOverlayDrawingAPI.d.ts → cjs/CamOverlayDrawingAPI.d.ts} +0 -0
- /package/{CamOverlayPainter → cjs/CamOverlayPainter}/Frame.d.ts +0 -0
- /package/{CamOverlayPainter → cjs/CamOverlayPainter}/ResourceManager.d.ts +0 -0
- /package/{CamScripterAPI.d.ts → cjs/CamScripterAPI.d.ts} +0 -0
- /package/{CamScripterAPICameraEventsGenerator.d.ts → cjs/CamScripterAPICameraEventsGenerator.d.ts} +0 -0
- /package/{CamStreamerAPI.d.ts → cjs/CamStreamerAPI.d.ts} +0 -0
- /package/{CreatePackage.d.ts → cjs/CreatePackage.d.ts} +0 -0
- /package/{VapixEvents.d.ts → cjs/VapixEvents.d.ts} +0 -0
- /package/{errors → cjs/errors}/errors.d.ts +0 -0
- /package/{events → cjs/events}/AxisCameraStationEvents.d.ts +0 -0
- /package/{events → cjs/events}/GenetecAgent.d.ts +0 -0
- /package/{internal → cjs/internal}/Digest.d.ts +0 -0
- /package/{internal → cjs/internal}/ProxyClient.d.ts +0 -0
- /package/{internal → cjs/internal}/constants.d.ts +0 -0
- /package/{internal → cjs/internal}/transformers.d.ts +0 -0
- /package/{internal → cjs/internal}/utils.d.ts +0 -0
- /package/{internal → cjs/internal}/versionCompare.d.ts +0 -0
- /package/{node → cjs/node}/DefaultClient.d.ts +0 -0
- /package/{node → cjs/node}/HttpRequestSender.d.ts +0 -0
- /package/{node → cjs/node}/HttpServer.d.ts +0 -0
- /package/{node → cjs/node}/WsClient.d.ts +0 -0
- /package/{node → cjs/node}/WsEventClient.d.ts +0 -0
- /package/{types → cjs/types}/CamOverlayAPI.d.ts +0 -0
- /package/{types → cjs/types}/CamScripterAPI.d.ts +0 -0
- /package/{types → cjs/types}/CamStreamerAPI.d.ts +0 -0
- /package/{types → cjs/types}/CamSwitcherAPI.d.ts +0 -0
- /package/{types/CamswitcherEvents.d.ts → cjs/types/CamSwitcherEvents.d.ts} +0 -0
- /package/{types → cjs/types}/common.d.ts +0 -0
- /package/{web → cjs/web}/DefaultClient.d.ts +0 -0
- /package/{web → cjs/web}/WsClient.d.ts +0 -0
- /package/{CamOverlayAPI.js → esm/CamOverlayAPI.js} +0 -0
- /package/{CamOverlayPainter → esm/CamOverlayPainter}/Frame.js +0 -0
- /package/{CamScripterAPI.js → esm/CamScripterAPI.js} +0 -0
- /package/{CamStreamerAPI.js → esm/CamStreamerAPI.js} +0 -0
- /package/{CreatePackage.js → esm/CreatePackage.js} +0 -0
- /package/{errors → esm/errors}/errors.js +0 -0
- /package/{events → esm/events}/AxisCameraStationEvents.js +0 -0
- /package/{events → esm/events}/GenetecAgent.js +0 -0
- /package/{internal → esm/internal}/ProxyClient.js +0 -0
- /package/{internal → esm/internal}/constants.js +0 -0
- /package/{internal → esm/internal}/transformers.js +0 -0
- /package/{internal → esm/internal}/utils.js +0 -0
- /package/{internal → esm/internal}/versionCompare.js +0 -0
- /package/{node → esm/node}/HttpRequestSender.js +0 -0
- /package/{node → esm/node}/WsClient.js +0 -0
- /package/{node → esm/node}/WsEventClient.js +0 -0
- /package/{types → esm/types}/CamOverlayAPI.js +0 -0
- /package/{types → esm/types}/CamScripterAPI.js +0 -0
- /package/{types → esm/types}/CamStreamerAPI.js +0 -0
- /package/{types → esm/types}/CamSwitcherAPI.js +0 -0
- /package/{types/CamswitcherEvents.js → esm/types/CamSwitcherEvents.js} +0 -0
- /package/{types → esm/types}/common.js +0 -0
- /package/{web → esm/web}/DefaultClient.js +0 -0
- /package/{web → esm/web}/WsClient.js +0 -0
|
@@ -0,0 +1,162 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.CamScripterAPICameraEventsGenerator = void 0;
|
|
4
|
+
const EventEmitter = require("events");
|
|
5
|
+
const WsClient_1 = require("./node/WsClient");
|
|
6
|
+
class CamScripterAPICameraEventsGenerator extends EventEmitter {
|
|
7
|
+
tls;
|
|
8
|
+
tlsInsecure;
|
|
9
|
+
ip;
|
|
10
|
+
port;
|
|
11
|
+
user;
|
|
12
|
+
pass;
|
|
13
|
+
callId;
|
|
14
|
+
sendMessages;
|
|
15
|
+
timeoutCheckTimer;
|
|
16
|
+
wsConnected;
|
|
17
|
+
ws;
|
|
18
|
+
constructor(options) {
|
|
19
|
+
super();
|
|
20
|
+
this.tls = options?.tls ?? false;
|
|
21
|
+
this.tlsInsecure = options?.tlsInsecure ?? false;
|
|
22
|
+
this.ip = options?.ip ?? '127.0.0.1';
|
|
23
|
+
this.port = options?.port ?? (this.tls ? 443 : 80);
|
|
24
|
+
this.user = options?.user ?? '';
|
|
25
|
+
this.pass = options?.pass ?? '';
|
|
26
|
+
this.callId = 0;
|
|
27
|
+
this.sendMessages = {};
|
|
28
|
+
this.wsConnected = false;
|
|
29
|
+
this.createWsClient();
|
|
30
|
+
EventEmitter.call(this);
|
|
31
|
+
}
|
|
32
|
+
connect() {
|
|
33
|
+
this.ws.open();
|
|
34
|
+
this.startMsgsTimeoutCheck();
|
|
35
|
+
}
|
|
36
|
+
disconnect() {
|
|
37
|
+
this.ws.close();
|
|
38
|
+
this.stopMsgsTimeoutCheck();
|
|
39
|
+
}
|
|
40
|
+
declareEvent(eventDeclaration) {
|
|
41
|
+
return this.sendMessage({
|
|
42
|
+
call_id: 0,
|
|
43
|
+
command: 'declare_event',
|
|
44
|
+
data: eventDeclaration,
|
|
45
|
+
});
|
|
46
|
+
}
|
|
47
|
+
undeclareEvent(eventUndeclaration) {
|
|
48
|
+
return this.sendMessage({
|
|
49
|
+
call_id: 0,
|
|
50
|
+
command: 'undeclare_event',
|
|
51
|
+
data: eventUndeclaration,
|
|
52
|
+
});
|
|
53
|
+
}
|
|
54
|
+
sendEvent(event) {
|
|
55
|
+
return this.sendMessage({
|
|
56
|
+
call_id: 0,
|
|
57
|
+
command: 'send_event',
|
|
58
|
+
data: event,
|
|
59
|
+
});
|
|
60
|
+
}
|
|
61
|
+
createWsClient() {
|
|
62
|
+
const options = {
|
|
63
|
+
user: this.user,
|
|
64
|
+
pass: this.pass,
|
|
65
|
+
tlsInsecure: this.tlsInsecure,
|
|
66
|
+
tls: this.tls,
|
|
67
|
+
ip: this.ip,
|
|
68
|
+
port: this.port,
|
|
69
|
+
address: `/local/camscripter/ws`,
|
|
70
|
+
protocol: 'camera-events',
|
|
71
|
+
};
|
|
72
|
+
this.ws = new WsClient_1.WsClient(options);
|
|
73
|
+
this.ws.on('open', () => {
|
|
74
|
+
this.wsConnected = true;
|
|
75
|
+
this.emit('open');
|
|
76
|
+
});
|
|
77
|
+
this.ws.on('message', (msgData) => this.incomingWsMessageHandler(msgData));
|
|
78
|
+
this.ws.on('error', (error) => {
|
|
79
|
+
this.reportErr(error);
|
|
80
|
+
});
|
|
81
|
+
this.ws.on('close', () => {
|
|
82
|
+
this.wsConnected = false;
|
|
83
|
+
this.reportClose();
|
|
84
|
+
});
|
|
85
|
+
}
|
|
86
|
+
incomingWsMessageHandler(msgData) {
|
|
87
|
+
const dataJSON = JSON.parse(msgData.toString());
|
|
88
|
+
let errorResponse;
|
|
89
|
+
if ('error' in dataJSON) {
|
|
90
|
+
errorResponse = dataJSON;
|
|
91
|
+
}
|
|
92
|
+
if (dataJSON.call_id !== undefined) {
|
|
93
|
+
if (errorResponse !== undefined) {
|
|
94
|
+
this.sendMessages[dataJSON.call_id]?.reject(new Error(errorResponse.error));
|
|
95
|
+
}
|
|
96
|
+
else {
|
|
97
|
+
this.sendMessages[dataJSON.call_id]?.resolve(dataJSON);
|
|
98
|
+
}
|
|
99
|
+
delete this.sendMessages[dataJSON.call_id];
|
|
100
|
+
}
|
|
101
|
+
if (errorResponse !== undefined) {
|
|
102
|
+
this.reconnectWithError(new Error(errorResponse.error));
|
|
103
|
+
}
|
|
104
|
+
}
|
|
105
|
+
sendMessage(msgJson) {
|
|
106
|
+
return new Promise((resolve, reject) => {
|
|
107
|
+
if (!this.wsConnected) {
|
|
108
|
+
throw new Error("Websocket hasn't been opened yet.");
|
|
109
|
+
}
|
|
110
|
+
try {
|
|
111
|
+
msgJson.call_id = ++this.callId;
|
|
112
|
+
this.ws.send(JSON.stringify(msgJson));
|
|
113
|
+
this.sendMessages[this.callId] = { resolve, reject, sentTimestamp: Date.now() };
|
|
114
|
+
}
|
|
115
|
+
catch (err) {
|
|
116
|
+
const errorMessage = err instanceof Error ? err.message : 'Unknown error';
|
|
117
|
+
const error = new Error(`Send message error: ${errorMessage}`);
|
|
118
|
+
reject(error);
|
|
119
|
+
this.reconnectWithError(error);
|
|
120
|
+
}
|
|
121
|
+
});
|
|
122
|
+
}
|
|
123
|
+
startMsgsTimeoutCheck() {
|
|
124
|
+
clearInterval(this.timeoutCheckTimer);
|
|
125
|
+
this.timeoutCheckTimer = setInterval(() => {
|
|
126
|
+
let reconnect = false;
|
|
127
|
+
const now = Date.now();
|
|
128
|
+
for (const callId in this.sendMessages) {
|
|
129
|
+
const msg = this.sendMessages[callId];
|
|
130
|
+
if (!msg) {
|
|
131
|
+
continue;
|
|
132
|
+
}
|
|
133
|
+
if (now - msg.sentTimestamp > 10000) {
|
|
134
|
+
reconnect = true;
|
|
135
|
+
msg.reject(new Error('Message timeout'));
|
|
136
|
+
delete this.sendMessages[callId];
|
|
137
|
+
}
|
|
138
|
+
}
|
|
139
|
+
if (reconnect) {
|
|
140
|
+
this.reconnectWithError(new Error('Message timeout'));
|
|
141
|
+
}
|
|
142
|
+
}, 5000);
|
|
143
|
+
}
|
|
144
|
+
stopMsgsTimeoutCheck() {
|
|
145
|
+
clearInterval(this.timeoutCheckTimer);
|
|
146
|
+
}
|
|
147
|
+
reconnectWithError(err) {
|
|
148
|
+
this.reportErr(err);
|
|
149
|
+
this.ws.reconnect();
|
|
150
|
+
}
|
|
151
|
+
reportErr(err) {
|
|
152
|
+
this.emit('error', err);
|
|
153
|
+
}
|
|
154
|
+
reportClose() {
|
|
155
|
+
for (const callId in this.sendMessages) {
|
|
156
|
+
this.sendMessages[callId]?.reject(new Error('Connection lost'));
|
|
157
|
+
}
|
|
158
|
+
this.sendMessages = {};
|
|
159
|
+
this.emit('close');
|
|
160
|
+
}
|
|
161
|
+
}
|
|
162
|
+
exports.CamScripterAPICameraEventsGenerator = CamScripterAPICameraEventsGenerator;
|
|
@@ -0,0 +1,65 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.CamStreamerAPI = void 0;
|
|
4
|
+
const common_1 = require("./internal/common");
|
|
5
|
+
const DefaultClient_1 = require("./node/DefaultClient");
|
|
6
|
+
const CamStreamerAPI_1 = require("./types/CamStreamerAPI");
|
|
7
|
+
class CamStreamerAPI {
|
|
8
|
+
client;
|
|
9
|
+
constructor(options = {}) {
|
|
10
|
+
if ((0, common_1.isClient)(options)) {
|
|
11
|
+
this.client = options;
|
|
12
|
+
}
|
|
13
|
+
else {
|
|
14
|
+
this.client = new DefaultClient_1.DefaultClient(options);
|
|
15
|
+
}
|
|
16
|
+
}
|
|
17
|
+
async getStreamList() {
|
|
18
|
+
const streamListRes = await this.get('/local/camstreamer/stream/list.cgi');
|
|
19
|
+
return CamStreamerAPI_1.streamListSchema.parse(streamListRes.data);
|
|
20
|
+
}
|
|
21
|
+
async getStream(streamID) {
|
|
22
|
+
const stream = await this.get(`/local/camstreamer/stream/get.cgi?stream_id=${streamID}`);
|
|
23
|
+
return CamStreamerAPI_1.streamAttributesSchema.parse(stream.data);
|
|
24
|
+
}
|
|
25
|
+
async getStreamParameter(streamID, paramName) {
|
|
26
|
+
const stream = await this.get(`/local/camstreamer/stream/get.cgi?stream_id=${streamID}`);
|
|
27
|
+
return stream.data[paramName];
|
|
28
|
+
}
|
|
29
|
+
async setStream(streamID, params) {
|
|
30
|
+
const { streamDelay, startTime, stopTime, ...rest } = params;
|
|
31
|
+
await this.get('/local/camstreamer/stream/set.cgi', {
|
|
32
|
+
stream_id: streamID,
|
|
33
|
+
streamDelay: streamDelay ?? '',
|
|
34
|
+
startTime: startTime ?? 'null',
|
|
35
|
+
stopTime: stopTime ?? 'null',
|
|
36
|
+
...rest,
|
|
37
|
+
});
|
|
38
|
+
}
|
|
39
|
+
async setStreamParameter(streamID, paramName, value) {
|
|
40
|
+
await this.get(`/local/camstreamer/stream/set.cgi?stream_id=${streamID}&${paramName}=${value}`);
|
|
41
|
+
}
|
|
42
|
+
async isStreaming(streamID) {
|
|
43
|
+
const response = await this.get(`/local/camstreamer/get_streamstat.cgi?stream_id=${streamID}`);
|
|
44
|
+
return response.data.is_streaming === 1;
|
|
45
|
+
}
|
|
46
|
+
async deleteStream(streamID) {
|
|
47
|
+
await this.get('/local/camstreamer/stream/remove.cgi', { stream_id: streamID });
|
|
48
|
+
}
|
|
49
|
+
wsAutoratization() {
|
|
50
|
+
return this.get('/local/camstreamer/ws_authorization.cgi');
|
|
51
|
+
}
|
|
52
|
+
async getUtcTime() {
|
|
53
|
+
return await this.get('/local/camstreamer/get_utc_time.cgi');
|
|
54
|
+
}
|
|
55
|
+
async get(path, parameters) {
|
|
56
|
+
const res = await this.client.get(path, parameters);
|
|
57
|
+
if (res.ok) {
|
|
58
|
+
return await res.json();
|
|
59
|
+
}
|
|
60
|
+
else {
|
|
61
|
+
throw new Error(await (0, common_1.responseStringify)(res));
|
|
62
|
+
}
|
|
63
|
+
}
|
|
64
|
+
}
|
|
65
|
+
exports.CamStreamerAPI = CamStreamerAPI;
|
|
@@ -5,9 +5,9 @@ export declare class CamSwitcherAPI<Client extends IClient = IClient> {
|
|
|
5
5
|
client: Client;
|
|
6
6
|
private vapixAgent;
|
|
7
7
|
constructor(client: Client);
|
|
8
|
-
static
|
|
9
|
-
static
|
|
10
|
-
static
|
|
8
|
+
static getProxyUrlPath: () => string;
|
|
9
|
+
static getWsEventsUrlPath: () => string;
|
|
10
|
+
static getClipPreviewUrlPath: (id: string, storage: TStorageType) => string;
|
|
11
11
|
generateSilence(sampleRate: number, channels: TAudioChannel): Promise<void>;
|
|
12
12
|
checkCameraTime(): Promise<boolean>;
|
|
13
13
|
getIpListFromNetworkCheck(): Promise<TNetworkCamera[]>;
|
|
@@ -0,0 +1,350 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.CamSwitcherAPI = void 0;
|
|
4
|
+
const zod_1 = require("zod");
|
|
5
|
+
const errors_1 = require("./errors/errors");
|
|
6
|
+
const common_1 = require("./internal/common");
|
|
7
|
+
const CamSwitcherAPI_1 = require("./types/CamSwitcherAPI");
|
|
8
|
+
const common_2 = require("./types/common");
|
|
9
|
+
const VapixAPI_1 = require("./VapixAPI");
|
|
10
|
+
const versionCompare_1 = require("./internal/versionCompare");
|
|
11
|
+
const utils_1 = require("./internal/utils");
|
|
12
|
+
const constants_1 = require("./internal/constants");
|
|
13
|
+
const baseUrl = '/local/camswitcher/api';
|
|
14
|
+
class CamSwitcherAPI {
|
|
15
|
+
client;
|
|
16
|
+
vapixAgent;
|
|
17
|
+
constructor(client) {
|
|
18
|
+
this.client = client;
|
|
19
|
+
this.vapixAgent = new VapixAPI_1.VapixAPI(client, () => '');
|
|
20
|
+
}
|
|
21
|
+
static getProxyUrlPath = () => `${baseUrl}/proxy.cgi`;
|
|
22
|
+
static getWsEventsUrlPath = () => `/local/camswitcher/events`;
|
|
23
|
+
static getClipPreviewUrlPath = (id, storage) => `${baseUrl}/clip_preview.cgi?clip_name=${id}&storage=${storage}`;
|
|
24
|
+
async generateSilence(sampleRate, channels) {
|
|
25
|
+
await this.client.get(`${baseUrl}/generate_silence.cgi`, {
|
|
26
|
+
sample_rate: sampleRate.toString(),
|
|
27
|
+
channels,
|
|
28
|
+
});
|
|
29
|
+
}
|
|
30
|
+
async checkCameraTime() {
|
|
31
|
+
const data = await this.get(`${baseUrl}/camera_time.cgi`);
|
|
32
|
+
return zod_1.z.boolean().parse(data);
|
|
33
|
+
}
|
|
34
|
+
async getIpListFromNetworkCheck() {
|
|
35
|
+
const data = await this.get(`${baseUrl}/network_camera_list.cgi`);
|
|
36
|
+
return common_2.networkCameraListSchema.parse(data);
|
|
37
|
+
}
|
|
38
|
+
async getMaxFps(source) {
|
|
39
|
+
const data = await this.get(`${baseUrl}/get_max_framerate.cgi`, {
|
|
40
|
+
video_source: source.toString(),
|
|
41
|
+
});
|
|
42
|
+
return zod_1.z.number().parse(data);
|
|
43
|
+
}
|
|
44
|
+
async getStorageInfo() {
|
|
45
|
+
const data = await this.get(`${baseUrl}/get_storage.cgi`);
|
|
46
|
+
return CamSwitcherAPI_1.storageInfoListSchema.parse(data);
|
|
47
|
+
}
|
|
48
|
+
async wsAuthorization() {
|
|
49
|
+
const data = await this.get(`${baseUrl}/ws_authorization.cgi`);
|
|
50
|
+
return zod_1.z.string().parse(data);
|
|
51
|
+
}
|
|
52
|
+
async getOutputInfo() {
|
|
53
|
+
const data = await this.get(`${baseUrl}/output_info.cgi`);
|
|
54
|
+
return CamSwitcherAPI_1.outputInfoSchema.parse(data);
|
|
55
|
+
}
|
|
56
|
+
async getAudioPushInfo() {
|
|
57
|
+
const data = await this.get(`${baseUrl}/audio_push_info.cgi`);
|
|
58
|
+
return CamSwitcherAPI_1.audioPushInfoSchema.parse(data);
|
|
59
|
+
}
|
|
60
|
+
async getStreamSaveList() {
|
|
61
|
+
const data = await this.get(`${baseUrl}/streams.cgi`, { action: 'get' });
|
|
62
|
+
return CamSwitcherAPI_1.streamSaveLoadSchema.parse(data);
|
|
63
|
+
}
|
|
64
|
+
async getClipSaveList() {
|
|
65
|
+
const data = await this.get(`${baseUrl}/clips.cgi`, { action: 'get' });
|
|
66
|
+
return CamSwitcherAPI_1.clipSaveLoadSchema.parse(data);
|
|
67
|
+
}
|
|
68
|
+
async getPlaylistSaveList() {
|
|
69
|
+
const data = await this.get(`${baseUrl}/playlists.cgi`, { action: 'get' });
|
|
70
|
+
return CamSwitcherAPI_1.playlistSaveLoadSchema.parse(data);
|
|
71
|
+
}
|
|
72
|
+
async getTrackerSaveList() {
|
|
73
|
+
const data = await this.get(`${baseUrl}/trackers.cgi`, { action: 'get' });
|
|
74
|
+
return CamSwitcherAPI_1.trackerSaveLoadSchema.parse(data);
|
|
75
|
+
}
|
|
76
|
+
async setStreamSaveList(data) {
|
|
77
|
+
return await this.set(`${baseUrl}/streams.cgi`, data, { action: 'set' });
|
|
78
|
+
}
|
|
79
|
+
async setClipSaveList(data) {
|
|
80
|
+
return await this.set(`${baseUrl}/clips.cgi`, data, { action: 'set' });
|
|
81
|
+
}
|
|
82
|
+
async setPlaylistSaveList(data) {
|
|
83
|
+
return await this.set(`${baseUrl}/playlists.cgi`, data, { action: 'set' });
|
|
84
|
+
}
|
|
85
|
+
async setTrackerSaveList(data) {
|
|
86
|
+
return await this.set(`${baseUrl}/trackers.cgi`, data, { action: 'set' });
|
|
87
|
+
}
|
|
88
|
+
async playlistSwitch(playlistName) {
|
|
89
|
+
await this.get(`${baseUrl}/playlist_switch.cgi?playlist_name=${playlistName}`);
|
|
90
|
+
}
|
|
91
|
+
async playlistQueuePush(playlistName) {
|
|
92
|
+
await this.get(`${baseUrl}/playlist_queue_push.cgi?playlist_name=${playlistName}`);
|
|
93
|
+
}
|
|
94
|
+
async playlistQueueClear() {
|
|
95
|
+
await this.get(`${baseUrl}/playlist_queue_clear.cgi`);
|
|
96
|
+
}
|
|
97
|
+
async playlistQueueList() {
|
|
98
|
+
const data = await this.get(`${baseUrl}/playlist_queue_list.cgi`);
|
|
99
|
+
return CamSwitcherAPI_1.playlistQueueSchema.parse(data).playlistQueueList;
|
|
100
|
+
}
|
|
101
|
+
async playlistQueuePlayNext() {
|
|
102
|
+
await this.get(`${baseUrl}/playlist_queue_play_next.cgi`);
|
|
103
|
+
}
|
|
104
|
+
async addNewClip(file, clipType, storage, id, fileName) {
|
|
105
|
+
const formData = new FormData();
|
|
106
|
+
formData.append('clip_name', id);
|
|
107
|
+
formData.append('clip_type', clipType);
|
|
108
|
+
formData.append('file', file, fileName);
|
|
109
|
+
const path = `${baseUrl}/clip_upload.cgi?storage=${storage}`;
|
|
110
|
+
const res = await this.client.post(path, formData);
|
|
111
|
+
const output = (await res.json());
|
|
112
|
+
if (output.status !== 200) {
|
|
113
|
+
throw new errors_1.AddNewClipError(output.message);
|
|
114
|
+
}
|
|
115
|
+
}
|
|
116
|
+
removeClip(id, storage) {
|
|
117
|
+
return this.get(`${baseUrl}/clip_remove.cgi`, { clip_name: id, storage });
|
|
118
|
+
}
|
|
119
|
+
async getClipList() {
|
|
120
|
+
const data = await this.get(`${baseUrl}/clip_list.cgi`);
|
|
121
|
+
return CamSwitcherAPI_1.clipListSchema.parse(data).clip_list;
|
|
122
|
+
}
|
|
123
|
+
setCamSwitchOptions(data, cameraFWVersion) {
|
|
124
|
+
const bitrateVapixParams = parseBitrateOptionsToBitrateVapixParams(cameraFWVersion, data.bitrateMode, data);
|
|
125
|
+
const saveData = {
|
|
126
|
+
video: {
|
|
127
|
+
resolution: data.resolution,
|
|
128
|
+
h264Profile: data.h264Profile,
|
|
129
|
+
fps: data.fps,
|
|
130
|
+
compression: data.compression,
|
|
131
|
+
govLength: data.govLength,
|
|
132
|
+
videoClipQuality: data.maximumBitRate,
|
|
133
|
+
bitrateVapixParams: bitrateVapixParams,
|
|
134
|
+
},
|
|
135
|
+
audio: {
|
|
136
|
+
sampleRate: data.audioSampleRate,
|
|
137
|
+
channelCount: data.audioChannelCount,
|
|
138
|
+
},
|
|
139
|
+
keyboard: data.keyboard,
|
|
140
|
+
};
|
|
141
|
+
return this.setParamFromCameraJSON(CSW_PARAM_NAMES.SETTINGS, saveData);
|
|
142
|
+
}
|
|
143
|
+
setGlobalAudioSettings(settings) {
|
|
144
|
+
let acceptedType = 'NONE';
|
|
145
|
+
if (settings.type === 'source' && settings.source) {
|
|
146
|
+
if ((0, utils_1.isClip)(settings.source)) {
|
|
147
|
+
acceptedType = 'CLIP';
|
|
148
|
+
}
|
|
149
|
+
else {
|
|
150
|
+
acceptedType = 'STREAM';
|
|
151
|
+
}
|
|
152
|
+
}
|
|
153
|
+
const data = {
|
|
154
|
+
type: acceptedType,
|
|
155
|
+
stream_name: settings.source,
|
|
156
|
+
clip_name: settings.source,
|
|
157
|
+
storage: settings.storage,
|
|
158
|
+
};
|
|
159
|
+
return this.setParamFromCameraJSON(CSW_PARAM_NAMES.MASTER_AUDIO, data);
|
|
160
|
+
}
|
|
161
|
+
setSecondaryAudioSettings(settings) {
|
|
162
|
+
const data = {
|
|
163
|
+
type: settings.type,
|
|
164
|
+
stream_name: settings.streamName ?? '',
|
|
165
|
+
clip_name: settings.clipName ?? '',
|
|
166
|
+
storage: settings.storage,
|
|
167
|
+
secondary_audio_level: settings.secondaryAudioLevel,
|
|
168
|
+
master_audio_level: settings.masterAudioLevel,
|
|
169
|
+
};
|
|
170
|
+
return this.setParamFromCameraJSON(CSW_PARAM_NAMES.SECONDARY_AUDIO, data);
|
|
171
|
+
}
|
|
172
|
+
setDefaultPlaylist(id) {
|
|
173
|
+
const value = JSON.stringify({ default_playlist_id: id });
|
|
174
|
+
return this.vapixAgent.setParameter({
|
|
175
|
+
[CSW_PARAM_NAMES.DEFAULT_PLAYLIST]: value,
|
|
176
|
+
}, null);
|
|
177
|
+
}
|
|
178
|
+
setPermanentRtspUrlToken(token) {
|
|
179
|
+
return this.vapixAgent.setParameter({ [CSW_PARAM_NAMES.RTSP_TOKEN]: token }, null);
|
|
180
|
+
}
|
|
181
|
+
async getCamSwitchOptions() {
|
|
182
|
+
const saveData = await this.getParamFromCameraAndJSONParse(CSW_PARAM_NAMES.SETTINGS);
|
|
183
|
+
if ((0, common_1.isNullish)(saveData.video)) {
|
|
184
|
+
return saveData;
|
|
185
|
+
}
|
|
186
|
+
if (!(0, common_1.isNullish)(saveData.video?.bitrateVapixParams)) {
|
|
187
|
+
const bitrateOptions = parseVapixParamsToBitrateOptions(saveData.video.bitrateVapixParams);
|
|
188
|
+
saveData.video.bitrateMode = bitrateOptions.bitrateMode;
|
|
189
|
+
saveData.video.maximumBitRate = bitrateOptions.maximumBitRate;
|
|
190
|
+
saveData.video.retentionTime = bitrateOptions.retentionTime;
|
|
191
|
+
saveData.video.bitRateLimit = bitrateOptions.bitRateLimit;
|
|
192
|
+
}
|
|
193
|
+
if (!(0, common_1.isNullish)(saveData.video?.bitrateLimit)) {
|
|
194
|
+
saveData.video.maximumBitRate = saveData.video.bitrateLimit;
|
|
195
|
+
saveData.video.bitrateMode = 'MBR';
|
|
196
|
+
}
|
|
197
|
+
if (!(0, common_1.isNullish)(saveData.video?.videoClipQuality)) {
|
|
198
|
+
saveData.video.maximumBitRate = saveData.video.videoClipQuality;
|
|
199
|
+
}
|
|
200
|
+
return {
|
|
201
|
+
...saveData.video,
|
|
202
|
+
audioSampleRate: saveData.audio.sampleRate,
|
|
203
|
+
audioChannelCount: saveData.audio.channelCount,
|
|
204
|
+
keyboard: saveData.keyboard,
|
|
205
|
+
};
|
|
206
|
+
}
|
|
207
|
+
async getGlobalAudioSettings() {
|
|
208
|
+
const settings = {
|
|
209
|
+
type: 'fromSource',
|
|
210
|
+
source: 'fromSource',
|
|
211
|
+
};
|
|
212
|
+
const res = await this.getParamFromCameraAndJSONParse(CSW_PARAM_NAMES.MASTER_AUDIO);
|
|
213
|
+
if (res.type === 'STREAM') {
|
|
214
|
+
settings.type = 'source';
|
|
215
|
+
settings.source = res.stream_name;
|
|
216
|
+
}
|
|
217
|
+
else if (res.type === 'CLIP') {
|
|
218
|
+
settings.type = 'source';
|
|
219
|
+
settings.source = res.clip_name;
|
|
220
|
+
settings.storage = res.storage;
|
|
221
|
+
}
|
|
222
|
+
return settings;
|
|
223
|
+
}
|
|
224
|
+
async getSecondaryAudioSettings() {
|
|
225
|
+
const res = await this.getParamFromCameraAndJSONParse(CSW_PARAM_NAMES.SECONDARY_AUDIO);
|
|
226
|
+
const settings = {
|
|
227
|
+
type: res.type ?? 'NONE',
|
|
228
|
+
streamName: res.stream_name,
|
|
229
|
+
clipName: res.clip_name,
|
|
230
|
+
storage: res.storage,
|
|
231
|
+
secondaryAudioLevel: res.secondary_audio_level ?? 1,
|
|
232
|
+
masterAudioLevel: res.master_audio_level ?? 1,
|
|
233
|
+
};
|
|
234
|
+
return settings;
|
|
235
|
+
}
|
|
236
|
+
async getPermanentRtspUrlToken() {
|
|
237
|
+
const paramName = CSW_PARAM_NAMES.RTSP_TOKEN;
|
|
238
|
+
const res = await this.vapixAgent.getParameter([paramName], null);
|
|
239
|
+
return res[paramName] ?? '';
|
|
240
|
+
}
|
|
241
|
+
async get(path, parameters = {}) {
|
|
242
|
+
const res = await this.client.get(path, parameters);
|
|
243
|
+
if (res.ok) {
|
|
244
|
+
const d = (await res.json());
|
|
245
|
+
return d.data;
|
|
246
|
+
}
|
|
247
|
+
else {
|
|
248
|
+
throw new Error(await (0, common_1.responseStringify)(res));
|
|
249
|
+
}
|
|
250
|
+
}
|
|
251
|
+
async set(path, data, parameters = {}) {
|
|
252
|
+
const res = await this.client.post(path, JSON.stringify(data), parameters);
|
|
253
|
+
if (res.ok) {
|
|
254
|
+
const parsed = await res.json();
|
|
255
|
+
return parsed.message === 'OK';
|
|
256
|
+
}
|
|
257
|
+
else {
|
|
258
|
+
throw new Error(await (0, common_1.responseStringify)(res));
|
|
259
|
+
}
|
|
260
|
+
}
|
|
261
|
+
setParamFromCameraJSON(paramName, data) {
|
|
262
|
+
const params = {};
|
|
263
|
+
params[paramName] = JSON.stringify(data);
|
|
264
|
+
return this.vapixAgent.setParameter(params, null);
|
|
265
|
+
}
|
|
266
|
+
async getParamFromCameraAndJSONParse(paramName) {
|
|
267
|
+
const data = await this.vapixAgent.getParameter([paramName], null);
|
|
268
|
+
if (data[paramName] !== undefined) {
|
|
269
|
+
try {
|
|
270
|
+
if (data[paramName] === '') {
|
|
271
|
+
return {};
|
|
272
|
+
}
|
|
273
|
+
else {
|
|
274
|
+
return JSON.parse(data[paramName] + '');
|
|
275
|
+
}
|
|
276
|
+
}
|
|
277
|
+
catch {
|
|
278
|
+
throw new Error('Error: in JSON parsing of ' + paramName + '. Cannot parse: ' + data[paramName]);
|
|
279
|
+
}
|
|
280
|
+
}
|
|
281
|
+
throw new Error("Error: no parametr '" + paramName + "' was found");
|
|
282
|
+
}
|
|
283
|
+
}
|
|
284
|
+
exports.CamSwitcherAPI = CamSwitcherAPI;
|
|
285
|
+
const CSW_PARAM_NAMES = {
|
|
286
|
+
SETTINGS: 'Camswitcher.Settings',
|
|
287
|
+
MASTER_AUDIO: 'Camswitcher.MasterAudio',
|
|
288
|
+
SECONDARY_AUDIO: 'Camswitcher.SecondaryAudio',
|
|
289
|
+
RTSP_TOKEN: 'Camswitcher.RTSPAccessToken',
|
|
290
|
+
DEFAULT_PLAYLIST: 'Camswitcher.DefaultPlaylist',
|
|
291
|
+
};
|
|
292
|
+
const parseBitrateOptionsToBitrateVapixParams = (firmWareVersion, bitrateMode, cameraOptions) => {
|
|
293
|
+
if (!(0, versionCompare_1.isFirmwareVersionAtLeast)(firmWareVersion, constants_1.FIRMWARE_WITH_BITRATE_MODES_SUPPORT)) {
|
|
294
|
+
return `videomaxbitrate=${cameraOptions.maximumBitRate}`;
|
|
295
|
+
}
|
|
296
|
+
if (bitrateMode === null) {
|
|
297
|
+
return '';
|
|
298
|
+
}
|
|
299
|
+
const data = {
|
|
300
|
+
VBR: 'videobitratemode=vbr',
|
|
301
|
+
MBR: `videobitratemode=mbr&videomaxbitrate=${cameraOptions.maximumBitRate}`,
|
|
302
|
+
ABR: `videobitratemode=abr&videoabrtargetbitrate=${cameraOptions.maximumBitRate}&videoabrretentiontime=${cameraOptions.retentionTime}&videoabrmaxbitrate=${cameraOptions.bitRateLimit}`,
|
|
303
|
+
};
|
|
304
|
+
return data[bitrateMode];
|
|
305
|
+
};
|
|
306
|
+
const parseVapixParamsToBitrateOptions = (bitrateVapixParams) => {
|
|
307
|
+
const params = {};
|
|
308
|
+
const searchParams = new URLSearchParams(bitrateVapixParams);
|
|
309
|
+
searchParams.forEach((value, key) => {
|
|
310
|
+
params[key] = value;
|
|
311
|
+
});
|
|
312
|
+
const bitrateMode = params['videobitratemode'] !== undefined ? params['videobitratemode'].toUpperCase() : undefined;
|
|
313
|
+
const hasLowerFw = bitrateMode === undefined && params['videomaxbitrate'] !== undefined;
|
|
314
|
+
if (hasLowerFw) {
|
|
315
|
+
const maximumBitRate = parseInt(params['videomaxbitrate'] ?? '0', 10);
|
|
316
|
+
return {
|
|
317
|
+
bitrateMode: 'MBR',
|
|
318
|
+
maximumBitRate: maximumBitRate,
|
|
319
|
+
retentionTime: 1,
|
|
320
|
+
bitRateLimit: Math.floor(maximumBitRate * 1.1),
|
|
321
|
+
};
|
|
322
|
+
}
|
|
323
|
+
if (bitrateMode === 'ABR') {
|
|
324
|
+
const maximumBitRate = parseInt(params['videoabrtargetbitrate'] ?? '0', 10);
|
|
325
|
+
const retentionTime = parseInt(params['videoabrretentiontime'] ?? '0', 10);
|
|
326
|
+
const bitRateLimit = parseInt(params['videoabrmaxbitrate'] ?? '0', 10);
|
|
327
|
+
return {
|
|
328
|
+
bitrateMode,
|
|
329
|
+
maximumBitRate,
|
|
330
|
+
retentionTime,
|
|
331
|
+
bitRateLimit,
|
|
332
|
+
};
|
|
333
|
+
}
|
|
334
|
+
else if (bitrateMode === 'MBR') {
|
|
335
|
+
const maximumBitRate = params['videomaxbitrate'] !== undefined ? parseInt(params['videomaxbitrate'], 10) : null;
|
|
336
|
+
const oldMaximumBitrateParamValue = parseInt(params['videombrmaxbitrate'] ?? '0', 10);
|
|
337
|
+
return {
|
|
338
|
+
bitrateMode: bitrateMode,
|
|
339
|
+
maximumBitRate: maximumBitRate ?? oldMaximumBitrateParamValue,
|
|
340
|
+
retentionTime: 1,
|
|
341
|
+
bitRateLimit: Math.floor(maximumBitRate ?? oldMaximumBitrateParamValue * 1.1),
|
|
342
|
+
};
|
|
343
|
+
}
|
|
344
|
+
return {
|
|
345
|
+
bitrateMode: bitrateMode,
|
|
346
|
+
retentionTime: 1,
|
|
347
|
+
maximumBitRate: 0,
|
|
348
|
+
bitRateLimit: 0,
|
|
349
|
+
};
|
|
350
|
+
};
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { IWebsocket } from './internal/common';
|
|
2
|
-
import { TCamSwitcherEventOfType, TCamSwitcherEventType } from './types/
|
|
2
|
+
import { TCamSwitcherEventOfType, TCamSwitcherEventType } from './types/CamSwitcherEvents';
|
|
3
3
|
type TListenerFunction<T extends TCamSwitcherEventType> = (data: TCamSwitcherEventOfType<T>, isInit: boolean) => void;
|
|
4
4
|
export declare class CamSwitcherEvents<Event extends {
|
|
5
5
|
data: string;
|
|
@@ -0,0 +1,67 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.CamSwitcherEvents = void 0;
|
|
4
|
+
const CamSwitcherEvents_1 = require("./types/CamSwitcherEvents");
|
|
5
|
+
class CamSwitcherEvents {
|
|
6
|
+
isDestroyed = false;
|
|
7
|
+
ws = null;
|
|
8
|
+
listeners = {};
|
|
9
|
+
setWebsocket(ws) {
|
|
10
|
+
if (this.ws) {
|
|
11
|
+
this.ws.destroy();
|
|
12
|
+
}
|
|
13
|
+
this.ws = ws;
|
|
14
|
+
this.ws.onmessage = (e) => this.onMessage(e);
|
|
15
|
+
}
|
|
16
|
+
resendInitData() {
|
|
17
|
+
const request = {
|
|
18
|
+
command: 'sendInitData',
|
|
19
|
+
};
|
|
20
|
+
this.ws?.send(JSON.stringify(request));
|
|
21
|
+
}
|
|
22
|
+
addListener(type, listener, id) {
|
|
23
|
+
const typeList = this.listeners[type];
|
|
24
|
+
if (typeList === undefined) {
|
|
25
|
+
this.listeners[type] = { [id]: listener };
|
|
26
|
+
return;
|
|
27
|
+
}
|
|
28
|
+
typeList[id] = listener;
|
|
29
|
+
}
|
|
30
|
+
removeListener(type, id) {
|
|
31
|
+
const typeList = this.listeners[type];
|
|
32
|
+
if (typeList) {
|
|
33
|
+
delete typeList[id];
|
|
34
|
+
}
|
|
35
|
+
}
|
|
36
|
+
onMessage(evt) {
|
|
37
|
+
if (this.isDestroyed) {
|
|
38
|
+
return;
|
|
39
|
+
}
|
|
40
|
+
try {
|
|
41
|
+
const eventData = JSON.parse(evt.data);
|
|
42
|
+
const data = CamSwitcherEvents_1.cswEventsSchema.parse(eventData);
|
|
43
|
+
if (data.type === 'init') {
|
|
44
|
+
this.processMessage(data.data, true);
|
|
45
|
+
return;
|
|
46
|
+
}
|
|
47
|
+
this.processMessage(data, false);
|
|
48
|
+
}
|
|
49
|
+
catch (error) {
|
|
50
|
+
console.error('Error parsing event data:', evt.data, error);
|
|
51
|
+
}
|
|
52
|
+
}
|
|
53
|
+
processMessage(event, isInit) {
|
|
54
|
+
const listeners = this.listeners[event.type];
|
|
55
|
+
const list = Object.values(listeners ?? {});
|
|
56
|
+
list.forEach((listener) => listener(event, isInit));
|
|
57
|
+
}
|
|
58
|
+
destroy() {
|
|
59
|
+
this.isDestroyed = true;
|
|
60
|
+
if (this.ws) {
|
|
61
|
+
this.ws.destroy();
|
|
62
|
+
this.ws = null;
|
|
63
|
+
}
|
|
64
|
+
this.listeners = {};
|
|
65
|
+
}
|
|
66
|
+
}
|
|
67
|
+
exports.CamSwitcherEvents = CamSwitcherEvents;
|