@camstack/addon-pipeline 0.1.0 → 0.1.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/addon.d.cts CHANGED
@@ -1,3 +1,3 @@
1
- export { P as PipelineAddon, d as RecordingEngineDependencies, e as RecordingEngineV2Dependencies, P as default } from './addon-CwDFZWAb.cjs';
1
+ export { P as PipelineAddon, d as RecordingEngineDependencies, e as RecordingEngineV2Dependencies, P as default } from './addon-DK7eQ0PN.cjs';
2
2
  import '@camstack/types';
3
3
  import 'better-sqlite3';
package/dist/addon.d.ts CHANGED
@@ -1,3 +1,3 @@
1
- export { P as PipelineAddon, d as RecordingEngineDependencies, e as RecordingEngineV2Dependencies, P as default } from './addon-CwDFZWAb.js';
1
+ export { P as PipelineAddon, d as RecordingEngineDependencies, e as RecordingEngineV2Dependencies, P as default } from './addon-DK7eQ0PN.js';
2
2
  import '@camstack/types';
3
3
  import 'better-sqlite3';
package/dist/addon.js CHANGED
@@ -14,10 +14,12 @@ __export(ffmpeg_config_exports, {
14
14
  buildFfmpegInputArgs: () => buildFfmpegInputArgs,
15
15
  buildFfmpegOutputArgs: () => buildFfmpegOutputArgs,
16
16
  detectPlatformDefaults: () => detectPlatformDefaults,
17
+ resolveFfmpegBinary: () => resolveFfmpegBinary,
17
18
  resolveFfmpegConfig: () => resolveFfmpegConfig
18
19
  });
19
20
  import { execFileSync } from "child_process";
20
21
  import * as os from "os";
