@camstack/addon-post-analysis 0.1.19 → 0.1.20
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/dist/embedding-encoder/index.js +1 -1
- package/dist/embedding-encoder/index.mjs +1 -1
- package/dist/enrichment-engine/index.js +1 -1
- package/dist/enrichment-engine/index.mjs +1 -1
- package/dist/{index-BFbwYH1P.js → index-B0RhVv1c.js} +3514 -750
- package/dist/index-B0RhVv1c.js.map +1 -0
- package/dist/{index-BrTlzsrE.mjs → index-ot5PeFg_.mjs} +3517 -753
- package/dist/index-ot5PeFg_.mjs.map +1 -0
- package/dist/pipeline-analytics/@mf-types.zip +0 -0
- package/dist/pipeline-analytics/{__mfe_internal__addon_pipeline_analytics_widgets__loadShare___mf_0_camstack_mf_1_sdk__loadShare__.mjs-h5aXOPSA.mjs → __mfe_internal__addon_pipeline_analytics_widgets__loadShare___mf_0_camstack_mf_1_sdk__loadShare__.mjs-lantnv8e.mjs} +1 -1
- package/dist/pipeline-analytics/__mfe_internal__addon_pipeline_analytics_widgets__loadShare___mf_0_camstack_mf_1_types__loadShare__.mjs-BD3oMNGB.mjs +29 -0
- package/dist/pipeline-analytics/__mfe_internal__addon_pipeline_analytics_widgets__loadShare___mf_0_camstack_mf_1_ui_mf_2_library__loadShare__.mjs-BgOHCakr.mjs +18 -0
- package/dist/pipeline-analytics/{__mfe_internal__addon_pipeline_analytics_widgets__loadShare__react__loadShare__.mjs-BZTB2scQ.mjs → __mfe_internal__addon_pipeline_analytics_widgets__loadShare__react__loadShare__.mjs-D1qPKjvR.mjs} +2 -1
- package/dist/pipeline-analytics/{__mfe_internal__addon_pipeline_analytics_widgets__loadShare__react__loadShare__.mjs_commonjs-proxy-CJO5YKGV.mjs → __mfe_internal__addon_pipeline_analytics_widgets__loadShare__react__loadShare__.mjs_commonjs-proxy-B5X50Xa4.mjs} +1 -1
- package/dist/pipeline-analytics/{__mfe_internal__addon_pipeline_analytics_widgets__loadShare__react_mf_2_dom__loadShare__.mjs_commonjs-proxy-B0h0AGOH.mjs → __mfe_internal__addon_pipeline_analytics_widgets__loadShare__react_mf_2_dom__loadShare__.mjs_commonjs-proxy-B10b5k5J.mjs} +1 -1
- package/dist/pipeline-analytics/_stub.js +2 -3
- package/dist/pipeline-analytics/{_virtual_mf-localSharedImportMap___mfe_internal__addon_pipeline_analytics_widgets-kZBmgzMg.mjs → _virtual_mf-localSharedImportMap___mfe_internal__addon_pipeline_analytics_widgets-DWB3apaJ.mjs} +6 -6
- package/dist/pipeline-analytics/{client-BlxIUpgf.mjs → client-C6xdgLZU.mjs} +2 -2
- package/dist/pipeline-analytics/{hostInit-qBB1Thhi.mjs → hostInit-3cyL9eyG.mjs} +12 -12
- package/dist/pipeline-analytics/{index-Dw6Q30NI.mjs → index-BCTHeI2m.mjs} +253 -267
- package/dist/pipeline-analytics/{index-DlhiA9R0.mjs → index-BuWLz0GG.mjs} +1 -1
- package/dist/pipeline-analytics/{index-DtdgkNgf.mjs → index-CIwq-tQL.mjs} +1 -1
- package/dist/pipeline-analytics/{index-BoL0rgZt.mjs → index-CWBMDbou.mjs} +1 -1
- package/dist/pipeline-analytics/index-CZhagnlH.mjs +67784 -0
- package/dist/pipeline-analytics/{index-CR1aiZDH.mjs → index-D883Q5B8.mjs} +1 -1
- package/dist/pipeline-analytics/{index-Dy2V7VOm.mjs → index-DtOI1aTU.mjs} +10112 -5987
- package/dist/pipeline-analytics/index.js +605 -42
- package/dist/pipeline-analytics/index.js.map +1 -1
- package/dist/pipeline-analytics/index.mjs +604 -42
- package/dist/pipeline-analytics/index.mjs.map +1 -1
- package/dist/pipeline-analytics/{jsx-runtime-Dlbl3gpr.mjs → jsx-runtime-DdLhuHmJ.mjs} +1 -1
- package/dist/pipeline-analytics/remoteEntry.js +1 -1
- package/dist/pipeline-analytics/{schemas-ClCuS4qa.mjs → schemas-B7L0qZtq.mjs} +411 -406
- package/package.json +12 -27
- package/dist/ffmpeg-config-DRONlBsj.mjs +0 -56
- package/dist/ffmpeg-config-DRONlBsj.mjs.map +0 -1
- package/dist/ffmpeg-config-uANz3sV5.js +0 -73
- package/dist/ffmpeg-config-uANz3sV5.js.map +0 -1
- package/dist/index-BFbwYH1P.js.map +0 -1
- package/dist/index-BrTlzsrE.mjs.map +0 -1
- package/dist/pipeline-analytics/__mfe_internal__addon_pipeline_analytics_widgets__loadShare___mf_0_camstack_mf_1_types__loadShare__.mjs-NjF4kxzW.mjs +0 -19
- package/dist/pipeline-analytics/__mfe_internal__addon_pipeline_analytics_widgets__loadShare___mf_0_camstack_mf_1_ui_mf_2_library__loadShare__.mjs-7HAAnpQu.mjs +0 -18
- package/dist/pipeline-analytics/index-i47purqY.mjs +0 -37880
- package/dist/playlist-generator-EhPaB7Hn.js +0 -48
- package/dist/playlist-generator-EhPaB7Hn.js.map +0 -1
- package/dist/playlist-generator-VTkgn53O.mjs +0 -48
- package/dist/playlist-generator-VTkgn53O.mjs.map +0 -1
- package/dist/recording/index.js +0 -257
- package/dist/recording/index.js.map +0 -1
- package/dist/recording/index.mjs +0 -235
- package/dist/recording/index.mjs.map +0 -1
- package/dist/recording-coordinator-BoGr5moz.js +0 -1052
- package/dist/recording-coordinator-BoGr5moz.js.map +0 -1
- package/dist/recording-coordinator-CsYH9LqF.mjs +0 -1012
- package/dist/recording-coordinator-CsYH9LqF.mjs.map +0 -1
- package/dist/recording-db-gOgaoQh0.js +0 -348
- package/dist/recording-db-gOgaoQh0.js.map +0 -1
- package/dist/recording-db-lIkSMTLq.mjs +0 -348
- package/dist/recording-db-lIkSMTLq.mjs.map +0 -1
- package/dist/recording-service-facade-B9lG6OFn.mjs +0 -123
- package/dist/recording-service-facade-B9lG6OFn.mjs.map +0 -1
- package/dist/recording-service-facade-Do1PKlAL.js +0 -123
- package/dist/recording-service-facade-Do1PKlAL.js.map +0 -1
- package/dist/storage-estimator-CRpoQc9j.js +0 -72
- package/dist/storage-estimator-CRpoQc9j.js.map +0 -1
- package/dist/storage-estimator-DzD8gWJH.mjs +0 -72
- package/dist/storage-estimator-DzD8gWJH.mjs.map +0 -1
|
@@ -1,48 +0,0 @@
|
|
|
1
|
-
"use strict";
|
|
2
|
-
Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
|
|
3
|
-
const FALLBACK_STREAMS = ["sub", "mid", "main"];
|
|
4
|
-
class PlaylistGenerator {
|
|
5
|
-
constructor(db) {
|
|
6
|
-
this.db = db;
|
|
7
|
-
}
|
|
8
|
-
generate(deviceId, streamId, startTime, endTime, options) {
|
|
9
|
-
const segments = this.resolveSegments(deviceId, streamId, startTime, endTime);
|
|
10
|
-
return this.buildPlaylist(segments, options);
|
|
11
|
-
}
|
|
12
|
-
resolveSegments(deviceId, streamId, startTime, endTime) {
|
|
13
|
-
const segments = this.db.querySegments(deviceId, streamId, startTime, endTime);
|
|
14
|
-
if (segments.length > 0) {
|
|
15
|
-
return segments;
|
|
16
|
-
}
|
|
17
|
-
const fallbacks = FALLBACK_STREAMS.filter((s) => s !== streamId);
|
|
18
|
-
for (const fb of fallbacks) {
|
|
19
|
-
const fallbackSegments = this.db.querySegments(deviceId, fb, startTime, endTime);
|
|
20
|
-
if (fallbackSegments.length > 0) {
|
|
21
|
-
return fallbackSegments;
|
|
22
|
-
}
|
|
23
|
-
}
|
|
24
|
-
return [];
|
|
25
|
-
}
|
|
26
|
-
buildPlaylist(segments, options) {
|
|
27
|
-
const targetDuration = segments.length > 0 ? Math.ceil(Math.max(...segments.map((s) => s.duration))) : 4;
|
|
28
|
-
const lines = [
|
|
29
|
-
"#EXTM3U",
|
|
30
|
-
"#EXT-X-VERSION:7",
|
|
31
|
-
`#EXT-X-TARGETDURATION:${targetDuration}`,
|
|
32
|
-
"#EXT-X-MEDIA-SEQUENCE:0"
|
|
33
|
-
];
|
|
34
|
-
if (!options?.live) {
|
|
35
|
-
lines.push("#EXT-X-PLAYLIST-TYPE:VOD");
|
|
36
|
-
}
|
|
37
|
-
for (const seg of segments) {
|
|
38
|
-
lines.push(`#EXTINF:${seg.duration.toFixed(3)},`);
|
|
39
|
-
lines.push(seg.path);
|
|
40
|
-
}
|
|
41
|
-
if (!options?.live) {
|
|
42
|
-
lines.push("#EXT-X-ENDLIST");
|
|
43
|
-
}
|
|
44
|
-
return lines.join("\n");
|
|
45
|
-
}
|
|
46
|
-
}
|
|
47
|
-
exports.PlaylistGenerator = PlaylistGenerator;
|
|
48
|
-
//# sourceMappingURL=playlist-generator-EhPaB7Hn.js.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"playlist-generator-EhPaB7Hn.js","sources":["../src/recording/recording/playlist-generator.ts"],"sourcesContent":["import type { RecordingDb } from './recording-db.js'\nimport type { RecordingSegment } from './types.js'\n\ninterface PlaylistOptions {\n readonly live?: boolean\n}\n\nconst FALLBACK_STREAMS = ['sub', 'mid', 'main'] as const\n\nexport class PlaylistGenerator {\n constructor(private readonly db: RecordingDb) {}\n\n generate(deviceId: number, streamId: string, startTime: number, endTime: number, options?: PlaylistOptions): string {\n const segments = this.resolveSegments(deviceId, streamId, startTime, endTime)\n return this.buildPlaylist(segments, options)\n }\n\n private resolveSegments(deviceId: number, streamId: string, startTime: number, endTime: number): readonly RecordingSegment[] {\n const segments = this.db.querySegments(deviceId, streamId, startTime, endTime)\n if (segments.length > 0) {\n return segments\n }\n\n const fallbacks = FALLBACK_STREAMS.filter(s => s !== streamId)\n for (const fb of fallbacks) {\n const fallbackSegments = this.db.querySegments(deviceId, fb, startTime, endTime)\n if (fallbackSegments.length > 0) {\n return fallbackSegments\n }\n }\n\n return []\n }\n\n private buildPlaylist(segments: readonly RecordingSegment[], options?: PlaylistOptions): string {\n const targetDuration = segments.length > 0\n ? Math.ceil(Math.max(...segments.map(s => s.duration)))\n : 4\n\n const lines: string[] = [\n '#EXTM3U',\n '#EXT-X-VERSION:7',\n `#EXT-X-TARGETDURATION:${targetDuration}`,\n '#EXT-X-MEDIA-SEQUENCE:0',\n ]\n\n if (!options?.live) {\n lines.push('#EXT-X-PLAYLIST-TYPE:VOD')\n }\n\n for (const seg of segments) {\n lines.push(`#EXTINF:${seg.duration.toFixed(3)},`)\n lines.push(seg.path)\n }\n\n if (!options?.live) {\n lines.push('#EXT-X-ENDLIST')\n }\n\n return lines.join('\\n')\n }\n}\n"],"names":[],"mappings":";;AAOA,MAAM,mBAAmB,CAAC,OAAO,OAAO,MAAM;AAEvC,MAAM,kBAAkB;AAAA,EAC7B,YAA6B,IAAiB;AAAjB,SAAA,KAAA;AAAA,EAAkB;AAAA,EAE/C,SAAS,UAAkB,UAAkB,WAAmB,SAAiB,SAAmC;AAClH,UAAM,WAAW,KAAK,gBAAgB,UAAU,UAAU,WAAW,OAAO;AAC5E,WAAO,KAAK,cAAc,UAAU,OAAO;AAAA,EAC7C;AAAA,EAEQ,gBAAgB,UAAkB,UAAkB,WAAmB,SAA8C;AAC3H,UAAM,WAAW,KAAK,GAAG,cAAc,UAAU,UAAU,WAAW,OAAO;AAC7E,QAAI,SAAS,SAAS,GAAG;AACvB,aAAO;AAAA,IACT;AAEA,UAAM,YAAY,iBAAiB,OAAO,CAAA,MAAK,MAAM,QAAQ;AAC7D,eAAW,MAAM,WAAW;AAC1B,YAAM,mBAAmB,KAAK,GAAG,cAAc,UAAU,IAAI,WAAW,OAAO;AAC/E,UAAI,iBAAiB,SAAS,GAAG;AAC/B,eAAO;AAAA,MACT;AAAA,IACF;AAEA,WAAO,CAAA;AAAA,EACT;AAAA,EAEQ,cAAc,UAAuC,SAAmC;AAC9F,UAAM,iBAAiB,SAAS,SAAS,IACrC,KAAK,KAAK,KAAK,IAAI,GAAG,SAAS,IAAI,CAAA,MAAK,EAAE,QAAQ,CAAC,CAAC,IACpD;AAEJ,UAAM,QAAkB;AAAA,MACtB;AAAA,MACA;AAAA,MACA,yBAAyB,cAAc;AAAA,MACvC;AAAA,IAAA;AAGF,QAAI,CAAC,SAAS,MAAM;AAClB,YAAM,KAAK,0BAA0B;AAAA,IACvC;AAEA,eAAW,OAAO,UAAU;AAC1B,YAAM,KAAK,WAAW,IAAI,SAAS,QAAQ,CAAC,CAAC,GAAG;AAChD,YAAM,KAAK,IAAI,IAAI;AAAA,IACrB;AAEA,QAAI,CAAC,SAAS,MAAM;AAClB,YAAM,KAAK,gBAAgB;AAAA,IAC7B;AAEA,WAAO,MAAM,KAAK,IAAI;AAAA,EACxB;AACF;;"}
|
|
@@ -1,48 +0,0 @@
|
|
|
1
|
-
const FALLBACK_STREAMS = ["sub", "mid", "main"];
|
|
2
|
-
class PlaylistGenerator {
|
|
3
|
-
constructor(db) {
|
|
4
|
-
this.db = db;
|
|
5
|
-
}
|
|
6
|
-
generate(deviceId, streamId, startTime, endTime, options) {
|
|
7
|
-
const segments = this.resolveSegments(deviceId, streamId, startTime, endTime);
|
|
8
|
-
return this.buildPlaylist(segments, options);
|
|
9
|
-
}
|
|
10
|
-
resolveSegments(deviceId, streamId, startTime, endTime) {
|
|
11
|
-
const segments = this.db.querySegments(deviceId, streamId, startTime, endTime);
|
|
12
|
-
if (segments.length > 0) {
|
|
13
|
-
return segments;
|
|
14
|
-
}
|
|
15
|
-
const fallbacks = FALLBACK_STREAMS.filter((s) => s !== streamId);
|
|
16
|
-
for (const fb of fallbacks) {
|
|
17
|
-
const fallbackSegments = this.db.querySegments(deviceId, fb, startTime, endTime);
|
|
18
|
-
if (fallbackSegments.length > 0) {
|
|
19
|
-
return fallbackSegments;
|
|
20
|
-
}
|
|
21
|
-
}
|
|
22
|
-
return [];
|
|
23
|
-
}
|
|
24
|
-
buildPlaylist(segments, options) {
|
|
25
|
-
const targetDuration = segments.length > 0 ? Math.ceil(Math.max(...segments.map((s) => s.duration))) : 4;
|
|
26
|
-
const lines = [
|
|
27
|
-
"#EXTM3U",
|
|
28
|
-
"#EXT-X-VERSION:7",
|
|
29
|
-
`#EXT-X-TARGETDURATION:${targetDuration}`,
|
|
30
|
-
"#EXT-X-MEDIA-SEQUENCE:0"
|
|
31
|
-
];
|
|
32
|
-
if (!options?.live) {
|
|
33
|
-
lines.push("#EXT-X-PLAYLIST-TYPE:VOD");
|
|
34
|
-
}
|
|
35
|
-
for (const seg of segments) {
|
|
36
|
-
lines.push(`#EXTINF:${seg.duration.toFixed(3)},`);
|
|
37
|
-
lines.push(seg.path);
|
|
38
|
-
}
|
|
39
|
-
if (!options?.live) {
|
|
40
|
-
lines.push("#EXT-X-ENDLIST");
|
|
41
|
-
}
|
|
42
|
-
return lines.join("\n");
|
|
43
|
-
}
|
|
44
|
-
}
|
|
45
|
-
export {
|
|
46
|
-
PlaylistGenerator
|
|
47
|
-
};
|
|
48
|
-
//# sourceMappingURL=playlist-generator-VTkgn53O.mjs.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"playlist-generator-VTkgn53O.mjs","sources":["../src/recording/recording/playlist-generator.ts"],"sourcesContent":["import type { RecordingDb } from './recording-db.js'\nimport type { RecordingSegment } from './types.js'\n\ninterface PlaylistOptions {\n readonly live?: boolean\n}\n\nconst FALLBACK_STREAMS = ['sub', 'mid', 'main'] as const\n\nexport class PlaylistGenerator {\n constructor(private readonly db: RecordingDb) {}\n\n generate(deviceId: number, streamId: string, startTime: number, endTime: number, options?: PlaylistOptions): string {\n const segments = this.resolveSegments(deviceId, streamId, startTime, endTime)\n return this.buildPlaylist(segments, options)\n }\n\n private resolveSegments(deviceId: number, streamId: string, startTime: number, endTime: number): readonly RecordingSegment[] {\n const segments = this.db.querySegments(deviceId, streamId, startTime, endTime)\n if (segments.length > 0) {\n return segments\n }\n\n const fallbacks = FALLBACK_STREAMS.filter(s => s !== streamId)\n for (const fb of fallbacks) {\n const fallbackSegments = this.db.querySegments(deviceId, fb, startTime, endTime)\n if (fallbackSegments.length > 0) {\n return fallbackSegments\n }\n }\n\n return []\n }\n\n private buildPlaylist(segments: readonly RecordingSegment[], options?: PlaylistOptions): string {\n const targetDuration = segments.length > 0\n ? Math.ceil(Math.max(...segments.map(s => s.duration)))\n : 4\n\n const lines: string[] = [\n '#EXTM3U',\n '#EXT-X-VERSION:7',\n `#EXT-X-TARGETDURATION:${targetDuration}`,\n '#EXT-X-MEDIA-SEQUENCE:0',\n ]\n\n if (!options?.live) {\n lines.push('#EXT-X-PLAYLIST-TYPE:VOD')\n }\n\n for (const seg of segments) {\n lines.push(`#EXTINF:${seg.duration.toFixed(3)},`)\n lines.push(seg.path)\n }\n\n if (!options?.live) {\n lines.push('#EXT-X-ENDLIST')\n }\n\n return lines.join('\\n')\n }\n}\n"],"names":[],"mappings":"AAOA,MAAM,mBAAmB,CAAC,OAAO,OAAO,MAAM;AAEvC,MAAM,kBAAkB;AAAA,EAC7B,YAA6B,IAAiB;AAAjB,SAAA,KAAA;AAAA,EAAkB;AAAA,EAE/C,SAAS,UAAkB,UAAkB,WAAmB,SAAiB,SAAmC;AAClH,UAAM,WAAW,KAAK,gBAAgB,UAAU,UAAU,WAAW,OAAO;AAC5E,WAAO,KAAK,cAAc,UAAU,OAAO;AAAA,EAC7C;AAAA,EAEQ,gBAAgB,UAAkB,UAAkB,WAAmB,SAA8C;AAC3H,UAAM,WAAW,KAAK,GAAG,cAAc,UAAU,UAAU,WAAW,OAAO;AAC7E,QAAI,SAAS,SAAS,GAAG;AACvB,aAAO;AAAA,IACT;AAEA,UAAM,YAAY,iBAAiB,OAAO,CAAA,MAAK,MAAM,QAAQ;AAC7D,eAAW,MAAM,WAAW;AAC1B,YAAM,mBAAmB,KAAK,GAAG,cAAc,UAAU,IAAI,WAAW,OAAO;AAC/E,UAAI,iBAAiB,SAAS,GAAG;AAC/B,eAAO;AAAA,MACT;AAAA,IACF;AAEA,WAAO,CAAA;AAAA,EACT;AAAA,EAEQ,cAAc,UAAuC,SAAmC;AAC9F,UAAM,iBAAiB,SAAS,SAAS,IACrC,KAAK,KAAK,KAAK,IAAI,GAAG,SAAS,IAAI,CAAA,MAAK,EAAE,QAAQ,CAAC,CAAC,IACpD;AAEJ,UAAM,QAAkB;AAAA,MACtB;AAAA,MACA;AAAA,MACA,yBAAyB,cAAc;AAAA,MACvC;AAAA,IAAA;AAGF,QAAI,CAAC,SAAS,MAAM;AAClB,YAAM,KAAK,0BAA0B;AAAA,IACvC;AAEA,eAAW,OAAO,UAAU;AAC1B,YAAM,KAAK,WAAW,IAAI,SAAS,QAAQ,CAAC,CAAC,GAAG;AAChD,YAAM,KAAK,IAAI,IAAI;AAAA,IACrB;AAEA,QAAI,CAAC,SAAS,MAAM;AAClB,YAAM,KAAK,gBAAgB;AAAA,IAC7B;AAEA,WAAO,MAAM,KAAK,IAAI;AAAA,EACxB;AACF;"}
|
package/dist/recording/index.js
DELETED
|
@@ -1,257 +0,0 @@
|
|
|
1
|
-
"use strict";
|
|
2
|
-
var __create = Object.create;
|
|
3
|
-
var __defProp = Object.defineProperty;
|
|
4
|
-
var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
|
|
5
|
-
var __getOwnPropNames = Object.getOwnPropertyNames;
|
|
6
|
-
var __getProtoOf = Object.getPrototypeOf;
|
|
7
|
-
var __hasOwnProp = Object.prototype.hasOwnProperty;
|
|
8
|
-
var __copyProps = (to, from, except, desc) => {
|
|
9
|
-
if (from && typeof from === "object" || typeof from === "function") {
|
|
10
|
-
for (let key of __getOwnPropNames(from))
|
|
11
|
-
if (!__hasOwnProp.call(to, key) && key !== except)
|
|
12
|
-
__defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
|
|
13
|
-
}
|
|
14
|
-
return to;
|
|
15
|
-
};
|
|
16
|
-
var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__getProtoOf(mod)) : {}, __copyProps(
|
|
17
|
-
// If the importer is in node compatibility mode or this is not an ESM
|
|
18
|
-
// file that has been converted to a CommonJS file using a Babel-
|
|
19
|
-
// compatible transform (i.e. "__esModule" has not been set), then set
|
|
20
|
-
// "default" to the CommonJS "module.exports" for node compatibility.
|
|
21
|
-
isNodeMode || !mod || !mod.__esModule ? __defProp(target, "default", { value: mod, enumerable: true }) : target,
|
|
22
|
-
mod
|
|
23
|
-
));
|
|
24
|
-
Object.defineProperties(exports, { __esModule: { value: true }, [Symbol.toStringTag]: { value: "Module" } });
|
|
25
|
-
const index = require("../index-BFbwYH1P.js");
|
|
26
|
-
class RecordingAddon extends index.BaseAddon {
|
|
27
|
-
coordinator = null;
|
|
28
|
-
recordingDb = null;
|
|
29
|
-
sqliteDb = null;
|
|
30
|
-
recordingDeps = null;
|
|
31
|
-
serviceFacade = null;
|
|
32
|
-
constructor() {
|
|
33
|
-
super({
|
|
34
|
-
ffmpegPath: "ffmpeg",
|
|
35
|
-
hwaccel: "none",
|
|
36
|
-
threads: 0,
|
|
37
|
-
segmentDurationSeconds: 4,
|
|
38
|
-
defaultRetentionDays: 30,
|
|
39
|
-
storageWarningThreshold: 80,
|
|
40
|
-
storageCriticalThreshold: 95,
|
|
41
|
-
storageHighUsageThreshold: 90,
|
|
42
|
-
retentionCheckIntervalMin: 5
|
|
43
|
-
});
|
|
44
|
-
}
|
|
45
|
-
setRecordingDependencies(deps) {
|
|
46
|
-
this.recordingDeps = deps;
|
|
47
|
-
}
|
|
48
|
-
async onInitialize() {
|
|
49
|
-
if (!this.recordingDeps) {
|
|
50
|
-
this.ctx.logger.info("Recording Engine: optional dependencies not wired — skipping init");
|
|
51
|
-
return;
|
|
52
|
-
}
|
|
53
|
-
try {
|
|
54
|
-
const Database = (await import("better-sqlite3")).default;
|
|
55
|
-
const path = await import("node:path");
|
|
56
|
-
const { detectPlatformDefaults } = await Promise.resolve().then(() => require("../ffmpeg-config-uANz3sV5.js"));
|
|
57
|
-
const { RecordingDb: RecDb } = await Promise.resolve().then(() => require("../recording-db-gOgaoQh0.js"));
|
|
58
|
-
const { RecordingCoordinator: RecCoord } = await Promise.resolve().then(() => require("../recording-coordinator-BoGr5moz.js"));
|
|
59
|
-
const storage = this.ctx.kernel.storage;
|
|
60
|
-
const dbPath = path.join(storage?.resolve({ location: "data", relativePath: "" }) ?? "camstack-data", "camstack.db");
|
|
61
|
-
this.sqliteDb = new Database(dbPath);
|
|
62
|
-
this.recordingDb = new RecDb(this.sqliteDb);
|
|
63
|
-
this.recordingDb.initialize();
|
|
64
|
-
const ffmpegPath = this.config.ffmpegPath;
|
|
65
|
-
const detectedFfmpegConfig = detectPlatformDefaults(ffmpegPath);
|
|
66
|
-
const globalFfmpegConfig = {
|
|
67
|
-
path: ffmpegPath,
|
|
68
|
-
hwaccel: this.config.hwaccel,
|
|
69
|
-
threads: this.config.threads
|
|
70
|
-
};
|
|
71
|
-
const segmentDurationSeconds = this.config.segmentDurationSeconds;
|
|
72
|
-
if (!storage) {
|
|
73
|
-
throw new Error("RecordingAddon: storage capability not available");
|
|
74
|
-
}
|
|
75
|
-
this.coordinator = new RecCoord({
|
|
76
|
-
db: this.recordingDb,
|
|
77
|
-
logger: this.ctx.logger,
|
|
78
|
-
eventBus: this.ctx.eventBus,
|
|
79
|
-
streamingEngine: this.recordingDeps.streamingEngine,
|
|
80
|
-
pipelineManager: this.recordingDeps.pipelineManager,
|
|
81
|
-
networkTracker: this.recordingDeps.networkTracker,
|
|
82
|
-
storageProvider: storage,
|
|
83
|
-
globalFfmpegConfig,
|
|
84
|
-
detectedFfmpegConfig,
|
|
85
|
-
segmentDurationSec: segmentDurationSeconds
|
|
86
|
-
});
|
|
87
|
-
await this.coordinator.start();
|
|
88
|
-
const { PlaylistGenerator } = await Promise.resolve().then(() => require("../playlist-generator-EhPaB7Hn.js"));
|
|
89
|
-
const { StorageEstimator } = await Promise.resolve().then(() => require("../storage-estimator-CRpoQc9j.js"));
|
|
90
|
-
const playlistGenerator = new PlaylistGenerator(this.recordingDb);
|
|
91
|
-
const storageEstimator = new StorageEstimator(this.recordingDb, this.recordingDeps.networkTracker);
|
|
92
|
-
const { RecordingServiceFacade } = await Promise.resolve().then(() => require("../recording-service-facade-Do1PKlAL.js"));
|
|
93
|
-
this.serviceFacade = new RecordingServiceFacade({
|
|
94
|
-
coordinator: this.coordinator,
|
|
95
|
-
db: this.recordingDb,
|
|
96
|
-
playlistGenerator,
|
|
97
|
-
storageEstimator
|
|
98
|
-
});
|
|
99
|
-
this.ctx.logger.info("Recording Engine initialized");
|
|
100
|
-
return [{ capability: index.recordingEngineCapability, provider: this.serviceFacade }];
|
|
101
|
-
} catch (error) {
|
|
102
|
-
const msg = index.errMsg(error);
|
|
103
|
-
this.ctx.logger.warn("Recording Engine failed to initialize", { meta: { error: msg } });
|
|
104
|
-
}
|
|
105
|
-
}
|
|
106
|
-
async onShutdown() {
|
|
107
|
-
if (this.coordinator) {
|
|
108
|
-
this.coordinator.stop();
|
|
109
|
-
this.coordinator = null;
|
|
110
|
-
}
|
|
111
|
-
if (this.sqliteDb) {
|
|
112
|
-
this.sqliteDb.close();
|
|
113
|
-
this.sqliteDb = null;
|
|
114
|
-
}
|
|
115
|
-
this.recordingDb = null;
|
|
116
|
-
}
|
|
117
|
-
// --- Recording engine accessors ---
|
|
118
|
-
getCoordinator() {
|
|
119
|
-
if (!this.coordinator) throw new Error("RecordingAddon: recording not initialized");
|
|
120
|
-
return this.coordinator;
|
|
121
|
-
}
|
|
122
|
-
getRecordingDb() {
|
|
123
|
-
if (!this.recordingDb) throw new Error("RecordingAddon: recording not initialized");
|
|
124
|
-
return this.recordingDb;
|
|
125
|
-
}
|
|
126
|
-
// --- Three-level settings API (Phase 3) ---
|
|
127
|
-
//
|
|
128
|
-
// Recording is post-detection infra. Until the dedicated post-detection
|
|
129
|
-
// UI exists, it exposes `getGlobalSettings` so the knobs surface under
|
|
130
|
-
// Cluster → Settings alongside other node-level infra.
|
|
131
|
-
globalSettingsSchema() {
|
|
132
|
-
return this.schema({
|
|
133
|
-
sections: [
|
|
134
|
-
{
|
|
135
|
-
id: "recording-general",
|
|
136
|
-
title: "Recording Settings",
|
|
137
|
-
columns: 2,
|
|
138
|
-
fields: [
|
|
139
|
-
{
|
|
140
|
-
type: "number",
|
|
141
|
-
key: "segmentDurationSeconds",
|
|
142
|
-
label: "Segment Duration",
|
|
143
|
-
description: "Duration of each recording segment",
|
|
144
|
-
min: 10,
|
|
145
|
-
max: 3600,
|
|
146
|
-
step: 10,
|
|
147
|
-
default: 300,
|
|
148
|
-
unit: "s"
|
|
149
|
-
},
|
|
150
|
-
{
|
|
151
|
-
type: "number",
|
|
152
|
-
key: "defaultRetentionDays",
|
|
153
|
-
label: "Retention",
|
|
154
|
-
description: "Days to keep recordings before automatic deletion",
|
|
155
|
-
min: 1,
|
|
156
|
-
max: 365,
|
|
157
|
-
step: 1,
|
|
158
|
-
default: 30,
|
|
159
|
-
unit: "days"
|
|
160
|
-
}
|
|
161
|
-
]
|
|
162
|
-
},
|
|
163
|
-
{
|
|
164
|
-
id: "recording-ffmpeg",
|
|
165
|
-
title: "FFmpeg",
|
|
166
|
-
columns: 3,
|
|
167
|
-
fields: [
|
|
168
|
-
{
|
|
169
|
-
type: "text",
|
|
170
|
-
key: "ffmpegPath",
|
|
171
|
-
label: "FFmpeg Path",
|
|
172
|
-
description: "Path to ffmpeg binary",
|
|
173
|
-
placeholder: "ffmpeg",
|
|
174
|
-
default: "ffmpeg"
|
|
175
|
-
},
|
|
176
|
-
{
|
|
177
|
-
type: "select",
|
|
178
|
-
key: "hwaccel",
|
|
179
|
-
label: "Hardware Acceleration",
|
|
180
|
-
options: [
|
|
181
|
-
{ value: "none", label: "None (CPU)" },
|
|
182
|
-
{ value: "vaapi", label: "VAAPI (Intel/AMD)" },
|
|
183
|
-
{ value: "cuda", label: "CUDA (NVIDIA)" },
|
|
184
|
-
{ value: "videotoolbox", label: "VideoToolbox (macOS)" }
|
|
185
|
-
]
|
|
186
|
-
},
|
|
187
|
-
{
|
|
188
|
-
type: "number",
|
|
189
|
-
key: "threads",
|
|
190
|
-
label: "Threads",
|
|
191
|
-
description: "FFmpeg encoding threads (0 = auto)",
|
|
192
|
-
min: 0,
|
|
193
|
-
max: 32,
|
|
194
|
-
step: 1,
|
|
195
|
-
default: 0
|
|
196
|
-
}
|
|
197
|
-
]
|
|
198
|
-
},
|
|
199
|
-
{
|
|
200
|
-
id: "recording-retention",
|
|
201
|
-
title: "Storage & Retention",
|
|
202
|
-
description: "Thresholds for storage usage alerts and retention enforcement frequency.",
|
|
203
|
-
columns: 2,
|
|
204
|
-
fields: [
|
|
205
|
-
{
|
|
206
|
-
type: "number",
|
|
207
|
-
key: "storageWarningThreshold",
|
|
208
|
-
label: "Warning Threshold",
|
|
209
|
-
description: "Storage usage percentage that triggers a warning event.",
|
|
210
|
-
min: 50,
|
|
211
|
-
max: 99,
|
|
212
|
-
step: 1,
|
|
213
|
-
default: 80,
|
|
214
|
-
unit: "%"
|
|
215
|
-
},
|
|
216
|
-
{
|
|
217
|
-
type: "number",
|
|
218
|
-
key: "storageCriticalThreshold",
|
|
219
|
-
label: "Critical Threshold",
|
|
220
|
-
description: "Storage usage percentage that triggers a critical event.",
|
|
221
|
-
min: 50,
|
|
222
|
-
max: 99,
|
|
223
|
-
step: 1,
|
|
224
|
-
default: 95,
|
|
225
|
-
unit: "%"
|
|
226
|
-
},
|
|
227
|
-
{
|
|
228
|
-
type: "number",
|
|
229
|
-
key: "storageHighUsageThreshold",
|
|
230
|
-
label: "High Usage Threshold",
|
|
231
|
-
description: "Storage usage percentage that increases retention check frequency.",
|
|
232
|
-
min: 50,
|
|
233
|
-
max: 99,
|
|
234
|
-
step: 1,
|
|
235
|
-
default: 90,
|
|
236
|
-
unit: "%"
|
|
237
|
-
},
|
|
238
|
-
{
|
|
239
|
-
type: "number",
|
|
240
|
-
key: "retentionCheckIntervalMin",
|
|
241
|
-
label: "Check Interval",
|
|
242
|
-
description: "Normal interval between retention cleanup cycles.",
|
|
243
|
-
min: 1,
|
|
244
|
-
max: 60,
|
|
245
|
-
step: 1,
|
|
246
|
-
default: 5,
|
|
247
|
-
unit: "min"
|
|
248
|
-
}
|
|
249
|
-
]
|
|
250
|
-
}
|
|
251
|
-
]
|
|
252
|
-
});
|
|
253
|
-
}
|
|
254
|
-
}
|
|
255
|
-
exports.RecordingAddon = RecordingAddon;
|
|
256
|
-
exports.default = RecordingAddon;
|
|
257
|
-
//# sourceMappingURL=index.js.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","sources":["../../src/recording/index.ts"],"sourcesContent":["import type {\n ProviderRegistration,\n FfmpegConfig,\n IStreamingEngine,\n IPipelineManager,\n INetworkQualityTracker,\n} from '@camstack/types'\nimport { BaseAddon, recordingEngineCapability, errMsg } from '@camstack/types'\n\n// Dynamic imports to avoid hard dep on better-sqlite3 at load time\ntype RecordingCoordinator = import('./recording/recording-coordinator.js').RecordingCoordinator\ntype RecordingDb = import('./recording/recording-db.js').RecordingDb\n\nexport interface RecordingEngineDependencies {\n readonly streamingEngine: IStreamingEngine\n readonly pipelineManager: IPipelineManager\n readonly networkTracker: INetworkQualityTracker\n}\n\ninterface RecordingConfig {\n ffmpegPath: string\n hwaccel: string\n threads: number\n segmentDurationSeconds: number\n defaultRetentionDays: number\n storageWarningThreshold: number\n storageCriticalThreshold: number\n storageHighUsageThreshold: number\n retentionCheckIntervalMin: number\n}\n\nexport class RecordingAddon extends BaseAddon<RecordingConfig> {\n private coordinator: RecordingCoordinator | null = null\n private recordingDb: RecordingDb | null = null\n private sqliteDb: import('better-sqlite3').Database | null = null\n private recordingDeps: RecordingEngineDependencies | null = null\n private serviceFacade: import('./recording-service-facade.js').RecordingServiceFacade | null = null\n\n constructor() {\n super({\n ffmpegPath: 'ffmpeg',\n hwaccel: 'none',\n threads: 0,\n segmentDurationSeconds: 4,\n defaultRetentionDays: 30,\n storageWarningThreshold: 80,\n storageCriticalThreshold: 95,\n storageHighUsageThreshold: 90,\n retentionCheckIntervalMin: 5,\n })\n }\n\n setRecordingDependencies(deps: RecordingEngineDependencies): void {\n this.recordingDeps = deps\n }\n\n protected async onInitialize(): Promise<ProviderRegistration[] | void> {\n if (!this.recordingDeps) {\n this.ctx.logger.info('Recording Engine: optional dependencies not wired — skipping init')\n return\n }\n\n try {\n const Database = (await import('better-sqlite3')).default\n const path = await import('node:path')\n const { detectPlatformDefaults } = await import('./recording/ffmpeg-config.js')\n const { RecordingDb: RecDb } = await import('./recording/recording-db.js')\n const { RecordingCoordinator: RecCoord } = await import('./recording/recording-coordinator.js')\n\n const storage = this.ctx.kernel.storage\n const dbPath = path.join(storage?.resolve({ location: 'data', relativePath: '' }) ?? 'camstack-data', 'camstack.db')\n this.sqliteDb = new Database(dbPath)\n this.recordingDb = new RecDb(this.sqliteDb)\n this.recordingDb.initialize()\n\n const ffmpegPath = this.config.ffmpegPath\n const detectedFfmpegConfig = detectPlatformDefaults(ffmpegPath)\n\n const globalFfmpegConfig: Partial<FfmpegConfig> = {\n path: ffmpegPath,\n hwaccel: this.config.hwaccel as FfmpegConfig['hwaccel'],\n threads: this.config.threads,\n }\n\n const segmentDurationSeconds = this.config.segmentDurationSeconds\n\n if (!storage) {\n throw new Error('RecordingAddon: storage capability not available')\n }\n\n this.coordinator = new RecCoord({\n db: this.recordingDb,\n logger: this.ctx.logger,\n eventBus: this.ctx.eventBus,\n streamingEngine: this.recordingDeps.streamingEngine,\n pipelineManager: this.recordingDeps.pipelineManager,\n networkTracker: this.recordingDeps.networkTracker,\n storageProvider: storage,\n globalFfmpegConfig,\n detectedFfmpegConfig,\n segmentDurationSec: segmentDurationSeconds,\n })\n await this.coordinator.start()\n\n // Create service facade wrapping all internal services.\n // The facade is the capability provider — the auto-generated cap router\n // dispatches typed tRPC procedures directly to facade methods.\n const { PlaylistGenerator } = await import('./recording/playlist-generator.js')\n const { StorageEstimator } = await import('./recording/storage-estimator.js')\n const playlistGenerator = new PlaylistGenerator(this.recordingDb)\n const storageEstimator = new StorageEstimator(this.recordingDb, this.recordingDeps.networkTracker)\n\n const { RecordingServiceFacade } = await import('./recording-service-facade.js')\n this.serviceFacade = new RecordingServiceFacade({\n coordinator: this.coordinator,\n db: this.recordingDb,\n playlistGenerator,\n storageEstimator,\n })\n this.ctx.logger.info('Recording Engine initialized')\n return [{ capability: recordingEngineCapability, provider: this.serviceFacade }]\n } catch (error: unknown) {\n const msg = errMsg(error)\n this.ctx.logger.warn('Recording Engine failed to initialize', { meta: { error: msg } })\n }\n }\n\n protected async onShutdown(): Promise<void> {\n if (this.coordinator) {\n this.coordinator.stop()\n this.coordinator = null\n }\n if (this.sqliteDb) {\n this.sqliteDb.close()\n this.sqliteDb = null\n }\n this.recordingDb = null\n }\n\n // --- Recording engine accessors ---\n\n getCoordinator(): RecordingCoordinator {\n if (!this.coordinator) throw new Error('RecordingAddon: recording not initialized')\n return this.coordinator\n }\n\n getRecordingDb(): RecordingDb {\n if (!this.recordingDb) throw new Error('RecordingAddon: recording not initialized')\n return this.recordingDb\n }\n\n // --- Three-level settings API (Phase 3) ---\n //\n // Recording is post-detection infra. Until the dedicated post-detection\n // UI exists, it exposes `getGlobalSettings` so the knobs surface under\n // Cluster → Settings alongside other node-level infra.\n\n protected globalSettingsSchema() {\n return this.schema({\n sections: [\n {\n id: 'recording-general',\n title: 'Recording Settings',\n columns: 2,\n fields: [\n {\n type: 'number',\n key: 'segmentDurationSeconds',\n label: 'Segment Duration',\n description: 'Duration of each recording segment',\n min: 10,\n max: 3600,\n step: 10,\n default: 300,\n unit: 's',\n },\n {\n type: 'number',\n key: 'defaultRetentionDays',\n label: 'Retention',\n description: 'Days to keep recordings before automatic deletion',\n min: 1,\n max: 365,\n step: 1,\n default: 30,\n unit: 'days',\n },\n ],\n },\n {\n id: 'recording-ffmpeg',\n title: 'FFmpeg',\n columns: 3,\n fields: [\n {\n type: 'text',\n key: 'ffmpegPath',\n label: 'FFmpeg Path',\n description: 'Path to ffmpeg binary',\n placeholder: 'ffmpeg',\n default: 'ffmpeg',\n },\n {\n type: 'select',\n key: 'hwaccel',\n label: 'Hardware Acceleration',\n options: [\n { value: 'none', label: 'None (CPU)' },\n { value: 'vaapi', label: 'VAAPI (Intel/AMD)' },\n { value: 'cuda', label: 'CUDA (NVIDIA)' },\n { value: 'videotoolbox', label: 'VideoToolbox (macOS)' },\n ],\n },\n {\n type: 'number',\n key: 'threads',\n label: 'Threads',\n description: 'FFmpeg encoding threads (0 = auto)',\n min: 0,\n max: 32,\n step: 1,\n default: 0,\n },\n ],\n },\n {\n id: 'recording-retention',\n title: 'Storage & Retention',\n description: 'Thresholds for storage usage alerts and retention enforcement frequency.',\n columns: 2,\n fields: [\n {\n type: 'number',\n key: 'storageWarningThreshold',\n label: 'Warning Threshold',\n description: 'Storage usage percentage that triggers a warning event.',\n min: 50, max: 99, step: 1, default: 80, unit: '%',\n },\n {\n type: 'number',\n key: 'storageCriticalThreshold',\n label: 'Critical Threshold',\n description: 'Storage usage percentage that triggers a critical event.',\n min: 50, max: 99, step: 1, default: 95, unit: '%',\n },\n {\n type: 'number',\n key: 'storageHighUsageThreshold',\n label: 'High Usage Threshold',\n description: 'Storage usage percentage that increases retention check frequency.',\n min: 50, max: 99, step: 1, default: 90, unit: '%',\n },\n {\n type: 'number',\n key: 'retentionCheckIntervalMin',\n label: 'Check Interval',\n description: 'Normal interval between retention cleanup cycles.',\n min: 1, max: 60, step: 1, default: 5, unit: 'min',\n },\n ],\n },\n ],\n })\n }\n\n}\n\nexport default RecordingAddon\n"],"names":["BaseAddon","recordingEngineCapability","errMsg"],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;AA+BO,MAAM,uBAAuBA,MAAAA,UAA2B;AAAA,EACrD,cAA2C;AAAA,EAC3C,cAAkC;AAAA,EAClC,WAAqD;AAAA,EACrD,gBAAoD;AAAA,EACpD,gBAAuF;AAAA,EAE/F,cAAc;AACZ,UAAM;AAAA,MACJ,YAAY;AAAA,MACZ,SAAS;AAAA,MACT,SAAS;AAAA,MACT,wBAAwB;AAAA,MACxB,sBAAsB;AAAA,MACtB,yBAAyB;AAAA,MACzB,0BAA0B;AAAA,MAC1B,2BAA2B;AAAA,MAC3B,2BAA2B;AAAA,IAAA,CAC5B;AAAA,EACH;AAAA,EAEA,yBAAyB,MAAyC;AAChE,SAAK,gBAAgB;AAAA,EACvB;AAAA,EAEA,MAAgB,eAAuD;AACrE,QAAI,CAAC,KAAK,eAAe;AACvB,WAAK,IAAI,OAAO,KAAK,mEAAmE;AACxF;AAAA,IACF;AAEA,QAAI;AACF,YAAM,YAAY,MAAM,OAAO,gBAAgB,GAAG;AAClD,YAAM,OAAO,MAAM,OAAO,WAAW;AACrC,YAAM,EAAE,uBAAA,IAA2B,MAAM,QAAA,QAAA,EAAA,KAAA,MAAA,QAAO,8BAA8B,CAAA;AAC9E,YAAM,EAAE,aAAa,UAAU,MAAM,QAAA,QAAA,EAAA,KAAA,MAAA,QAAO,6BAA6B,CAAA;AACzE,YAAM,EAAE,sBAAsB,aAAa,MAAM,QAAA,QAAA,EAAA,KAAA,MAAA,QAAO,sCAAsC,CAAA;AAE9F,YAAM,UAAU,KAAK,IAAI,OAAO;AAChC,YAAM,SAAS,KAAK,KAAK,SAAS,QAAQ,EAAE,UAAU,QAAQ,cAAc,GAAA,CAAI,KAAK,iBAAiB,aAAa;AACnH,WAAK,WAAW,IAAI,SAAS,MAAM;AACnC,WAAK,cAAc,IAAI,MAAM,KAAK,QAAQ;AAC1C,WAAK,YAAY,WAAA;AAEjB,YAAM,aAAa,KAAK,OAAO;AAC/B,YAAM,uBAAuB,uBAAuB,UAAU;AAE9D,YAAM,qBAA4C;AAAA,QAChD,MAAM;AAAA,QACN,SAAS,KAAK,OAAO;AAAA,QACrB,SAAS,KAAK,OAAO;AAAA,MAAA;AAGvB,YAAM,yBAAyB,KAAK,OAAO;AAE3C,UAAI,CAAC,SAAS;AACZ,cAAM,IAAI,MAAM,kDAAkD;AAAA,MACpE;AAEA,WAAK,cAAc,IAAI,SAAS;AAAA,QAC9B,IAAI,KAAK;AAAA,QACT,QAAQ,KAAK,IAAI;AAAA,QACjB,UAAU,KAAK,IAAI;AAAA,QACnB,iBAAiB,KAAK,cAAc;AAAA,QACpC,iBAAiB,KAAK,cAAc;AAAA,QACpC,gBAAgB,KAAK,cAAc;AAAA,QACnC,iBAAiB;AAAA,QACjB;AAAA,QACA;AAAA,QACA,oBAAoB;AAAA,MAAA,CACrB;AACD,YAAM,KAAK,YAAY,MAAA;AAKvB,YAAM,EAAE,kBAAA,IAAsB,MAAM,QAAA,QAAA,EAAA,KAAA,MAAA,QAAO,mCAAmC,CAAA;AAC9E,YAAM,EAAE,iBAAA,IAAqB,MAAM,QAAA,QAAA,EAAA,KAAA,MAAA,QAAO,kCAAkC,CAAA;AAC5E,YAAM,oBAAoB,IAAI,kBAAkB,KAAK,WAAW;AAChE,YAAM,mBAAmB,IAAI,iBAAiB,KAAK,aAAa,KAAK,cAAc,cAAc;AAEjG,YAAM,EAAE,uBAAA,IAA2B,MAAM,QAAA,QAAA,EAAA,KAAA,MAAA,QAAO,yCAA+B,CAAA;AAC/E,WAAK,gBAAgB,IAAI,uBAAuB;AAAA,QAC9C,aAAa,KAAK;AAAA,QAClB,IAAI,KAAK;AAAA,QACT;AAAA,QACA;AAAA,MAAA,CACD;AACD,WAAK,IAAI,OAAO,KAAK,8BAA8B;AACnD,aAAO,CAAC,EAAE,YAAYC,MAAAA,2BAA2B,UAAU,KAAK,eAAe;AAAA,IACjF,SAAS,OAAgB;AACvB,YAAM,MAAMC,MAAAA,OAAO,KAAK;AACxB,WAAK,IAAI,OAAO,KAAK,yCAAyC,EAAE,MAAM,EAAE,OAAO,IAAA,GAAO;AAAA,IACxF;AAAA,EACF;AAAA,EAEA,MAAgB,aAA4B;AAC1C,QAAI,KAAK,aAAa;AACpB,WAAK,YAAY,KAAA;AACjB,WAAK,cAAc;AAAA,IACrB;AACA,QAAI,KAAK,UAAU;AACjB,WAAK,SAAS,MAAA;AACd,WAAK,WAAW;AAAA,IAClB;AACA,SAAK,cAAc;AAAA,EACrB;AAAA;AAAA,EAIA,iBAAuC;AACrC,QAAI,CAAC,KAAK,YAAa,OAAM,IAAI,MAAM,2CAA2C;AAClF,WAAO,KAAK;AAAA,EACd;AAAA,EAEA,iBAA8B;AAC5B,QAAI,CAAC,KAAK,YAAa,OAAM,IAAI,MAAM,2CAA2C;AAClF,WAAO,KAAK;AAAA,EACd;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAQU,uBAAuB;AAC/B,WAAO,KAAK,OAAO;AAAA,MACjB,UAAU;AAAA,QACR;AAAA,UACE,IAAI;AAAA,UACJ,OAAO;AAAA,UACP,SAAS;AAAA,UACT,QAAQ;AAAA,YACN;AAAA,cACE,MAAM;AAAA,cACN,KAAK;AAAA,cACL,OAAO;AAAA,cACP,aAAa;AAAA,cACb,KAAK;AAAA,cACL,KAAK;AAAA,cACL,MAAM;AAAA,cACN,SAAS;AAAA,cACT,MAAM;AAAA,YAAA;AAAA,YAER;AAAA,cACE,MAAM;AAAA,cACN,KAAK;AAAA,cACL,OAAO;AAAA,cACP,aAAa;AAAA,cACb,KAAK;AAAA,cACL,KAAK;AAAA,cACL,MAAM;AAAA,cACN,SAAS;AAAA,cACT,MAAM;AAAA,YAAA;AAAA,UACR;AAAA,QACF;AAAA,QAEF;AAAA,UACE,IAAI;AAAA,UACJ,OAAO;AAAA,UACP,SAAS;AAAA,UACT,QAAQ;AAAA,YACN;AAAA,cACE,MAAM;AAAA,cACN,KAAK;AAAA,cACL,OAAO;AAAA,cACP,aAAa;AAAA,cACb,aAAa;AAAA,cACb,SAAS;AAAA,YAAA;AAAA,YAEX;AAAA,cACE,MAAM;AAAA,cACN,KAAK;AAAA,cACL,OAAO;AAAA,cACP,SAAS;AAAA,gBACP,EAAE,OAAO,QAAQ,OAAO,aAAA;AAAA,gBACxB,EAAE,OAAO,SAAS,OAAO,oBAAA;AAAA,gBACzB,EAAE,OAAO,QAAQ,OAAO,gBAAA;AAAA,gBACxB,EAAE,OAAO,gBAAgB,OAAO,uBAAA;AAAA,cAAuB;AAAA,YACzD;AAAA,YAEF;AAAA,cACE,MAAM;AAAA,cACN,KAAK;AAAA,cACL,OAAO;AAAA,cACP,aAAa;AAAA,cACb,KAAK;AAAA,cACL,KAAK;AAAA,cACL,MAAM;AAAA,cACN,SAAS;AAAA,YAAA;AAAA,UACX;AAAA,QACF;AAAA,QAEF;AAAA,UACE,IAAI;AAAA,UACJ,OAAO;AAAA,UACP,aAAa;AAAA,UACb,SAAS;AAAA,UACT,QAAQ;AAAA,YACN;AAAA,cACE,MAAM;AAAA,cACN,KAAK;AAAA,cACL,OAAO;AAAA,cACP,aAAa;AAAA,cACb,KAAK;AAAA,cAAI,KAAK;AAAA,cAAI,MAAM;AAAA,cAAG,SAAS;AAAA,cAAI,MAAM;AAAA,YAAA;AAAA,YAEhD;AAAA,cACE,MAAM;AAAA,cACN,KAAK;AAAA,cACL,OAAO;AAAA,cACP,aAAa;AAAA,cACb,KAAK;AAAA,cAAI,KAAK;AAAA,cAAI,MAAM;AAAA,cAAG,SAAS;AAAA,cAAI,MAAM;AAAA,YAAA;AAAA,YAEhD;AAAA,cACE,MAAM;AAAA,cACN,KAAK;AAAA,cACL,OAAO;AAAA,cACP,aAAa;AAAA,cACb,KAAK;AAAA,cAAI,KAAK;AAAA,cAAI,MAAM;AAAA,cAAG,SAAS;AAAA,cAAI,MAAM;AAAA,YAAA;AAAA,YAEhD;AAAA,cACE,MAAM;AAAA,cACN,KAAK;AAAA,cACL,OAAO;AAAA,cACP,aAAa;AAAA,cACb,KAAK;AAAA,cAAG,KAAK;AAAA,cAAI,MAAM;AAAA,cAAG,SAAS;AAAA,cAAG,MAAM;AAAA,YAAA;AAAA,UAC9C;AAAA,QACF;AAAA,MACF;AAAA,IACF,CACD;AAAA,EACH;AAEF;;;"}
|
package/dist/recording/index.mjs
DELETED
|
@@ -1,235 +0,0 @@
|
|
|
1
|
-
import { B as BaseAddon, r as recordingEngineCapability, e as errMsg } from "../index-BrTlzsrE.mjs";
|
|
2
|
-
class RecordingAddon extends BaseAddon {
|
|
3
|
-
coordinator = null;
|
|
4
|
-
recordingDb = null;
|
|
5
|
-
sqliteDb = null;
|
|
6
|
-
recordingDeps = null;
|
|
7
|
-
serviceFacade = null;
|
|
8
|
-
constructor() {
|
|
9
|
-
super({
|
|
10
|
-
ffmpegPath: "ffmpeg",
|
|
11
|
-
hwaccel: "none",
|
|
12
|
-
threads: 0,
|
|
13
|
-
segmentDurationSeconds: 4,
|
|
14
|
-
defaultRetentionDays: 30,
|
|
15
|
-
storageWarningThreshold: 80,
|
|
16
|
-
storageCriticalThreshold: 95,
|
|
17
|
-
storageHighUsageThreshold: 90,
|
|
18
|
-
retentionCheckIntervalMin: 5
|
|
19
|
-
});
|
|
20
|
-
}
|
|
21
|
-
setRecordingDependencies(deps) {
|
|
22
|
-
this.recordingDeps = deps;
|
|
23
|
-
}
|
|
24
|
-
async onInitialize() {
|
|
25
|
-
if (!this.recordingDeps) {
|
|
26
|
-
this.ctx.logger.info("Recording Engine: optional dependencies not wired — skipping init");
|
|
27
|
-
return;
|
|
28
|
-
}
|
|
29
|
-
try {
|
|
30
|
-
const Database = (await import("better-sqlite3")).default;
|
|
31
|
-
const path = await import("node:path");
|
|
32
|
-
const { detectPlatformDefaults } = await import("../ffmpeg-config-DRONlBsj.mjs");
|
|
33
|
-
const { RecordingDb: RecDb } = await import("../recording-db-lIkSMTLq.mjs");
|
|
34
|
-
const { RecordingCoordinator: RecCoord } = await import("../recording-coordinator-CsYH9LqF.mjs");
|
|
35
|
-
const storage = this.ctx.kernel.storage;
|
|
36
|
-
const dbPath = path.join(storage?.resolve({ location: "data", relativePath: "" }) ?? "camstack-data", "camstack.db");
|
|
37
|
-
this.sqliteDb = new Database(dbPath);
|
|
38
|
-
this.recordingDb = new RecDb(this.sqliteDb);
|
|
39
|
-
this.recordingDb.initialize();
|
|
40
|
-
const ffmpegPath = this.config.ffmpegPath;
|
|
41
|
-
const detectedFfmpegConfig = detectPlatformDefaults(ffmpegPath);
|
|
42
|
-
const globalFfmpegConfig = {
|
|
43
|
-
path: ffmpegPath,
|
|
44
|
-
hwaccel: this.config.hwaccel,
|
|
45
|
-
threads: this.config.threads
|
|
46
|
-
};
|
|
47
|
-
const segmentDurationSeconds = this.config.segmentDurationSeconds;
|
|
48
|
-
if (!storage) {
|
|
49
|
-
throw new Error("RecordingAddon: storage capability not available");
|
|
50
|
-
}
|
|
51
|
-
this.coordinator = new RecCoord({
|
|
52
|
-
db: this.recordingDb,
|
|
53
|
-
logger: this.ctx.logger,
|
|
54
|
-
eventBus: this.ctx.eventBus,
|
|
55
|
-
streamingEngine: this.recordingDeps.streamingEngine,
|
|
56
|
-
pipelineManager: this.recordingDeps.pipelineManager,
|
|
57
|
-
networkTracker: this.recordingDeps.networkTracker,
|
|
58
|
-
storageProvider: storage,
|
|
59
|
-
globalFfmpegConfig,
|
|
60
|
-
detectedFfmpegConfig,
|
|
61
|
-
segmentDurationSec: segmentDurationSeconds
|
|
62
|
-
});
|
|
63
|
-
await this.coordinator.start();
|
|
64
|
-
const { PlaylistGenerator } = await import("../playlist-generator-VTkgn53O.mjs");
|
|
65
|
-
const { StorageEstimator } = await import("../storage-estimator-DzD8gWJH.mjs");
|
|
66
|
-
const playlistGenerator = new PlaylistGenerator(this.recordingDb);
|
|
67
|
-
const storageEstimator = new StorageEstimator(this.recordingDb, this.recordingDeps.networkTracker);
|
|
68
|
-
const { RecordingServiceFacade } = await import("../recording-service-facade-B9lG6OFn.mjs");
|
|
69
|
-
this.serviceFacade = new RecordingServiceFacade({
|
|
70
|
-
coordinator: this.coordinator,
|
|
71
|
-
db: this.recordingDb,
|
|
72
|
-
playlistGenerator,
|
|
73
|
-
storageEstimator
|
|
74
|
-
});
|
|
75
|
-
this.ctx.logger.info("Recording Engine initialized");
|
|
76
|
-
return [{ capability: recordingEngineCapability, provider: this.serviceFacade }];
|
|
77
|
-
} catch (error) {
|
|
78
|
-
const msg = errMsg(error);
|
|
79
|
-
this.ctx.logger.warn("Recording Engine failed to initialize", { meta: { error: msg } });
|
|
80
|
-
}
|
|
81
|
-
}
|
|
82
|
-
async onShutdown() {
|
|
83
|
-
if (this.coordinator) {
|
|
84
|
-
this.coordinator.stop();
|
|
85
|
-
this.coordinator = null;
|
|
86
|
-
}
|
|
87
|
-
if (this.sqliteDb) {
|
|
88
|
-
this.sqliteDb.close();
|
|
89
|
-
this.sqliteDb = null;
|
|
90
|
-
}
|
|
91
|
-
this.recordingDb = null;
|
|
92
|
-
}
|
|
93
|
-
// --- Recording engine accessors ---
|
|
94
|
-
getCoordinator() {
|
|
95
|
-
if (!this.coordinator) throw new Error("RecordingAddon: recording not initialized");
|
|
96
|
-
return this.coordinator;
|
|
97
|
-
}
|
|
98
|
-
getRecordingDb() {
|
|
99
|
-
if (!this.recordingDb) throw new Error("RecordingAddon: recording not initialized");
|
|
100
|
-
return this.recordingDb;
|
|
101
|
-
}
|
|
102
|
-
// --- Three-level settings API (Phase 3) ---
|
|
103
|
-
//
|
|
104
|
-
// Recording is post-detection infra. Until the dedicated post-detection
|
|
105
|
-
// UI exists, it exposes `getGlobalSettings` so the knobs surface under
|
|
106
|
-
// Cluster → Settings alongside other node-level infra.
|
|
107
|
-
globalSettingsSchema() {
|
|
108
|
-
return this.schema({
|
|
109
|
-
sections: [
|
|
110
|
-
{
|
|
111
|
-
id: "recording-general",
|
|
112
|
-
title: "Recording Settings",
|
|
113
|
-
columns: 2,
|
|
114
|
-
fields: [
|
|
115
|
-
{
|
|
116
|
-
type: "number",
|
|
117
|
-
key: "segmentDurationSeconds",
|
|
118
|
-
label: "Segment Duration",
|
|
119
|
-
description: "Duration of each recording segment",
|
|
120
|
-
min: 10,
|
|
121
|
-
max: 3600,
|
|
122
|
-
step: 10,
|
|
123
|
-
default: 300,
|
|
124
|
-
unit: "s"
|
|
125
|
-
},
|
|
126
|
-
{
|
|
127
|
-
type: "number",
|
|
128
|
-
key: "defaultRetentionDays",
|
|
129
|
-
label: "Retention",
|
|
130
|
-
description: "Days to keep recordings before automatic deletion",
|
|
131
|
-
min: 1,
|
|
132
|
-
max: 365,
|
|
133
|
-
step: 1,
|
|
134
|
-
default: 30,
|
|
135
|
-
unit: "days"
|
|
136
|
-
}
|
|
137
|
-
]
|
|
138
|
-
},
|
|
139
|
-
{
|
|
140
|
-
id: "recording-ffmpeg",
|
|
141
|
-
title: "FFmpeg",
|
|
142
|
-
columns: 3,
|
|
143
|
-
fields: [
|
|
144
|
-
{
|
|
145
|
-
type: "text",
|
|
146
|
-
key: "ffmpegPath",
|
|
147
|
-
label: "FFmpeg Path",
|
|
148
|
-
description: "Path to ffmpeg binary",
|
|
149
|
-
placeholder: "ffmpeg",
|
|
150
|
-
default: "ffmpeg"
|
|
151
|
-
},
|
|
152
|
-
{
|
|
153
|
-
type: "select",
|
|
154
|
-
key: "hwaccel",
|
|
155
|
-
label: "Hardware Acceleration",
|
|
156
|
-
options: [
|
|
157
|
-
{ value: "none", label: "None (CPU)" },
|
|
158
|
-
{ value: "vaapi", label: "VAAPI (Intel/AMD)" },
|
|
159
|
-
{ value: "cuda", label: "CUDA (NVIDIA)" },
|
|
160
|
-
{ value: "videotoolbox", label: "VideoToolbox (macOS)" }
|
|
161
|
-
]
|
|
162
|
-
},
|
|
163
|
-
{
|
|
164
|
-
type: "number",
|
|
165
|
-
key: "threads",
|
|
166
|
-
label: "Threads",
|
|
167
|
-
description: "FFmpeg encoding threads (0 = auto)",
|
|
168
|
-
min: 0,
|
|
169
|
-
max: 32,
|
|
170
|
-
step: 1,
|
|
171
|
-
default: 0
|
|
172
|
-
}
|
|
173
|
-
]
|
|
174
|
-
},
|
|
175
|
-
{
|
|
176
|
-
id: "recording-retention",
|
|
177
|
-
title: "Storage & Retention",
|
|
178
|
-
description: "Thresholds for storage usage alerts and retention enforcement frequency.",
|
|
179
|
-
columns: 2,
|
|
180
|
-
fields: [
|
|
181
|
-
{
|
|
182
|
-
type: "number",
|
|
183
|
-
key: "storageWarningThreshold",
|
|
184
|
-
label: "Warning Threshold",
|
|
185
|
-
description: "Storage usage percentage that triggers a warning event.",
|
|
186
|
-
min: 50,
|
|
187
|
-
max: 99,
|
|
188
|
-
step: 1,
|
|
189
|
-
default: 80,
|
|
190
|
-
unit: "%"
|
|
191
|
-
},
|
|
192
|
-
{
|
|
193
|
-
type: "number",
|
|
194
|
-
key: "storageCriticalThreshold",
|
|
195
|
-
label: "Critical Threshold",
|
|
196
|
-
description: "Storage usage percentage that triggers a critical event.",
|
|
197
|
-
min: 50,
|
|
198
|
-
max: 99,
|
|
199
|
-
step: 1,
|
|
200
|
-
default: 95,
|
|
201
|
-
unit: "%"
|
|
202
|
-
},
|
|
203
|
-
{
|
|
204
|
-
type: "number",
|
|
205
|
-
key: "storageHighUsageThreshold",
|
|
206
|
-
label: "High Usage Threshold",
|
|
207
|
-
description: "Storage usage percentage that increases retention check frequency.",
|
|
208
|
-
min: 50,
|
|
209
|
-
max: 99,
|
|
210
|
-
step: 1,
|
|
211
|
-
default: 90,
|
|
212
|
-
unit: "%"
|
|
213
|
-
},
|
|
214
|
-
{
|
|
215
|
-
type: "number",
|
|
216
|
-
key: "retentionCheckIntervalMin",
|
|
217
|
-
label: "Check Interval",
|
|
218
|
-
description: "Normal interval between retention cleanup cycles.",
|
|
219
|
-
min: 1,
|
|
220
|
-
max: 60,
|
|
221
|
-
step: 1,
|
|
222
|
-
default: 5,
|
|
223
|
-
unit: "min"
|
|
224
|
-
}
|
|
225
|
-
]
|
|
226
|
-
}
|
|
227
|
-
]
|
|
228
|
-
});
|
|
229
|
-
}
|
|
230
|
-
}
|
|
231
|
-
export {
|
|
232
|
-
RecordingAddon,
|
|
233
|
-
RecordingAddon as default
|
|
234
|
-
};
|
|
235
|
-
//# sourceMappingURL=index.mjs.map
|