iobroker.eusec 2.0.2 → 3.0.2
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/LICENSE +1 -1
- package/README.md +25 -10
- package/build/lib/eufyApiCompat.js +63 -0
- package/build/lib/eufyApiCompat.js.map +7 -0
- package/build/lib/go2rtc.js +36 -0
- package/build/lib/go2rtc.js.map +7 -0
- package/build/lib/interfaces.js.map +1 -1
- package/build/lib/log.js.map +2 -2
- package/build/lib/types.js.map +1 -1
- package/build/lib/utils.js +53 -35
- package/build/lib/utils.js.map +2 -2
- package/build/lib/video.js +55 -38
- package/build/lib/video.js.map +2 -2
- package/build/main.js +586 -238
- package/build/main.js.map +2 -2
- package/cleanupCveFix.js +1 -1
- package/io-package.json +17 -29
- package/package.json +24 -35
package/build/lib/video.js
CHANGED
|
@@ -36,15 +36,16 @@ __export(video_exports, {
|
|
|
36
36
|
streamToGo2rtc: () => streamToGo2rtc
|
|
37
37
|
});
|
|
38
38
|
module.exports = __toCommonJS(video_exports);
|
|
39
|
-
var
|
|
40
|
-
var
|
|
39
|
+
var import_node_net = __toESM(require("node:net"));
|
|
40
|
+
var import_node_path = __toESM(require("node:path"));
|
|
41
41
|
var import_fluent_ffmpeg = __toESM(require("@bropat/fluent-ffmpeg"));
|
|
42
42
|
var import_ffmpeg_for_homebridge = __toESM(require("ffmpeg-for-homebridge"));
|
|
43
43
|
var import_eufy_security_client = require("eufy-security-client");
|
|
44
|
-
var
|
|
44
|
+
var import_node_os = require("node:os");
|
|
45
45
|
var import_fs_extra = __toESM(require("fs-extra"));
|
|
46
46
|
var import_node_stream = __toESM(require("node:stream"));
|
|
47
47
|
var import_promises = require("node:stream/promises");
|
|
48
|
+
var import_go2rtc = require("./go2rtc");
|
|
48
49
|
var import_utils = require("./utils");
|
|
49
50
|
class UniversalStream {
|
|
50
51
|
url;
|
|
@@ -52,43 +53,50 @@ class UniversalStream {
|
|
|
52
53
|
server;
|
|
53
54
|
sock_id;
|
|
54
55
|
constructor(namespace, onSocket) {
|
|
55
|
-
let
|
|
56
|
+
let sockPath = "";
|
|
56
57
|
const unique_sock_id = (0, import_utils.lowestUnusedNumber)([...UniversalStream.socks], 1);
|
|
57
58
|
UniversalStream.socks.add(unique_sock_id);
|
|
58
59
|
this.sock_id = unique_sock_id;
|
|
59
60
|
if (process.platform === "win32") {
|
|
60
61
|
const pipePrefix = "\\\\.\\pipe\\";
|
|
61
62
|
const pipeName = `node-webrtc.${namespace}.${unique_sock_id}.sock`;
|
|
62
|
-
|
|
63
|
-
this.url =
|
|
63
|
+
sockPath = import_node_path.default.join(pipePrefix, pipeName);
|
|
64
|
+
this.url = sockPath;
|
|
64
65
|
} else {
|
|
65
66
|
const pipeName = `${namespace}.${unique_sock_id}.sock`;
|
|
66
|
-
|
|
67
|
-
this.url =
|
|
67
|
+
sockPath = import_node_path.default.join((0, import_node_os.tmpdir)(), pipeName);
|
|
68
|
+
this.url = `unix:${sockPath}`;
|
|
68
69
|
try {
|
|
69
|
-
if (import_fs_extra.default.existsSync(
|
|
70
|
-
import_fs_extra.default.unlinkSync(
|
|
71
|
-
|
|
70
|
+
if (import_fs_extra.default.existsSync(sockPath)) {
|
|
71
|
+
import_fs_extra.default.unlinkSync(sockPath);
|
|
72
|
+
}
|
|
73
|
+
} catch {
|
|
72
74
|
}
|
|
73
75
|
}
|
|
74
|
-
this.server =
|
|
75
|
-
this.server.listen(
|
|
76
|
+
this.server = import_node_net.default.createServer(onSocket);
|
|
77
|
+
this.server.listen(sockPath);
|
|
76
78
|
this.server.on("error", () => {
|
|
77
79
|
});
|
|
78
80
|
}
|
|
79
81
|
close() {
|
|
80
|
-
|
|
81
|
-
|
|
82
|
+
var _a;
|
|
83
|
+
(_a = this.server) == null ? void 0 : _a.close();
|
|
82
84
|
UniversalStream.socks.delete(this.sock_id);
|
|
83
85
|
}
|
|
84
86
|
}
|
|
85
87
|
const StreamInput = function(namespace, stream2) {
|
|
86
|
-
return new UniversalStream(
|
|
87
|
-
|
|
88
|
+
return new UniversalStream(
|
|
89
|
+
namespace,
|
|
90
|
+
(socket) => stream2.pipe(socket, { end: true }).on("error", (_error) => {
|
|
91
|
+
})
|
|
92
|
+
);
|
|
88
93
|
};
|
|
89
94
|
const StreamOutput = function(namespace, stream2) {
|
|
90
|
-
return new UniversalStream(
|
|
91
|
-
|
|
95
|
+
return new UniversalStream(
|
|
96
|
+
namespace,
|
|
97
|
+
(socket) => socket.pipe(stream2, { end: true }).on("error", (_error) => {
|
|
98
|
+
})
|
|
99
|
+
);
|
|
92
100
|
};
|
|
93
101
|
const ffmpegPreviewImage = (config, input, output, log, skip_seconds = 2) => {
|
|
94
102
|
return new Promise((resolve, reject) => {
|
|
@@ -97,10 +105,7 @@ const ffmpegPreviewImage = (config, input, output, log, skip_seconds = 2) => {
|
|
|
97
105
|
import_fluent_ffmpeg.default.setFfmpegPath(import_ffmpeg_for_homebridge.default);
|
|
98
106
|
(0, import_fluent_ffmpeg.default)().withProcessOptions({
|
|
99
107
|
detached: true
|
|
100
|
-
}).addOptions([
|
|
101
|
-
`-ss ${skip_seconds}`,
|
|
102
|
-
"-frames:v 1"
|
|
103
|
-
]).input(input).inputFormat("hls").outputFormat("image2").output(output).on("error", function(err, stdout, stderr) {
|
|
108
|
+
}).addOptions([`-ss ${skip_seconds}`, "-frames:v 1"]).input(input).inputFormat("hls").outputFormat("image2").output(output).on("error", function(err, stdout, stderr) {
|
|
104
109
|
log.error(`ffmpegPreviewImage(): An error occurred: ${err.message}`);
|
|
105
110
|
log.error(`ffmpegPreviewImage(): ffmpeg output:
|
|
106
111
|
${stdout}`);
|
|
@@ -116,7 +121,7 @@ ${stderr}`);
|
|
|
116
121
|
}
|
|
117
122
|
} catch (error) {
|
|
118
123
|
log.error(`ffmpegPreviewImage(): Error: ${error}`);
|
|
119
|
-
reject(error);
|
|
124
|
+
reject(new Error(error.toString()));
|
|
120
125
|
}
|
|
121
126
|
});
|
|
122
127
|
};
|
|
@@ -167,7 +172,9 @@ const ffmpegStreamToHls = (config, namespace, metadata, videoStream, audioStream
|
|
|
167
172
|
command.input(uAudioStream.url).inputFormat(audioFormat).videoCodec("copy").audioCodec("copy");
|
|
168
173
|
options.push("-absf aac_adtstoasc");
|
|
169
174
|
} else {
|
|
170
|
-
log.warn(
|
|
175
|
+
log.warn(
|
|
176
|
+
`ffmpegStreamToHls(): Not support audio codec or unknown audio codec (${import_eufy_security_client.AudioCodec[metadata.audioCodec]})`
|
|
177
|
+
);
|
|
171
178
|
}
|
|
172
179
|
command.output(output).addOptions(options).on("error", function(err, stdout, stderr) {
|
|
173
180
|
log.error(`ffmpegStreamToHls(): An error occurred: ${err.message}`);
|
|
@@ -190,7 +197,7 @@ ${stderr}`);
|
|
|
190
197
|
}
|
|
191
198
|
} catch (error) {
|
|
192
199
|
log.error(`ffmpegStreamToHls(): Error: ${error}`);
|
|
193
|
-
reject(error);
|
|
200
|
+
reject(new Error(error.toString()));
|
|
194
201
|
}
|
|
195
202
|
});
|
|
196
203
|
};
|
|
@@ -239,7 +246,9 @@ const ffmpegStreamToGo2rtc = (config, namespace, camera, metadata, videoStream,
|
|
|
239
246
|
if (audioFormat !== "") {
|
|
240
247
|
command.input(uAudioStream.url).inputFormat(audioFormat).audioCodec("opus");
|
|
241
248
|
} else {
|
|
242
|
-
log.warn(
|
|
249
|
+
log.warn(
|
|
250
|
+
`ffmpegStreamToGo2rtc(): Not support audio codec or unknown audio codec (${import_eufy_security_client.AudioCodec[metadata.audioCodec]})`
|
|
251
|
+
);
|
|
243
252
|
}
|
|
244
253
|
command.output(`rtsp://localhost:${config.go2rtc_rtsp_port}/${camera}`).outputFormat("rtsp").addOptions(options).on("start", (commandline) => {
|
|
245
254
|
log.debug(`ffmpegStreamToGo2rtc(): commandline: ${commandline}`);
|
|
@@ -264,11 +273,11 @@ ${stderr}`);
|
|
|
264
273
|
}
|
|
265
274
|
} catch (error) {
|
|
266
275
|
log.error(`ffmpegStreamToGo2rtc(): Error: ${error}`);
|
|
267
|
-
reject(error);
|
|
276
|
+
reject(new Error(error.toString()));
|
|
268
277
|
}
|
|
269
278
|
});
|
|
270
279
|
};
|
|
271
|
-
const streamToGo2rtc = async (camera, videoStream, audioStream, log,
|
|
280
|
+
const streamToGo2rtc = async (camera, videoStream, audioStream, log, config, _namespace, _metadata) => {
|
|
272
281
|
const { default: got } = await import("got");
|
|
273
282
|
const api = got.extend({
|
|
274
283
|
hooks: {
|
|
@@ -276,11 +285,14 @@ const streamToGo2rtc = async (camera, videoStream, audioStream, log, _config, _n
|
|
|
276
285
|
(error) => {
|
|
277
286
|
const { response, options } = error;
|
|
278
287
|
const { method, url, prefixUrl } = options;
|
|
279
|
-
const shortUrl = (0, import_utils.getShortUrl)(
|
|
288
|
+
const shortUrl = (0, import_utils.getShortUrl)(
|
|
289
|
+
typeof url === "string" ? new URL(url) : url === void 0 ? new URL("") : url,
|
|
290
|
+
typeof prefixUrl === "string" ? prefixUrl : prefixUrl.toString()
|
|
291
|
+
);
|
|
280
292
|
const body = (response == null ? void 0 : response.body) ? response.body : error.message;
|
|
281
293
|
error.message = `${error.message} | method: ${method} url: ${shortUrl}`;
|
|
282
294
|
if (response == null ? void 0 : response.body) {
|
|
283
|
-
error.message = `${error.message} body: ${body}`;
|
|
295
|
+
error.message = `${error.message} body: ${typeof body === "object" ? JSON.stringify(body) : body == null ? void 0 : body.toString()}`;
|
|
284
296
|
}
|
|
285
297
|
return error;
|
|
286
298
|
}
|
|
@@ -293,12 +305,12 @@ const streamToGo2rtc = async (camera, videoStream, audioStream, log, _config, _n
|
|
|
293
305
|
audioStream.on("error", (error) => {
|
|
294
306
|
log.error("streamToGo2rtc(): Audiostream Error", error);
|
|
295
307
|
});
|
|
296
|
-
|
|
308
|
+
const ingestUrl = `http://localhost:${config.go2rtc_api_port}/api/stream?dst=${camera}`;
|
|
309
|
+
const results = await Promise.allSettled([
|
|
297
310
|
(0, import_promises.pipeline)(
|
|
298
311
|
videoStream,
|
|
299
|
-
api.stream.post(
|
|
300
|
-
|
|
301
|
-
if (!((_b = (_a = error.response) == null ? void 0 : _a.body) == null ? void 0 : _b.startsWith("EOF"))) {
|
|
312
|
+
api.stream.post(ingestUrl).on("error", (error) => {
|
|
313
|
+
if (!(0, import_go2rtc.isRegularStreamEnd)(error)) {
|
|
302
314
|
log.error(`streamToGo2rtc(): Got Videostream Error: ${error.message}`);
|
|
303
315
|
}
|
|
304
316
|
}),
|
|
@@ -306,9 +318,8 @@ const streamToGo2rtc = async (camera, videoStream, audioStream, log, _config, _n
|
|
|
306
318
|
),
|
|
307
319
|
(0, import_promises.pipeline)(
|
|
308
320
|
audioStream,
|
|
309
|
-
api.stream.post(
|
|
310
|
-
|
|
311
|
-
if (!((_b = (_a = error.response) == null ? void 0 : _a.body) == null ? void 0 : _b.startsWith("EOF"))) {
|
|
321
|
+
api.stream.post(ingestUrl).on("error", (error) => {
|
|
322
|
+
if (!(0, import_go2rtc.isRegularStreamEnd)(error)) {
|
|
312
323
|
log.error(`streamToGo2rtc(): Got Audiostream Error: ${error.message}`);
|
|
313
324
|
}
|
|
314
325
|
}),
|
|
@@ -379,6 +390,12 @@ const streamToGo2rtc = async (camera, videoStream, audioStream, log, _config, _n
|
|
|
379
390
|
}
|
|
380
391
|
})*/
|
|
381
392
|
]);
|
|
393
|
+
for (const result of results) {
|
|
394
|
+
if (result.status === "rejected" && !(0, import_go2rtc.isRegularStreamEnd)(result.reason)) {
|
|
395
|
+
log.error(`streamToGo2rtc(): Stream to go2rtc failed: ${result.reason}`);
|
|
396
|
+
}
|
|
397
|
+
}
|
|
398
|
+
return results;
|
|
382
399
|
};
|
|
383
400
|
// Annotate the CommonJS export names for ESM import in node:
|
|
384
401
|
0 && (module.exports = {
|
package/build/lib/video.js.map
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"version": 3,
|
|
3
3
|
"sources": ["../../src/lib/video.ts"],
|
|
4
|
-
"sourcesContent": ["import net from \"net\";\r\nimport path from \"path\";\r\nimport ffmpeg from \"@bropat/fluent-ffmpeg\";\r\nimport pathToFfmpeg from \"ffmpeg-for-homebridge\";\r\nimport { Readable } from \"stream\";\r\nimport { StreamMetadata, AudioCodec, VideoCodec } from \"eufy-security-client\";\r\nimport { tmpdir } from \"os\";\r\nimport fse from \"fs-extra\";\r\n\r\nimport stream from \"node:stream\";\r\nimport {pipeline as streamPipeline} from \"node:stream/promises\";\r\n\r\nimport { ioBrokerLogger } from \"./log\";\r\nimport { getShortUrl, lowestUnusedNumber } from \"./utils\";\r\n\r\nclass UniversalStream {\r\n\r\n public url: string;\r\n private static socks = new Set<number>();\r\n private server: net.Server;\r\n private sock_id: number;\r\n\r\n constructor (namespace: string, onSocket: ((socket: net.Socket) => void) | undefined) {\r\n let sockpath = \"\";\r\n\r\n const unique_sock_id = lowestUnusedNumber([...UniversalStream.socks], 1);\r\n UniversalStream.socks.add(unique_sock_id);\r\n this.sock_id = unique_sock_id;\r\n\r\n if (process.platform === \"win32\") {\r\n const pipePrefix = \"\\\\\\\\.\\\\pipe\\\\\";\r\n const pipeName = `node-webrtc.${namespace}.${unique_sock_id}.sock`;\r\n\r\n sockpath = path.join(pipePrefix, pipeName);\r\n this.url = sockpath;\r\n }\r\n else {\r\n const pipeName = `${namespace}.${unique_sock_id}.sock`;\r\n sockpath = path.join(tmpdir(), pipeName);\r\n this.url = \"unix:\" + sockpath;\r\n\r\n try {\r\n if (fse.existsSync(sockpath))\r\n fse.unlinkSync(sockpath);\r\n } catch(error) {\r\n }\r\n }\r\n\r\n this.server = net.createServer(onSocket);\r\n this.server.listen(sockpath);\r\n this.server.on(\"error\", () => {});\r\n }\r\n\r\n public close(): void {\r\n if (this.server)\r\n this.server.close();\r\n UniversalStream.socks.delete(this.sock_id);\r\n }\r\n\r\n}\r\n\r\nexport const StreamInput = function(namespace: string, stream: NodeJS.ReadableStream): UniversalStream {\r\n return new UniversalStream(namespace, (socket: net.Socket) => stream.pipe(socket, { end: true }).on(\"error\", (_error) => {\r\n //TODO: log error\r\n }));\r\n}\r\n\r\nexport const StreamOutput = function(namespace: string, stream: NodeJS.WritableStream): UniversalStream {\r\n return new UniversalStream(namespace, (socket: net.Socket) => socket.pipe(stream, { end: true }).on(\"error\", (_error) => {\r\n //TODO: log error\r\n }));\r\n}\r\n\r\nexport const ffmpegPreviewImage = (config: ioBroker.AdapterConfig, input:string, output: string, log: ioBrokerLogger, skip_seconds = 2.0): Promise<void> => {\r\n return new Promise((resolve, reject) => {\r\n try {\r\n if (pathToFfmpeg) {\r\n // @ts-expect-error old code\r\n ffmpeg.setFfmpegPath(pathToFfmpeg);\r\n\r\n ffmpeg()\r\n .withProcessOptions({\r\n detached: true\r\n })\r\n .addOptions([\r\n `-ss ${skip_seconds}`,\r\n \"-frames:v 1\"\r\n ])\r\n .input(input)\r\n .inputFormat(\"hls\")\r\n .outputFormat(\"image2\")\r\n .output(output)\r\n .on(\"error\", function(err, stdout, stderr) {\r\n log.error(`ffmpegPreviewImage(): An error occurred: ${err.message}`);\r\n log.error(`ffmpegPreviewImage(): ffmpeg output:\\n${stdout}`);\r\n log.error(`ffmpegPreviewImage(): ffmpeg stderr:\\n${stderr}`);\r\n reject(err);\r\n })\r\n .on(\"end\", () => {\r\n log.debug(\"ffmpegPreviewImage(): Preview image generated!\");\r\n resolve();\r\n })\r\n .run();\r\n } else {\r\n reject(new Error(\"ffmpeg binary not found\"));\r\n }\r\n } catch (error) {\r\n log.error(`ffmpegPreviewImage(): Error: ${error}`);\r\n reject(error);\r\n }\r\n });\r\n}\r\n\r\nexport const ffmpegStreamToHls = (config: ioBroker.AdapterConfig, namespace: string, metadata: StreamMetadata, videoStream: Readable, audioStream: Readable, output: string, log: ioBrokerLogger): Promise<void> => {\r\n return new Promise((resolve, reject) => {\r\n try {\r\n if (pathToFfmpeg) {\r\n // @ts-expect-error old code\r\n ffmpeg.setFfmpegPath(pathToFfmpeg);\r\n\r\n videoStream.on(\"error\", (error) => {\r\n log.error(\"ffmpegStreamToHls(): Videostream Error\", error);\r\n });\r\n\r\n audioStream.on(\"error\", (error) => {\r\n log.error(\"ffmpegStreamToHls(): Audiostream Error\", error);\r\n });\r\n\r\n const uVideoStream = StreamInput(namespace, videoStream);\r\n const uAudioStream = StreamInput(namespace, audioStream);\r\n\r\n let videoFormat = \"h264\";\r\n let audioFormat = \"\";\r\n const options: string[] = [\r\n \"-hls_init_time 0\",\r\n \"-hls_time 2\",\r\n \"-hls_segment_type mpegts\",\r\n //\"-start_number 1\",\r\n \"-sc_threshold 0\",\r\n `-g ${metadata.videoFPS}`,\r\n \"-fflags genpts+nobuffer+flush_packets\",\r\n //\"-flush_packets 1\",\r\n \"-hls_playlist_type event\"\r\n //\"-hls_flags split_by_time\"\r\n ];\r\n\r\n switch(metadata.videoCodec) {\r\n case VideoCodec.H264:\r\n videoFormat = \"h264\";\r\n break;\r\n case VideoCodec.H265:\r\n videoFormat = \"hevc\";\r\n break;\r\n }\r\n\r\n switch(metadata.audioCodec) {\r\n case AudioCodec.AAC:\r\n audioFormat = \"aac\";\r\n break;\r\n }\r\n\r\n const command = ffmpeg()\r\n .withProcessOptions({\r\n detached: true\r\n })\r\n .input(uVideoStream.url)\r\n .inputFormat(videoFormat)\r\n .inputFps(metadata.videoFPS);\r\n if (audioFormat !== \"\") {\r\n command.input(uAudioStream.url)\r\n .inputFormat(audioFormat)\r\n .videoCodec(\"copy\")\r\n .audioCodec(\"copy\");\r\n options.push(\"-absf aac_adtstoasc\");\r\n } else {\r\n log.warn(`ffmpegStreamToHls(): Not support audio codec or unknown audio codec (${AudioCodec[metadata.audioCodec]})`);\r\n }\r\n command.output(output)\r\n .addOptions(options)\r\n .on(\"error\", function(err, stdout, stderr) {\r\n log.error(`ffmpegStreamToHls(): An error occurred: ${err.message}`);\r\n log.error(`ffmpegStreamToHls(): ffmpeg output:\\n${stdout}`);\r\n log.error(`ffmpegStreamToHls(): ffmpeg stderr:\\n${stderr}`);\r\n uVideoStream.close();\r\n uAudioStream.close();\r\n reject(err);\r\n })\r\n .on(\"end\", () => {\r\n log.debug(\"ffmpegStreamToHls(): Processing finished!\");\r\n uVideoStream.close();\r\n uAudioStream.close();\r\n resolve();\r\n });\r\n command.run();\r\n } else {\r\n reject(new Error(\"ffmpeg binary not found\"));\r\n }\r\n } catch (error) {\r\n log.error(`ffmpegStreamToHls(): Error: ${error}`);\r\n reject(error);\r\n }\r\n });\r\n}\r\n\r\nexport const ffmpegStreamToGo2rtc = (config: ioBroker.AdapterConfig, namespace: string, camera: string, metadata: StreamMetadata, videoStream: Readable, audioStream: Readable, log: ioBrokerLogger): Promise<void> => {\r\n return new Promise((resolve, reject) => {\r\n try {\r\n if (pathToFfmpeg) {\r\n // @ts-expect-error old code\r\n ffmpeg.setFfmpegPath(pathToFfmpeg);\r\n\r\n videoStream.on(\"error\", (error) => {\r\n log.error(\"ffmpegStreamToGo2rtc(): Videostream Error\", error);\r\n });\r\n\r\n audioStream.on(\"error\", (error) => {\r\n log.error(\"ffmpegStreamToGo2rtc(): Audiostream Error\", error);\r\n });\r\n\r\n //TODO: For debugging purposes\r\n /*const outputVFile = path.resolve(__dirname, \"../../video-stream.dump\");\r\n videoStream.pipe(fse.createWriteStream(outputVFile)).on(\"finish\", () => {\r\n log.debug(\"videoStream dump finished!\");\r\n log.info(\"Manually test the output by running# ffplay output/video-stream.dump\");\r\n });\r\n const outputAFile = path.resolve(__dirname, \"../../audio-stream.dump\");\r\n audioStream.pipe(fse.createWriteStream(outputAFile)).on(\"finish\", () => {\r\n log.debug(\"audioStream dump finished!\");\r\n log.info(\"Manually test the output by running# ffplay output/audio-stream.dump\");\r\n });*/\r\n\r\n const uVideoStream = StreamInput(namespace, videoStream);\r\n const uAudioStream = StreamInput(namespace, audioStream);\r\n\r\n let videoFormat = \"h264\";\r\n let audioFormat = \"\";\r\n const options: string[] = [\r\n \"-rtsp_transport tcp\",\r\n \"-sc_threshold 0\",\r\n \"-fflags genpts+nobuffer+flush_packets\",\r\n //\"-rtpflags latm\",\r\n ];\r\n\r\n switch(metadata.videoCodec) {\r\n case VideoCodec.H264:\r\n videoFormat = \"h264\";\r\n break;\r\n case VideoCodec.H265:\r\n videoFormat = \"hevc\";\r\n break;\r\n }\r\n\r\n switch(metadata.audioCodec) {\r\n case AudioCodec.AAC:\r\n audioFormat = \"aac\";\r\n break;\r\n }\r\n\r\n const command = ffmpeg()\r\n .withProcessOptions({\r\n detached: true\r\n })\r\n .input(uVideoStream.url)\r\n .inputFormat(videoFormat);\r\n if (metadata.videoFPS > 0 ) {\r\n options.push(`-g ${metadata.videoFPS}`);\r\n command.inputFps(metadata.videoFPS);\r\n }\r\n command.videoCodec(\"copy\");\r\n if (audioFormat !== \"\") {\r\n command.input(uAudioStream.url)\r\n .inputFormat(audioFormat)\r\n //.audioCodec(\"copy\");\r\n //.audioCodec(\"aac\");\r\n .audioCodec(\"opus\");\r\n } else {\r\n log.warn(`ffmpegStreamToGo2rtc(): Not support audio codec or unknown audio codec (${AudioCodec[metadata.audioCodec]})`);\r\n }\r\n command.output(`rtsp://localhost:${config.go2rtc_rtsp_port}/${camera}`)\r\n .outputFormat(\"rtsp\")\r\n .addOptions(options)\r\n .on(\"start\", (commandline) => {\r\n log.debug(`ffmpegStreamToGo2rtc(): commandline: ${commandline}`);\r\n })\r\n .on(\"error\", function(err, stdout, stderr) {\r\n log.error(`ffmpegStreamToGo2rtc(): An error occurred: ${err.message}`);\r\n log.error(`ffmpegStreamToGo2rtc(): ffmpeg output:\\n${stdout}`);\r\n log.error(`ffmpegStreamToGo2rtc(): ffmpeg stderr:\\n${stderr}`);\r\n uVideoStream.close();\r\n uAudioStream.close();\r\n reject(err);\r\n })\r\n .on(\"end\", () => {\r\n log.debug(\"ffmpegStreamToGo2rtc(): Processing finished!\");\r\n uVideoStream.close();\r\n uAudioStream.close();\r\n resolve();\r\n });\r\n command.run();\r\n } else {\r\n reject(new Error(\"ffmpeg binary not found\"));\r\n }\r\n } catch (error) {\r\n log.error(`ffmpegStreamToGo2rtc(): Error: ${error}`);\r\n reject(error);\r\n }\r\n });\r\n}\r\n\r\nexport const streamToGo2rtc = async (camera: string, videoStream: Readable, audioStream: Readable, log: ioBrokerLogger, _config: ioBroker.AdapterConfig, _namespace: string, _metadata: StreamMetadata): Promise<Array<PromiseSettledResult<void>>> => {\r\n const { default: got } = await import(\"got\");\r\n const api = got.extend({\r\n hooks: {\r\n beforeError: [\r\n error => {\r\n const { response, options } = error;\r\n const { method, url, prefixUrl } = options;\r\n const shortUrl = getShortUrl(typeof url === \"string\" ? new URL(url) : url === undefined ? new URL(\"\") : url, typeof prefixUrl === \"string\" ? prefixUrl : prefixUrl.toString());\r\n const body = response?.body ? response.body : error.message;\r\n error.message = `${error.message} | method: ${method} url: ${shortUrl}`;\r\n if (response?.body) {\r\n error.message = `${error.message} body: ${body}`;\r\n }\r\n return error;\r\n }\r\n ],\r\n }\r\n });\r\n videoStream.on(\"error\", (error) => {\r\n log.error(\"streamToGo2rtc(): Videostream Error\", error);\r\n });\r\n\r\n audioStream.on(\"error\", (error) => {\r\n log.error(\"streamToGo2rtc(): Audiostream Error\", error);\r\n });\r\n return Promise.allSettled([\r\n streamPipeline(\r\n videoStream,\r\n api.stream.post(`http://localhost:1984/api/stream?dst=${camera}`).on(\"error\", (error: any) => {\r\n if (!(error.response?.body as string)?.startsWith(\"EOF\")) {\r\n log.error(`streamToGo2rtc(): Got Videostream Error: ${error.message}`);\r\n }\r\n }),\r\n new stream.PassThrough()\r\n ),\r\n streamPipeline(\r\n audioStream,\r\n api.stream.post(`http://localhost:1984/api/stream?dst=${camera}`).on(\"error\", (error: any) => {\r\n if (!(error.response?.body as string)?.startsWith(\"EOF\")) {\r\n log.error(`streamToGo2rtc(): Got Audiostream Error: ${error.message}`);\r\n }\r\n }),\r\n new stream.PassThrough()\r\n )\r\n // Alternative implementation in case of go2rtc audio bitstream isn't working (<= 1.8.5)\r\n /*new Promise<void>((resolve, reject) => {\r\n try {\r\n if (pathToFfmpeg) {\r\n ffmpeg.setFfmpegPath(pathToFfmpeg);\r\n\r\n const uAudioStream = StreamInput(namespace, audioStream);\r\n\r\n let audioFormat = \"\";\r\n const options: string[] = [\r\n \"-rtsp_transport tcp\",\r\n \"-fflags genpts+nobuffer+flush_packets\",\r\n //\"-rtpflags latm\",\r\n //\"-compression_level 5\",\r\n \"-application lowdelay\",\r\n ];\r\n\r\n switch(metadata.audioCodec) {\r\n case AudioCodec.AAC:\r\n audioFormat = \"aac\";\r\n break;\r\n }\r\n\r\n const command = ffmpeg()\r\n .withProcessOptions({\r\n detached: true\r\n });\r\n\r\n if (audioFormat !== \"\") {\r\n command.input(uAudioStream.url)\r\n .inputFormat(audioFormat)\r\n .audioCodec(\"opus\");\r\n } else {\r\n log.warn(`streamToGo2rtc(): ffmpeg - Not support audio codec or unknown audio codec (${AudioCodec[metadata.audioCodec]})`);\r\n }\r\n command.output(`rtsp://localhost:${config.go2rtc_rtsp_port}/${camera}`)\r\n .outputFormat(\"rtsp\")\r\n .addOptions(options)\r\n .on(\"start\", (commandline) => {\r\n log.debug(`streamToGo2rtc(): ffmpeg - commandline: ${commandline}`);\r\n })\r\n .on(\"error\", function(err, stdout, stderr) {\r\n log.error(`streamToGo2rtc(): ffmpeg - An error occurred: ${err.message}`);\r\n log.error(`streamToGo2rtc(): ffmpeg output:\\n${stdout}`);\r\n log.error(`streamToGo2rtc(): ffmpeg stderr:\\n${stderr}`);\r\n uAudioStream.close();\r\n reject(err);\r\n })\r\n .on(\"end\", (stdout, stderr) => {\r\n log.debug(`streamToGo2rtc(): ffmpeg output:\\n${stdout}`);\r\n log.debug(`streamToGo2rtc(): ffmpeg stderr:\\n${stderr}`);\r\n log.debug(\"streamToGo2rtc(): Processing finished!\");\r\n uAudioStream.close();\r\n resolve();\r\n });\r\n command.run();\r\n } else {\r\n reject(new Error(\"ffmpeg binary not found\"));\r\n }\r\n } catch (error) {\r\n log.error(`streamToGo2rtc(): Audio Error: ${error}`);\r\n reject(error);\r\n }\r\n })*/\r\n ]);\r\n}"],
|
|
5
|
-
"mappings": ";;;;;;;;;;;;;;;;;;;;;;;;;;;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,
|
|
4
|
+
"sourcesContent": ["import net from 'node:net';\nimport path from 'node:path';\nimport ffmpeg from '@bropat/fluent-ffmpeg';\nimport pathToFfmpeg from 'ffmpeg-for-homebridge';\nimport type { Readable } from 'node:stream';\nimport { type StreamMetadata, AudioCodec, VideoCodec } from 'eufy-security-client';\nimport { tmpdir } from 'node:os';\nimport fse from 'fs-extra';\n\nimport stream from 'node:stream';\nimport { pipeline as streamPipeline } from 'node:stream/promises';\n\nimport type { ioBrokerLogger } from './log';\nimport { isRegularStreamEnd } from './go2rtc';\nimport { getShortUrl, lowestUnusedNumber } from './utils';\n\nclass UniversalStream {\n public url: string;\n private static socks = new Set<number>();\n private readonly server: net.Server;\n private readonly sock_id: number;\n\n constructor(namespace: string, onSocket: ((socket: net.Socket) => void) | undefined) {\n let sockPath = '';\n\n const unique_sock_id = lowestUnusedNumber([...UniversalStream.socks], 1);\n UniversalStream.socks.add(unique_sock_id);\n this.sock_id = unique_sock_id;\n\n if (process.platform === 'win32') {\n const pipePrefix = '\\\\\\\\.\\\\pipe\\\\';\n const pipeName = `node-webrtc.${namespace}.${unique_sock_id}.sock`;\n\n sockPath = path.join(pipePrefix, pipeName);\n this.url = sockPath;\n } else {\n const pipeName = `${namespace}.${unique_sock_id}.sock`;\n sockPath = path.join(tmpdir(), pipeName);\n this.url = `unix:${sockPath}`;\n\n try {\n if (fse.existsSync(sockPath)) {\n fse.unlinkSync(sockPath);\n }\n } catch {\n // ignore\n }\n }\n\n this.server = net.createServer(onSocket);\n this.server.listen(sockPath);\n this.server.on('error', () => {});\n }\n\n public close(): void {\n this.server?.close();\n UniversalStream.socks.delete(this.sock_id);\n }\n}\n\nexport const StreamInput = function (namespace: string, stream: NodeJS.ReadableStream): UniversalStream {\n return new UniversalStream(namespace, (socket: net.Socket) =>\n stream.pipe(socket, { end: true }).on('error', _error => {\n // TODO: log error\n }),\n );\n};\n\nexport const StreamOutput = function (namespace: string, stream: NodeJS.WritableStream): UniversalStream {\n return new UniversalStream(namespace, (socket: net.Socket) =>\n socket.pipe(stream, { end: true }).on('error', _error => {\n // TODO: log error\n }),\n );\n};\n\nexport const ffmpegPreviewImage = (\n config: ioBroker.AdapterConfig,\n input: string,\n output: string,\n log: ioBrokerLogger,\n skip_seconds = 2.0,\n): Promise<void> => {\n return new Promise((resolve, reject) => {\n try {\n if (pathToFfmpeg) {\n ffmpeg.setFfmpegPath(pathToFfmpeg);\n\n ffmpeg()\n .withProcessOptions({\n detached: true,\n })\n .addOptions([`-ss ${skip_seconds}`, '-frames:v 1'])\n .input(input)\n .inputFormat('hls')\n .outputFormat('image2')\n .output(output)\n .on('error', function (err: Error, stdout, stderr) {\n log.error(`ffmpegPreviewImage(): An error occurred: ${err.message}`);\n log.error(`ffmpegPreviewImage(): ffmpeg output:\\n${stdout}`);\n log.error(`ffmpegPreviewImage(): ffmpeg stderr:\\n${stderr}`);\n reject(err);\n })\n .on('end', () => {\n log.debug('ffmpegPreviewImage(): Preview image generated!');\n resolve();\n })\n .run();\n } else {\n reject(new Error('ffmpeg binary not found'));\n }\n } catch (error) {\n log.error(`ffmpegPreviewImage(): Error: ${error as Error}`);\n reject(new Error((error as Error).toString()));\n }\n });\n};\n\nexport const ffmpegStreamToHls = (\n config: ioBroker.AdapterConfig,\n namespace: string,\n metadata: StreamMetadata,\n videoStream: Readable,\n audioStream: Readable,\n output: string,\n log: ioBrokerLogger,\n): Promise<void> => {\n return new Promise((resolve, reject) => {\n try {\n if (pathToFfmpeg) {\n ffmpeg.setFfmpegPath(pathToFfmpeg);\n\n videoStream.on('error', error => {\n log.error('ffmpegStreamToHls(): Videostream Error', error);\n });\n\n audioStream.on('error', error => {\n log.error('ffmpegStreamToHls(): Audiostream Error', error);\n });\n\n const uVideoStream = StreamInput(namespace, videoStream);\n const uAudioStream = StreamInput(namespace, audioStream);\n\n let videoFormat = 'h264';\n let audioFormat = '';\n const options: string[] = [\n '-hls_init_time 0',\n '-hls_time 2',\n '-hls_segment_type mpegts',\n //\"-start_number 1\",\n '-sc_threshold 0',\n `-g ${metadata.videoFPS}`,\n '-fflags genpts+nobuffer+flush_packets',\n //\"-flush_packets 1\",\n '-hls_playlist_type event',\n //\"-hls_flags split_by_time\"\n ];\n\n switch (metadata.videoCodec) {\n case VideoCodec.H264:\n videoFormat = 'h264';\n break;\n case VideoCodec.H265:\n videoFormat = 'hevc';\n break;\n }\n\n switch (metadata.audioCodec) {\n case AudioCodec.AAC:\n audioFormat = 'aac';\n break;\n }\n\n const command = ffmpeg()\n .withProcessOptions({\n detached: true,\n })\n .input(uVideoStream.url)\n .inputFormat(videoFormat)\n .inputFps(metadata.videoFPS);\n if (audioFormat !== '') {\n command.input(uAudioStream.url).inputFormat(audioFormat).videoCodec('copy').audioCodec('copy');\n options.push('-absf aac_adtstoasc');\n } else {\n log.warn(\n `ffmpegStreamToHls(): Not support audio codec or unknown audio codec (${AudioCodec[metadata.audioCodec]})`,\n );\n }\n command\n .output(output)\n .addOptions(options)\n .on('error', function (err: Error, stdout, stderr) {\n log.error(`ffmpegStreamToHls(): An error occurred: ${err.message}`);\n log.error(`ffmpegStreamToHls(): ffmpeg output:\\n${stdout}`);\n log.error(`ffmpegStreamToHls(): ffmpeg stderr:\\n${stderr}`);\n uVideoStream.close();\n uAudioStream.close();\n reject(err);\n })\n .on('end', () => {\n log.debug('ffmpegStreamToHls(): Processing finished!');\n uVideoStream.close();\n uAudioStream.close();\n resolve();\n });\n command.run();\n } else {\n reject(new Error('ffmpeg binary not found'));\n }\n } catch (error) {\n log.error(`ffmpegStreamToHls(): Error: ${error as Error}`);\n reject(new Error((error as Error).toString()));\n }\n });\n};\n\nexport const ffmpegStreamToGo2rtc = (\n config: ioBroker.AdapterConfig,\n namespace: string,\n camera: string,\n metadata: StreamMetadata,\n videoStream: Readable,\n audioStream: Readable,\n log: ioBrokerLogger,\n): Promise<void> => {\n return new Promise((resolve, reject) => {\n try {\n if (pathToFfmpeg) {\n ffmpeg.setFfmpegPath(pathToFfmpeg);\n\n videoStream.on('error', error => {\n log.error('ffmpegStreamToGo2rtc(): Videostream Error', error);\n });\n\n audioStream.on('error', error => {\n log.error('ffmpegStreamToGo2rtc(): Audiostream Error', error);\n });\n\n //TODO: For debugging purposes\n /*const outputVFile = path.resolve(__dirname, \"../../video-stream.dump\");\n videoStream.pipe(fse.createWriteStream(outputVFile)).on(\"finish\", () => {\n log.debug(\"videoStream dump finished!\");\n log.info(\"Manually test the output by running# ffplay output/video-stream.dump\");\n });\n const outputAFile = path.resolve(__dirname, \"../../audio-stream.dump\");\n audioStream.pipe(fse.createWriteStream(outputAFile)).on(\"finish\", () => {\n log.debug(\"audioStream dump finished!\");\n log.info(\"Manually test the output by running# ffplay output/audio-stream.dump\");\n });*/\n\n const uVideoStream = StreamInput(namespace, videoStream);\n const uAudioStream = StreamInput(namespace, audioStream);\n\n let videoFormat = 'h264';\n let audioFormat = '';\n const options: string[] = [\n '-rtsp_transport tcp',\n '-sc_threshold 0',\n '-fflags genpts+nobuffer+flush_packets',\n //\"-rtpflags latm\",\n ];\n\n switch (metadata.videoCodec) {\n case VideoCodec.H264:\n videoFormat = 'h264';\n break;\n case VideoCodec.H265:\n videoFormat = 'hevc';\n break;\n }\n\n switch (metadata.audioCodec) {\n case AudioCodec.AAC:\n audioFormat = 'aac';\n break;\n }\n\n const command = ffmpeg()\n .withProcessOptions({\n detached: true,\n })\n .input(uVideoStream.url)\n .inputFormat(videoFormat);\n if (metadata.videoFPS > 0) {\n options.push(`-g ${metadata.videoFPS}`);\n command.inputFps(metadata.videoFPS);\n }\n command.videoCodec('copy');\n if (audioFormat !== '') {\n command\n .input(uAudioStream.url)\n .inputFormat(audioFormat)\n //.audioCodec(\"copy\");\n //.audioCodec(\"aac\");\n .audioCodec('opus');\n } else {\n log.warn(\n `ffmpegStreamToGo2rtc(): Not support audio codec or unknown audio codec (${AudioCodec[metadata.audioCodec]})`,\n );\n }\n command\n .output(`rtsp://localhost:${config.go2rtc_rtsp_port}/${camera}`)\n .outputFormat('rtsp')\n .addOptions(options)\n .on('start', commandline => {\n log.debug(`ffmpegStreamToGo2rtc(): commandline: ${commandline}`);\n })\n .on('error', function (err: Error, stdout, stderr) {\n log.error(`ffmpegStreamToGo2rtc(): An error occurred: ${err.message}`);\n log.error(`ffmpegStreamToGo2rtc(): ffmpeg output:\\n${stdout}`);\n log.error(`ffmpegStreamToGo2rtc(): ffmpeg stderr:\\n${stderr}`);\n uVideoStream.close();\n uAudioStream.close();\n reject(err);\n })\n .on('end', () => {\n log.debug('ffmpegStreamToGo2rtc(): Processing finished!');\n uVideoStream.close();\n uAudioStream.close();\n resolve();\n });\n command.run();\n } else {\n reject(new Error('ffmpeg binary not found'));\n }\n } catch (error) {\n log.error(`ffmpegStreamToGo2rtc(): Error: ${error as Error}`);\n reject(new Error((error as Error).toString()));\n }\n });\n};\n\nexport const streamToGo2rtc = async (\n camera: string,\n videoStream: Readable,\n audioStream: Readable,\n log: ioBrokerLogger,\n config: ioBroker.AdapterConfig,\n _namespace: string,\n _metadata: StreamMetadata,\n): Promise<Array<PromiseSettledResult<void>>> => {\n const { default: got } = await import('got');\n const api = got.extend({\n hooks: {\n beforeError: [\n error => {\n const { response, options } = error;\n const { method, url, prefixUrl } = options;\n const shortUrl = getShortUrl(\n typeof url === 'string' ? new URL(url) : url === undefined ? new URL('') : url,\n typeof prefixUrl === 'string' ? prefixUrl : prefixUrl.toString(),\n );\n const body = response?.body ? response.body : error.message;\n error.message = `${error.message} | method: ${method} url: ${shortUrl}`;\n if (response?.body) {\n // eslint-disable-next-line @typescript-eslint/no-base-to-string\n error.message = `${error.message} body: ${typeof body === 'object' ? JSON.stringify(body) : body?.toString()}`;\n }\n return error;\n },\n ],\n },\n });\n videoStream.on('error', error => {\n log.error('streamToGo2rtc(): Videostream Error', error);\n });\n\n audioStream.on('error', error => {\n log.error('streamToGo2rtc(): Audiostream Error', error);\n });\n const ingestUrl = `http://localhost:${config.go2rtc_api_port}/api/stream?dst=${camera}`;\n const results = await Promise.allSettled([\n streamPipeline(\n videoStream,\n api.stream.post(ingestUrl).on('error', (error: any) => {\n if (!isRegularStreamEnd(error)) {\n log.error(`streamToGo2rtc(): Got Videostream Error: ${error.message}`);\n }\n }),\n new stream.PassThrough(),\n ),\n streamPipeline(\n audioStream,\n api.stream.post(ingestUrl).on('error', (error: any) => {\n if (!isRegularStreamEnd(error)) {\n log.error(`streamToGo2rtc(): Got Audiostream Error: ${error.message}`);\n }\n }),\n new stream.PassThrough(),\n ),\n // Alternative implementation in case of go2rtc audio bitstream isn't working (<= 1.8.5)\n /*new Promise<void>((resolve, reject) => {\n try {\n if (pathToFfmpeg) {\n ffmpeg.setFfmpegPath(pathToFfmpeg);\n\n const uAudioStream = StreamInput(namespace, audioStream);\n\n let audioFormat = \"\";\n const options: string[] = [\n \"-rtsp_transport tcp\",\n \"-fflags genpts+nobuffer+flush_packets\",\n //\"-rtpflags latm\",\n //\"-compression_level 5\",\n \"-application lowdelay\",\n ];\n\n switch(metadata.audioCodec) {\n case AudioCodec.AAC:\n audioFormat = \"aac\";\n break;\n }\n\n const command = ffmpeg()\n .withProcessOptions({\n detached: true\n });\n\n if (audioFormat !== \"\") {\n command.input(uAudioStream.url)\n .inputFormat(audioFormat)\n .audioCodec(\"opus\");\n } else {\n log.warn(`streamToGo2rtc(): ffmpeg - Not support audio codec or unknown audio codec (${AudioCodec[metadata.audioCodec]})`);\n }\n command.output(`rtsp://localhost:${config.go2rtc_rtsp_port}/${camera}`)\n .outputFormat(\"rtsp\")\n .addOptions(options)\n .on(\"start\", (commandline) => {\n log.debug(`streamToGo2rtc(): ffmpeg - commandline: ${commandline}`);\n })\n .on(\"error\", function(err, stdout, stderr) {\n log.error(`streamToGo2rtc(): ffmpeg - An error occurred: ${err.message}`);\n log.error(`streamToGo2rtc(): ffmpeg output:\\n${stdout}`);\n log.error(`streamToGo2rtc(): ffmpeg stderr:\\n${stderr}`);\n uAudioStream.close();\n reject(err);\n })\n .on(\"end\", (stdout, stderr) => {\n log.debug(`streamToGo2rtc(): ffmpeg output:\\n${stdout}`);\n log.debug(`streamToGo2rtc(): ffmpeg stderr:\\n${stderr}`);\n log.debug(\"streamToGo2rtc(): Processing finished!\");\n uAudioStream.close();\n resolve();\n });\n command.run();\n } else {\n reject(new Error(\"ffmpeg binary not found\"));\n }\n } catch (error) {\n log.error(`streamToGo2rtc(): Audio Error: ${error}`);\n reject(error);\n }\n })*/\n ]);\n\n // Without this the rejection is swallowed by allSettled and a dead pipeline stays invisible,\n // while the camera keeps streaming until the maximum livestream duration expires.\n for (const result of results) {\n if (result.status === 'rejected' && !isRegularStreamEnd(result.reason)) {\n log.error(`streamToGo2rtc(): Stream to go2rtc failed: ${result.reason}`);\n }\n }\n\n return results;\n};\n"],
|
|
5
|
+
"mappings": "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",
|
|
6
6
|
"names": ["path", "fse", "net", "stream", "pathToFfmpeg", "ffmpeg", "streamPipeline"]
|
|
7
7
|
}
|