22
+ import { ensureFfmpeg } from "@camstack/core";
21
23
  function detectPlatformDefaults(ffmpegPath = "ffmpeg") {
22
24
  let hwaccels = [];
23
25
  try {
@@ -58,6 +60,12 @@ function buildFfmpegOutputArgs(config) {
58
60
  if (config.outputArgs?.length) args.push(...config.outputArgs);
59
61
  return args;
60
62
  }
63
+ async function resolveFfmpegBinary(configPath, dataDir, logger) {
64
+ if (configPath && configPath !== "ffmpeg") {
65
+ return configPath;
66
+ }
67
+ return ensureFfmpeg(dataDir, logger);
68
+ }
61
69
  var init_ffmpeg_config = __esm({
62
70
  "src/recording/ffmpeg-config.ts"() {
63
71
  "use strict";
@@ -1166,7 +1174,7 @@ var recording_coordinator_exports = {};
1166
1174
  __export(recording_coordinator_exports, {
1167
1175
  RecordingCoordinator: () => RecordingCoordinator
1168
1176
  });
1169
- var POLICY_EVAL_INTERVAL_MS, MOTION_FALLBACK_TIMEOUT_MS, RecordingCoordinator;
1177
+ var DEFAULT_SEGMENT_DURATION_SEC, POLICY_EVAL_INTERVAL_MS, MOTION_FALLBACK_TIMEOUT_MS, RecordingCoordinator;
1170
1178
  var init_recording_coordinator = __esm({
1171
1179
  "src/recording/recording-coordinator.ts"() {
1172
1180
  "use strict";
@@ -1176,6 +1184,7 @@ var init_recording_coordinator = __esm({
1176
1184
  init_retention_manager();
1177
1185
  init_playlist_generator();
1178
1186
  init_storage_estimator();
1187
+ DEFAULT_SEGMENT_DURATION_SEC = 4;
1179
1188
  POLICY_EVAL_INTERVAL_MS = 1e3;
1180
1189
  MOTION_FALLBACK_TIMEOUT_MS = 6e4;
1181
1190
  RecordingCoordinator = class _RecordingCoordinator {
@@ -1189,6 +1198,7 @@ var init_recording_coordinator = __esm({
1189
1198
  storagePath;
1190
1199
  globalFfmpegConfig;
1191
1200
  detectedFfmpegConfig;
1201
+ segmentDurationSec;
1192
1202
  recordings = /* @__PURE__ */ new Map();
1193
1203
  policyTimer = null;
1194
1204
  retentionManager;
@@ -1205,6 +1215,7 @@ var init_recording_coordinator = __esm({
1205
1215
  this.storagePath = config.storagePath;
1206
1216
  this.globalFfmpegConfig = config.globalFfmpegConfig;
1207
1217
  this.detectedFfmpegConfig = config.detectedFfmpegConfig;
1218
+ this.segmentDurationSec = config.segmentDurationSec ?? DEFAULT_SEGMENT_DURATION_SEC;
1208
1219
  this.retentionManager = new RetentionManager(
1209
1220
  this.db,
1210
1221
  this.logger.child("retention"),
@@ -1290,7 +1301,7 @@ var init_recording_coordinator = __esm({
1290
1301
  const writerConfig = {
1291
1302
  deviceId,
1292
1303
  streamId: sp.streamId,
1293
- segmentDurationSec: 4,
1304
+ segmentDurationSec: this.segmentDurationSec,
1294
1305
  storagePath: this.storagePath,
1295
1306
  storageName,
1296
1307
  subDirectory,
@@ -3135,9 +3146,7 @@ var PipelineAddon = class {
3135
3146
  capabilities: [
3136
3147
  { name: "stream-broker", mode: "singleton" },
3137
3148
  { name: "recording-engine", mode: "singleton" },
3138
- { name: "analysis-pipeline", mode: "singleton" },
3139
- { name: "analysis-data-persistence", mode: "singleton" },
3140
- { name: "webrtc", mode: "collection" }
3149
+ { name: "analysis-data-persistence", mode: "singleton" }
3141
3150
  ]
3142
3151
  };
3143
3152
  // Stream broker
@@ -3150,11 +3159,10 @@ var PipelineAddon = class {
3150
3159
  currentRecordingConfig = {
3151
3160
  ffmpegPath: "ffmpeg",
3152
3161
  hwaccel: void 0,
3153
- threads: void 0
3162
+ threads: void 0,
3163
+ segmentDurationSeconds: 4,
3164
+ defaultRetentionDays: 30
3154
3165
  };
3155
- // Analysis pipeline
3156
- analysisPipeline = null;
3157
- analysisLogger = null;
3158
3166
  // Analysis persistence
3159
3167
  persistenceFacade = null;
3160
3168
  setRecordingDependencies(deps) {
@@ -3184,10 +3192,14 @@ var PipelineAddon = class {
3184
3192
  hwaccel: context.addonConfig.hwaccel ?? this.currentRecordingConfig.hwaccel,
3185
3193
  threads: context.addonConfig.threads ?? this.currentRecordingConfig.threads
3186
3194
  };
3195
+ const segmentDurationSeconds = context.addonConfig.segmentDurationSeconds ?? this.currentRecordingConfig.segmentDurationSeconds;
3196
+ const defaultRetentionDays = context.addonConfig.defaultRetentionDays ?? this.currentRecordingConfig.defaultRetentionDays;
3187
3197
  this.currentRecordingConfig = {
3188
3198
  ffmpegPath,
3189
3199
  hwaccel: globalFfmpegConfig.hwaccel,
3190
- threads: globalFfmpegConfig.threads
3200
+ threads: globalFfmpegConfig.threads,
3201
+ segmentDurationSeconds,
3202
+ defaultRetentionDays
3191
3203
  };
3192
3204
  const fileStorage = context.storage.files;
3193
3205
  if (!fileStorage) {
@@ -3203,7 +3215,8 @@ var PipelineAddon = class {
3203
3215
  fileStorage,
3204
3216
  storagePath,
3205
3217
  globalFfmpegConfig,
3206
- detectedFfmpegConfig
3218
+ detectedFfmpegConfig,
3219
+ segmentDurationSec: segmentDurationSeconds
3207
3220
  });
3208
3221
  await this.coordinator.start();
3209
3222
  context.logger.info("Recording Engine initialized");
@@ -3212,16 +3225,6 @@ var PipelineAddon = class {
3212
3225
  context.logger.warn(`Recording Engine failed to initialize: ${msg}`);
3213
3226
  }
3214
3227
  }
3215
- this.analysisLogger = context.logger;
3216
- try {
3217
- const mod = await import("@camstack/lib-pipeline-analysis");
3218
- const instance = new mod.AnalysisPipeline();
3219
- this.analysisPipeline = instance;
3220
- this.analysisLogger.info("Analysis pipeline loaded successfully");
3221
- } catch (error) {
3222
- const msg = error instanceof Error ? error.message : String(error);
3223
- this.analysisLogger.warn(`Analysis pipeline not available: ${msg} -- analysis features disabled`);
3224
- }
3225
3228
  const eventPersistence = new EventPersistenceService({
3226
3229
  getStorageLocation: () => context.storage,
3227
3230
  subscribe: (filter, handler) => context.eventBus.subscribe(filter, handler),
@@ -3273,7 +3276,6 @@ var PipelineAddon = class {
3273
3276
  this.sqliteDb = null;
3274
3277
  }
3275
3278
  this.recordingDb = null;
3276
- this.analysisPipeline = null;
3277
3279
  if (this.persistenceFacade) {
3278
3280
  this.persistenceFacade.eventPersistence.stop();
3279
3281
  this.persistenceFacade.retention.stop();
@@ -3286,13 +3288,8 @@ var PipelineAddon = class {
3286
3288
  return this.brokerManager;
3287
3289
  case "recording-engine":
3288
3290
  return this.coordinator;
3289
- case "analysis-pipeline":
3290
- return this.analysisPipeline;
3291
3291
  case "analysis-data-persistence":
3292
3292
  return this.persistenceFacade;
3293
- case "webrtc":
3294
- return null;
3295
- // WebRTC is provided externally or via collection
3296
3293
  default:
3297
3294
  return null;
3298
3295
  }
@@ -3306,52 +3303,9 @@ var PipelineAddon = class {
3306
3303
  if (!this.recordingDb) throw new Error("PipelineAddon recording not initialized");
3307
3304
  return this.recordingDb;
3308
3305
  }
3309
- /** Whether the analysis pipeline package loaded successfully */
3310
- isAnalysisAvailable() {
3311
- return this.analysisPipeline !== null;
3312
- }
3313
3306
  // --- IConfigurable ---
3314
3307
  getConfigSchema() {
3315
- return {
3316
- sections: [
3317
- {
3318
- id: "ffmpeg",
3319
- title: "FFmpeg Settings",
3320
- columns: 2,
3321
- fields: [
3322
- {
3323
- type: "text",
3324
- key: "ffmpegPath",
3325
- label: "FFmpeg Binary Path",
3326
- description: 'Path to the ffmpeg executable, or just "ffmpeg" if it is in your PATH',
3327
- placeholder: "ffmpeg"
3328
- },
3329
- {
3330
- type: "select",
3331
- key: "hwaccel",
3332
- label: "Hardware Acceleration",
3333
- description: "Enable GPU-accelerated video encoding if supported by your hardware",
3334
- options: [
3335
- { value: "", label: "None (software)", description: "CPU-only encoding" },
3336
- { value: "nvenc", label: "NVIDIA NVENC", description: "NVIDIA GPU encoding" },
3337
- { value: "vaapi", label: "Intel VAAPI", description: "Intel GPU encoding (Linux)" },
3338
- { value: "videotoolbox", label: "Apple VideoToolbox", description: "macOS hardware encoding" }
3339
- ]
3340
- },
3341
- {
3342
- type: "number",
3343
- key: "threads",
3344
- label: "FFmpeg Threads",
3345
- description: "Number of CPU threads for software encoding (0 = auto)",
3346
- min: 0,
3347
- max: 64,
3348
- step: 1,
3349
- unit: "threads"
3350
- }
3351
- ]
3352
- }
3353
- ]
3354
- };
3308
+ return { sections: [] };
3355
3309
  }
3356
3310
  getConfig() {
3357
3311
  return { ...this.currentRecordingConfig };
@@ -3360,7 +3314,9 @@ var PipelineAddon = class {
3360
3314
  this.currentRecordingConfig = {
3361
3315
  ffmpegPath: config.ffmpegPath ?? this.currentRecordingConfig.ffmpegPath,
3362
3316
  hwaccel: config.hwaccel ?? this.currentRecordingConfig.hwaccel,
3363
- threads: config.threads ?? this.currentRecordingConfig.threads
3317
+ threads: config.threads ?? this.currentRecordingConfig.threads,
3318
+ segmentDurationSeconds: config.segmentDurationSeconds ?? this.currentRecordingConfig.segmentDurationSeconds,
3319
+ defaultRetentionDays: config.defaultRetentionDays ?? this.currentRecordingConfig.defaultRetentionDays
3364
3320
  };
3365
3321
  }
3366
3322
  };