@camstack/addon-pipeline 0.1.0 → 0.1.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/dist/{addon-CwDFZWAb.d.cts → addon-DK7eQ0PN.d.cts} +3 -4
- package/dist/{addon-CwDFZWAb.d.ts → addon-DK7eQ0PN.d.ts} +3 -4
- package/dist/addon.cjs +27 -72
- package/dist/addon.cjs.map +1 -1
- package/dist/addon.d.cts +1 -1
- package/dist/addon.d.ts +1 -1
- package/dist/addon.js +27 -72
- package/dist/addon.js.map +1 -1
- package/dist/index.cjs +29 -3304
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +4 -921
- package/dist/index.d.ts +4 -921
- package/dist/index.js +28 -3271
- package/dist/index.js.map +1 -1
- package/package.json +34 -17
|
@@ -173,6 +173,8 @@ interface RecordingCoordinatorConfig {
|
|
|
173
173
|
readonly storagePath: string;
|
|
174
174
|
readonly globalFfmpegConfig: Partial<FfmpegConfig>;
|
|
175
175
|
readonly detectedFfmpegConfig: Partial<FfmpegConfig>;
|
|
176
|
+
/** Global segment duration from system settings (recording.segmentDurationSeconds). */
|
|
177
|
+
readonly segmentDurationSec?: number;
|
|
176
178
|
}
|
|
177
179
|
declare class RecordingCoordinator$1 {
|
|
178
180
|
private readonly db;
|
|
@@ -185,6 +187,7 @@ declare class RecordingCoordinator$1 {
|
|
|
185
187
|
private readonly storagePath;
|
|
186
188
|
private readonly globalFfmpegConfig;
|
|
187
189
|
private readonly detectedFfmpegConfig;
|
|
190
|
+
private readonly segmentDurationSec;
|
|
188
191
|
private readonly recordings;
|
|
189
192
|
private policyTimer;
|
|
190
193
|
private readonly retentionManager;
|
|
@@ -219,8 +222,6 @@ declare class PipelineAddon implements ICamstackAddon, IConfigurable {
|
|
|
219
222
|
private sqliteDb;
|
|
220
223
|
private recordingDeps;
|
|
221
224
|
private currentRecordingConfig;
|
|
222
|
-
private analysisPipeline;
|
|
223
|
-
private analysisLogger;
|
|
224
225
|
private persistenceFacade;
|
|
225
226
|
setRecordingDependencies(deps: RecordingEngineDependencies): void;
|
|
226
227
|
initialize(context: AddonContext): Promise<void>;
|
|
@@ -228,8 +229,6 @@ declare class PipelineAddon implements ICamstackAddon, IConfigurable {
|
|
|
228
229
|
getCapabilityProvider<K extends keyof CapabilityProviderMap>(name: K): CapabilityProviderMap[K] | null;
|
|
229
230
|
getCoordinator(): RecordingCoordinator;
|
|
230
231
|
getRecordingDb(): RecordingDb;
|
|
231
|
-
/** Whether the analysis pipeline package loaded successfully */
|
|
232
|
-
isAnalysisAvailable(): boolean;
|
|
233
232
|
getConfigSchema(): ConfigUISchema;
|
|
234
233
|
getConfig(): Record<string, unknown>;
|
|
235
234
|
onConfigChange(config: Record<string, unknown>): Promise<void>;
|
|
@@ -173,6 +173,8 @@ interface RecordingCoordinatorConfig {
|
|
|
173
173
|
readonly storagePath: string;
|
|
174
174
|
readonly globalFfmpegConfig: Partial<FfmpegConfig>;
|
|
175
175
|
readonly detectedFfmpegConfig: Partial<FfmpegConfig>;
|
|
176
|
+
/** Global segment duration from system settings (recording.segmentDurationSeconds). */
|
|
177
|
+
readonly segmentDurationSec?: number;
|
|
176
178
|
}
|
|
177
179
|
declare class RecordingCoordinator$1 {
|
|
178
180
|
private readonly db;
|
|
@@ -185,6 +187,7 @@ declare class RecordingCoordinator$1 {
|
|
|
185
187
|
private readonly storagePath;
|
|
186
188
|
private readonly globalFfmpegConfig;
|
|
187
189
|
private readonly detectedFfmpegConfig;
|
|
190
|
+
private readonly segmentDurationSec;
|
|
188
191
|
private readonly recordings;
|
|
189
192
|
private policyTimer;
|
|
190
193
|
private readonly retentionManager;
|
|
@@ -219,8 +222,6 @@ declare class PipelineAddon implements ICamstackAddon, IConfigurable {
|
|
|
219
222
|
private sqliteDb;
|
|
220
223
|
private recordingDeps;
|
|
221
224
|
private currentRecordingConfig;
|
|
222
|
-
private analysisPipeline;
|
|
223
|
-
private analysisLogger;
|
|
224
225
|
private persistenceFacade;
|
|
225
226
|
setRecordingDependencies(deps: RecordingEngineDependencies): void;
|
|
226
227
|
initialize(context: AddonContext): Promise<void>;
|
|
@@ -228,8 +229,6 @@ declare class PipelineAddon implements ICamstackAddon, IConfigurable {
|
|
|
228
229
|
getCapabilityProvider<K extends keyof CapabilityProviderMap>(name: K): CapabilityProviderMap[K] | null;
|
|
229
230
|
getCoordinator(): RecordingCoordinator;
|
|
230
231
|
getRecordingDb(): RecordingDb;
|
|
231
|
-
/** Whether the analysis pipeline package loaded successfully */
|
|
232
|
-
isAnalysisAvailable(): boolean;
|
|
233
232
|
getConfigSchema(): ConfigUISchema;
|
|
234
233
|
getConfig(): Record<string, unknown>;
|
|
235
234
|
onConfigChange(config: Record<string, unknown>): Promise<void>;
|
package/dist/addon.cjs
CHANGED
|
@@ -36,6 +36,7 @@ __export(ffmpeg_config_exports, {
|
|
|
36
36
|
buildFfmpegInputArgs: () => buildFfmpegInputArgs,
|
|
37
37
|
buildFfmpegOutputArgs: () => buildFfmpegOutputArgs,
|
|
38
38
|
detectPlatformDefaults: () => detectPlatformDefaults,
|
|
39
|
+
resolveFfmpegBinary: () => resolveFfmpegBinary,
|
|
39
40
|
resolveFfmpegConfig: () => resolveFfmpegConfig
|
|
40
41
|
});
|
|
41
42
|
function detectPlatformDefaults(ffmpegPath = "ffmpeg") {
|
|
@@ -78,6 +79,12 @@ function buildFfmpegOutputArgs(config) {
|
|
|
78
79
|
if (config.outputArgs?.length) args.push(...config.outputArgs);
|
|
79
80
|
return args;
|
|
80
81
|
}
|
|
82
|
+
async function resolveFfmpegBinary(configPath, deps) {
|
|
83
|
+
if (configPath && configPath !== "ffmpeg") {
|
|
84
|
+
return configPath;
|
|
85
|
+
}
|
|
86
|
+
return deps.ensureFfmpeg();
|
|
87
|
+
}
|
|
81
88
|
var import_node_child_process3, os;
|
|
82
89
|
var init_ffmpeg_config = __esm({
|
|
83
90
|
"src/recording/ffmpeg-config.ts"() {
|
|
@@ -1189,7 +1196,7 @@ var recording_coordinator_exports = {};
|
|
|
1189
1196
|
__export(recording_coordinator_exports, {
|
|
1190
1197
|
RecordingCoordinator: () => RecordingCoordinator
|
|
1191
1198
|
});
|
|
1192
|
-
var POLICY_EVAL_INTERVAL_MS, MOTION_FALLBACK_TIMEOUT_MS, RecordingCoordinator;
|
|
1199
|
+
var DEFAULT_SEGMENT_DURATION_SEC, POLICY_EVAL_INTERVAL_MS, MOTION_FALLBACK_TIMEOUT_MS, RecordingCoordinator;
|
|
1193
1200
|
var init_recording_coordinator = __esm({
|
|
1194
1201
|
"src/recording/recording-coordinator.ts"() {
|
|
1195
1202
|
"use strict";
|
|
@@ -1199,6 +1206,7 @@ var init_recording_coordinator = __esm({
|
|
|
1199
1206
|
init_retention_manager();
|
|
1200
1207
|
init_playlist_generator();
|
|
1201
1208
|
init_storage_estimator();
|
|
1209
|
+
DEFAULT_SEGMENT_DURATION_SEC = 4;
|
|
1202
1210
|
POLICY_EVAL_INTERVAL_MS = 1e3;
|
|
1203
1211
|
MOTION_FALLBACK_TIMEOUT_MS = 6e4;
|
|
1204
1212
|
RecordingCoordinator = class _RecordingCoordinator {
|
|
@@ -1212,6 +1220,7 @@ var init_recording_coordinator = __esm({
|
|
|
1212
1220
|
storagePath;
|
|
1213
1221
|
globalFfmpegConfig;
|
|
1214
1222
|
detectedFfmpegConfig;
|
|
1223
|
+
segmentDurationSec;
|
|
1215
1224
|
recordings = /* @__PURE__ */ new Map();
|
|
1216
1225
|
policyTimer = null;
|
|
1217
1226
|
retentionManager;
|
|
@@ -1228,6 +1237,7 @@ var init_recording_coordinator = __esm({
|
|
|
1228
1237
|
this.storagePath = config.storagePath;
|
|
1229
1238
|
this.globalFfmpegConfig = config.globalFfmpegConfig;
|
|
1230
1239
|
this.detectedFfmpegConfig = config.detectedFfmpegConfig;
|
|
1240
|
+
this.segmentDurationSec = config.segmentDurationSec ?? DEFAULT_SEGMENT_DURATION_SEC;
|
|
1231
1241
|
this.retentionManager = new RetentionManager(
|
|
1232
1242
|
this.db,
|
|
1233
1243
|
this.logger.child("retention"),
|
|
@@ -1313,7 +1323,7 @@ var init_recording_coordinator = __esm({
|
|
|
1313
1323
|
const writerConfig = {
|
|
1314
1324
|
deviceId,
|
|
1315
1325
|
streamId: sp.streamId,
|
|
1316
|
-
segmentDurationSec:
|
|
1326
|
+
segmentDurationSec: this.segmentDurationSec,
|
|
1317
1327
|
storagePath: this.storagePath,
|
|
1318
1328
|
storageName,
|
|
1319
1329
|
subDirectory,
|
|
@@ -3166,9 +3176,7 @@ var PipelineAddon = class {
|
|
|
3166
3176
|
capabilities: [
|
|
3167
3177
|
{ name: "stream-broker", mode: "singleton" },
|
|
3168
3178
|
{ name: "recording-engine", mode: "singleton" },
|
|
3169
|
-
{ name: "analysis-
|
|
3170
|
-
{ name: "analysis-data-persistence", mode: "singleton" },
|
|
3171
|
-
{ name: "webrtc", mode: "collection" }
|
|
3179
|
+
{ name: "analysis-data-persistence", mode: "singleton" }
|
|
3172
3180
|
]
|
|
3173
3181
|
};
|
|
3174
3182
|
// Stream broker
|
|
@@ -3181,11 +3189,10 @@ var PipelineAddon = class {
|
|
|
3181
3189
|
currentRecordingConfig = {
|
|
3182
3190
|
ffmpegPath: "ffmpeg",
|
|
3183
3191
|
hwaccel: void 0,
|
|
3184
|
-
threads: void 0
|
|
3192
|
+
threads: void 0,
|
|
3193
|
+
segmentDurationSeconds: 4,
|
|
3194
|
+
defaultRetentionDays: 30
|
|
3185
3195
|
};
|
|
3186
|
-
// Analysis pipeline
|
|
3187
|
-
analysisPipeline = null;
|
|
3188
|
-
analysisLogger = null;
|
|
3189
3196
|
// Analysis persistence
|
|
3190
3197
|
persistenceFacade = null;
|
|
3191
3198
|
setRecordingDependencies(deps) {
|
|
@@ -3215,10 +3222,14 @@ var PipelineAddon = class {
|
|
|
3215
3222
|
hwaccel: context.addonConfig.hwaccel ?? this.currentRecordingConfig.hwaccel,
|
|
3216
3223
|
threads: context.addonConfig.threads ?? this.currentRecordingConfig.threads
|
|
3217
3224
|
};
|
|
3225
|
+
const segmentDurationSeconds = context.addonConfig.segmentDurationSeconds ?? this.currentRecordingConfig.segmentDurationSeconds;
|
|
3226
|
+
const defaultRetentionDays = context.addonConfig.defaultRetentionDays ?? this.currentRecordingConfig.defaultRetentionDays;
|
|
3218
3227
|
this.currentRecordingConfig = {
|
|
3219
3228
|
ffmpegPath,
|
|
3220
3229
|
hwaccel: globalFfmpegConfig.hwaccel,
|
|
3221
|
-
threads: globalFfmpegConfig.threads
|
|
3230
|
+
threads: globalFfmpegConfig.threads,
|
|
3231
|
+
segmentDurationSeconds,
|
|
3232
|
+
defaultRetentionDays
|
|
3222
3233
|
};
|
|
3223
3234
|
const fileStorage = context.storage.files;
|
|
3224
3235
|
if (!fileStorage) {
|
|
@@ -3234,7 +3245,8 @@ var PipelineAddon = class {
|
|
|
3234
3245
|
fileStorage,
|
|
3235
3246
|
storagePath,
|
|
3236
3247
|
globalFfmpegConfig,
|
|
3237
|
-
detectedFfmpegConfig
|
|
3248
|
+
detectedFfmpegConfig,
|
|
3249
|
+
segmentDurationSec: segmentDurationSeconds
|
|
3238
3250
|
});
|
|
3239
3251
|
await this.coordinator.start();
|
|
3240
3252
|
context.logger.info("Recording Engine initialized");
|
|
@@ -3243,16 +3255,6 @@ var PipelineAddon = class {
|
|
|
3243
3255
|
context.logger.warn(`Recording Engine failed to initialize: ${msg}`);
|
|
3244
3256
|
}
|
|
3245
3257
|
}
|
|
3246
|
-
this.analysisLogger = context.logger;
|
|
3247
|
-
try {
|
|
3248
|
-
const mod = await import("@camstack/lib-pipeline-analysis");
|
|
3249
|
-
const instance = new mod.AnalysisPipeline();
|
|
3250
|
-
this.analysisPipeline = instance;
|
|
3251
|
-
this.analysisLogger.info("Analysis pipeline loaded successfully");
|
|
3252
|
-
} catch (error) {
|
|
3253
|
-
const msg = error instanceof Error ? error.message : String(error);
|
|
3254
|
-
this.analysisLogger.warn(`Analysis pipeline not available: ${msg} -- analysis features disabled`);
|
|
3255
|
-
}
|
|
3256
3258
|
const eventPersistence = new EventPersistenceService({
|
|
3257
3259
|
getStorageLocation: () => context.storage,
|
|
3258
3260
|
subscribe: (filter, handler) => context.eventBus.subscribe(filter, handler),
|
|
@@ -3304,7 +3306,6 @@ var PipelineAddon = class {
|
|
|
3304
3306
|
this.sqliteDb = null;
|
|
3305
3307
|
}
|
|
3306
3308
|
this.recordingDb = null;
|
|
3307
|
-
this.analysisPipeline = null;
|
|
3308
3309
|
if (this.persistenceFacade) {
|
|
3309
3310
|
this.persistenceFacade.eventPersistence.stop();
|
|
3310
3311
|
this.persistenceFacade.retention.stop();
|
|
@@ -3317,13 +3318,8 @@ var PipelineAddon = class {
|
|
|
3317
3318
|
return this.brokerManager;
|
|
3318
3319
|
case "recording-engine":
|
|
3319
3320
|
return this.coordinator;
|
|
3320
|
-
case "analysis-pipeline":
|
|
3321
|
-
return this.analysisPipeline;
|
|
3322
3321
|
case "analysis-data-persistence":
|
|
3323
3322
|
return this.persistenceFacade;
|
|
3324
|
-
case "webrtc":
|
|
3325
|
-
return null;
|
|
3326
|
-
// WebRTC is provided externally or via collection
|
|
3327
3323
|
default:
|
|
3328
3324
|
return null;
|
|
3329
3325
|
}
|
|
@@ -3337,52 +3333,9 @@ var PipelineAddon = class {
|
|
|
3337
3333
|
if (!this.recordingDb) throw new Error("PipelineAddon recording not initialized");
|
|
3338
3334
|
return this.recordingDb;
|
|
3339
3335
|
}
|
|
3340
|
-
/** Whether the analysis pipeline package loaded successfully */
|
|
3341
|
-
isAnalysisAvailable() {
|
|
3342
|
-
return this.analysisPipeline !== null;
|
|
3343
|
-
}
|
|
3344
3336
|
// --- IConfigurable ---
|
|
3345
3337
|
getConfigSchema() {
|
|
3346
|
-
return {
|
|
3347
|
-
sections: [
|
|
3348
|
-
{
|
|
3349
|
-
id: "ffmpeg",
|
|
3350
|
-
title: "FFmpeg Settings",
|
|
3351
|
-
columns: 2,
|
|
3352
|
-
fields: [
|
|
3353
|
-
{
|
|
3354
|
-
type: "text",
|
|
3355
|
-
key: "ffmpegPath",
|
|
3356
|
-
label: "FFmpeg Binary Path",
|
|
3357
|
-
description: 'Path to the ffmpeg executable, or just "ffmpeg" if it is in your PATH',
|
|
3358
|
-
placeholder: "ffmpeg"
|
|
3359
|
-
},
|
|
3360
|
-
{
|
|
3361
|
-
type: "select",
|
|
3362
|
-
key: "hwaccel",
|
|
3363
|
-
label: "Hardware Acceleration",
|
|
3364
|
-
description: "Enable GPU-accelerated video encoding if supported by your hardware",
|
|
3365
|
-
options: [
|
|
3366
|
-
{ value: "", label: "None (software)", description: "CPU-only encoding" },
|
|
3367
|
-
{ value: "nvenc", label: "NVIDIA NVENC", description: "NVIDIA GPU encoding" },
|
|
3368
|
-
{ value: "vaapi", label: "Intel VAAPI", description: "Intel GPU encoding (Linux)" },
|
|
3369
|
-
{ value: "videotoolbox", label: "Apple VideoToolbox", description: "macOS hardware encoding" }
|
|
3370
|
-
]
|
|
3371
|
-
},
|
|
3372
|
-
{
|
|
3373
|
-
type: "number",
|
|
3374
|
-
key: "threads",
|
|
3375
|
-
label: "FFmpeg Threads",
|
|
3376
|
-
description: "Number of CPU threads for software encoding (0 = auto)",
|
|
3377
|
-
min: 0,
|
|
3378
|
-
max: 64,
|
|
3379
|
-
step: 1,
|
|
3380
|
-
unit: "threads"
|
|
3381
|
-
}
|
|
3382
|
-
]
|
|
3383
|
-
}
|
|
3384
|
-
]
|
|
3385
|
-
};
|
|
3338
|
+
return { sections: [] };
|
|
3386
3339
|
}
|
|
3387
3340
|
getConfig() {
|
|
3388
3341
|
return { ...this.currentRecordingConfig };
|
|
@@ -3391,7 +3344,9 @@ var PipelineAddon = class {
|
|
|
3391
3344
|
this.currentRecordingConfig = {
|
|
3392
3345
|
ffmpegPath: config.ffmpegPath ?? this.currentRecordingConfig.ffmpegPath,
|
|
3393
3346
|
hwaccel: config.hwaccel ?? this.currentRecordingConfig.hwaccel,
|
|
3394
|
-
threads: config.threads ?? this.currentRecordingConfig.threads
|
|
3347
|
+
threads: config.threads ?? this.currentRecordingConfig.threads,
|
|
3348
|
+
segmentDurationSeconds: config.segmentDurationSeconds ?? this.currentRecordingConfig.segmentDurationSeconds,
|
|
3349
|
+
defaultRetentionDays: config.defaultRetentionDays ?? this.currentRecordingConfig.defaultRetentionDays
|
|
3395
3350
|
};
|
|
3396
3351
|
}
|
|
3397
3352
|
};
|