@camstack/system 1.1.25 → 1.1.26

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.
@@ -1,5 +1,5 @@
1
1
  const require_chunk = require("./chunk-Cek0wNdY.js");
2
- const require_manifest_python_deps = require("./manifest-python-deps-BqXCckob.js");
2
+ const require_manifest_python_deps = require("./manifest-python-deps-CCmnJmNf.js");
3
3
  const require_custom_action_registry = require("./custom-action-registry-vLYEFTtv.js");
4
4
  let node_fs = require("node:fs");
5
5
  node_fs = require_chunk.__toESM(node_fs);
@@ -1,4 +1,4 @@
1
- import { F as createUdsLoggerWithControl, I as LocalChildClient, i as createUdsAddonContext, it as setWorkerNativeCapsChangeListener, nt as getWorkerNativeCapSnapshot, ot as validateProviderRegistrations, t as installManifestPythonDeps, tt as getWorkerNativeCapProvider, vt as installManifestNativeDeps, yt as resolveAddonClass } from "./manifest-python-deps-Dxl4twM3.mjs";
1
+ import { F as createUdsLoggerWithControl, I as LocalChildClient, i as createUdsAddonContext, it as setWorkerNativeCapsChangeListener, nt as getWorkerNativeCapSnapshot, ot as validateProviderRegistrations, t as installManifestPythonDeps, tt as getWorkerNativeCapProvider, vt as installManifestNativeDeps, yt as resolveAddonClass } from "./manifest-python-deps-DPA7N9UP.mjs";
2
2
  import { t as CustomActionRegistry } from "./custom-action-registry-BEXwC-oo.mjs";
3
3
  import { register } from "node:module";
4
4
  import * as fs from "node:fs";
@@ -1,12 +1,8 @@
1
1
  import { ProviderRegistration, BaseAddon } from '@camstack/types';
2
2
  export { PlatformScorer } from './platform-scorer.js';
3
3
  export { InferenceConfigResolver } from './inference-config-resolver.js';
4
- export { HardwareEncoderProber } from './hardware-encoder-probe.js';
5
- export { HardwareDecodeAccelProber } from './hardware-decode-accel-probe.js';
6
4
  export declare class PlatformProbeNativeAddon extends BaseAddon {
7
5
  private scorer;
8
- private encoderProber;
9
- private decodeAccelProber;
10
6
  private cachedCaps;
11
7
  /**
12
8
  * Per-boot generation stamp for the manual readiness emissions below.
@@ -31,13 +27,6 @@ export declare class PlatformProbeNativeAddon extends BaseAddon {
31
27
  private bareLocalNodeId;
32
28
  /** Emit a `system.ready-state` transition for the platform-probe cap. */
33
29
  private emitProbeReadiness;
34
- /**
35
- * Resolve the ffmpeg binary the encoder probe should test, from the cluster
36
- * `ffmpeg` config section (`binaryPath`). The probe MUST exercise the same
37
- * binary the broker/recorder spawn, or it may report encoders for a different
38
- * ffmpeg. Defaults to PATH `ffmpeg` on any miss.
39
- */
40
- private resolveFfmpegBinaryPath;
41
30
  protected onInitialize(): Promise<ProviderRegistration[]>;
42
31
  protected onShutdown(): Promise<void>;
43
32
  }
@@ -18,7 +18,7 @@ node_os = require_chunk.__toESM(node_os);
18
18
  * entire Node process (WS handshakes, tRPC subscriptions, metrics — all
19
19
  * stalled). Keeping it async turns the probe into a true background task.
20
20
  */
21
- var execFileAsync$2 = (0, node_util.promisify)(node_child_process.execFile);
21
+ var execFileAsync = (0, node_util.promisify)(node_child_process.execFile);
22
22
  /** Minimal no-op logger for default parameter */
23
23
  var noopLogger = {
24
24
  debug() {},
@@ -46,7 +46,7 @@ async function getAvailableRAM_MB() {
46
46
  const platform = node_os.platform();
47
47
  try {
48
48
  if (platform === "darwin") {
49
- const { stdout: output } = await execFileAsync$2("vm_stat", [], {
49
+ const { stdout: output } = await execFileAsync("vm_stat", [], {
50
50
  encoding: "utf8",
51
51
  timeout: 3e3
52
52
  });
@@ -171,7 +171,7 @@ var PlatformScorer = class {
171
171
  }
172
172
  if (platform === "linux") {
173
173
  try {
174
- const { stdout } = await execFileAsync$2("nvidia-smi", ["--query-gpu=name,memory.total", "--format=csv,noheader"], {
174
+ const { stdout } = await execFileAsync("nvidia-smi", ["--query-gpu=name,memory.total", "--format=csv,noheader"], {
175
175
  encoding: "utf8",
176
176
  timeout: 5e3
177
177
  });
@@ -237,7 +237,7 @@ var PlatformScorer = class {
237
237
  "python"
238
238
  ];
239
239
  for (const cmd of candidates) try {
240
- await execFileAsync$2(cmd, ["--version"], { timeout: 5e3 });
240
+ await execFileAsync(cmd, ["--version"], { timeout: 5e3 });
241
241
  return cmd;
242
242
  } catch (err) {
243
243
  this.logger.debug(`Python command "${cmd}" not found`, { meta: { error: (0, _camstack_types.errMsg)(err) } });
@@ -335,264 +335,6 @@ var InferenceConfigResolver = class {
335
335
  }
336
336
  };
337
337
  //#endregion
338
- //#region src/builtins/platform-probe/hardware-encoder-probe.ts
339
- var execFileAsync$1 = (0, node_util.promisify)(node_child_process.execFile);
340
- function buildCandidates(hardware) {
341
- const out = [];
342
- if (hardware.platform === "darwin") {
343
- out.push({
344
- encoder: "h264_videotoolbox",
345
- codec: "H264",
346
- family: "videotoolbox"
347
- });
348
- out.push({
349
- encoder: "hevc_videotoolbox",
350
- codec: "H265",
351
- family: "videotoolbox"
352
- });
353
- }
354
- if (hardware.platform === "linux") {
355
- if (hardware.gpu?.type === "nvidia") {
356
- out.push({
357
- encoder: "h264_nvenc",
358
- codec: "H264",
359
- family: "nvenc"
360
- });
361
- out.push({
362
- encoder: "hevc_nvenc",
363
- codec: "H265",
364
- family: "nvenc"
365
- });
366
- }
367
- if (hardware.gpu?.type === "intel" || hardware.gpu?.type === "amd" || !hardware.gpu) {
368
- out.push({
369
- encoder: "h264_vaapi",
370
- codec: "H264",
371
- family: "vaapi"
372
- });
373
- out.push({
374
- encoder: "hevc_vaapi",
375
- codec: "H265",
376
- family: "vaapi"
377
- });
378
- }
379
- }
380
- return out;
381
- }
382
- async function runTestEncode(candidate, opts) {
383
- const ffmpeg = opts.ffmpegPath ?? "ffmpeg";
384
- const timeout = opts.timeoutMs ?? 8e3;
385
- const nullSink = node_os.platform() === "win32" ? "NUL" : "/dev/null";
386
- const baseArgs = [
387
- "-hide_banner",
388
- "-loglevel",
389
- "error"
390
- ];
391
- const inArgs = [
392
- "-f",
393
- "lavfi",
394
- "-i",
395
- "testsrc=duration=0.04:size=16x16:rate=25"
396
- ];
397
- let outArgs;
398
- if (candidate.family === "vaapi") outArgs = [
399
- "-vaapi_device",
400
- "/dev/dri/renderD128",
401
- "-vf",
402
- "format=nv12,hwupload",
403
- "-c:v",
404
- candidate.encoder,
405
- "-frames:v",
406
- "1",
407
- "-f",
408
- "null",
409
- nullSink
410
- ];
411
- else outArgs = [
412
- "-c:v",
413
- candidate.encoder,
414
- "-frames:v",
415
- "1",
416
- "-f",
417
- "null",
418
- nullSink
419
- ];
420
- try {
421
- await execFileAsync$1(ffmpeg, [
422
- ...baseArgs,
423
- ...inArgs,
424
- ...outArgs
425
- ], {
426
- timeout,
427
- encoding: "utf8"
428
- });
429
- return {
430
- encoder: candidate.encoder,
431
- codec: candidate.codec,
432
- family: candidate.family,
433
- available: true
434
- };
435
- } catch (err) {
436
- return {
437
- encoder: candidate.encoder,
438
- codec: candidate.codec,
439
- family: candidate.family,
440
- available: false,
441
- reason: (0, _camstack_types.errMsg)(err)
442
- };
443
- }
444
- }
445
- var HardwareEncoderProber = class {
446
- cached = null;
447
- inflight = null;
448
- logger;
449
- ffmpegPath;
450
- constructor(logger, ffmpegPath = "ffmpeg") {
451
- this.logger = logger;
452
- this.ffmpegPath = ffmpegPath;
453
- }
454
- getCached() {
455
- return this.cached;
456
- }
457
- async probe(hardware, options = {}) {
458
- if (!options.force && this.cached) return this.cached;
459
- if (this.inflight) return this.inflight;
460
- this.inflight = this.runProbe(hardware).then((res) => {
461
- this.cached = res;
462
- this.inflight = null;
463
- return res;
464
- }).catch((err) => {
465
- this.inflight = null;
466
- throw err;
467
- });
468
- return this.inflight;
469
- }
470
- async runProbe(hardware) {
471
- const candidates = buildCandidates(hardware);
472
- const start = Date.now();
473
- this.logger.info("Probing hardware encoders", { meta: {
474
- platform: hardware.platform,
475
- arch: hardware.arch,
476
- candidates: candidates.length
477
- } });
478
- const probes = await Promise.all(candidates.map((c) => runTestEncode(c, { ffmpegPath: this.ffmpegPath })));
479
- probes.push({
480
- encoder: "libx264",
481
- codec: "H264",
482
- family: "software",
483
- available: true
484
- });
485
- probes.push({
486
- encoder: "libx265",
487
- codec: "H265",
488
- family: "software",
489
- available: true
490
- });
491
- const pickDefault = (codec) => {
492
- const hw = probes.find((p) => p.codec === codec && p.available && p.family !== "software");
493
- if (hw) return hw.encoder;
494
- return codec === "H264" ? "libx264" : "libx265";
495
- };
496
- const result = {
497
- encoders: probes,
498
- defaultH264: pickDefault("H264"),
499
- defaultH265: pickDefault("H265"),
500
- probedAt: Date.now()
501
- };
502
- const elapsed = Date.now() - start;
503
- this.logger.info("Hardware encoder probe complete", { meta: {
504
- elapsedMs: elapsed,
505
- defaultH264: result.defaultH264,
506
- defaultH265: result.defaultH265,
507
- availableHw: probes.filter((p) => p.available && p.family !== "software").map((p) => p.encoder)
508
- } });
509
- return result;
510
- }
511
- };
512
- //#endregion
513
- //#region src/builtins/platform-probe/hardware-decode-accel-probe.ts
514
- var execFileAsync = (0, node_util.promisify)(node_child_process.execFile);
515
- var defaultExecFn = async (ffmpegPath, args) => {
516
- const { stdout } = await execFileAsync(ffmpegPath, [...args], {
517
- timeout: 8e3,
518
- encoding: "utf8"
519
- });
520
- return { stdout };
521
- };
522
- /**
523
- * Parse the output of `ffmpeg -hwaccels`. The listing looks like:
524
- *
525
- * Hardware acceleration methods:
526
- * videotoolbox
527
- *
528
- * The header line is dropped; remaining non-empty trimmed lines are the
529
- * method names, lowercased and de-duplicated (order preserved).
530
- */
531
- function parseHwAccelsOutput(stdout) {
532
- const seen = /* @__PURE__ */ new Set();
533
- const methods = [];
534
- for (const raw of stdout.split("\n")) {
535
- const line = raw.trim().toLowerCase();
536
- if (line.length === 0) continue;
537
- if (line.endsWith("methods:")) continue;
538
- if (seen.has(line)) continue;
539
- seen.add(line);
540
- methods.push(line);
541
- }
542
- return methods;
543
- }
544
- /**
545
- * Probes which `-hwaccel` decode backends the configured ffmpeg binary
546
- * supports. Mirrors {@link HardwareEncoderProber} (configured binary, cached,
547
- * single-flight, forceable). Never throws: a probe failure yields an empty
548
- * method list so callers fall back to software decode.
549
- */
550
- var HardwareDecodeAccelProber = class {
551
- cached = null;
552
- inflight = null;
553
- logger;
554
- ffmpegPath;
555
- execFn;
556
- constructor(logger, ffmpegPath = "ffmpeg", execFn = defaultExecFn) {
557
- this.logger = logger;
558
- this.ffmpegPath = ffmpegPath;
559
- this.execFn = execFn;
560
- }
561
- getCached() {
562
- return this.cached;
563
- }
564
- async probe(options = {}) {
565
- if (!options.force && this.cached) return this.cached;
566
- if (this.inflight) return this.inflight;
567
- this.inflight = this.runProbe().then((res) => {
568
- this.cached = res;
569
- this.inflight = null;
570
- return res;
571
- }).catch((err) => {
572
- this.inflight = null;
573
- throw err;
574
- });
575
- return this.inflight;
576
- }
577
- async runProbe() {
578
- try {
579
- const { stdout } = await this.execFn(this.ffmpegPath, ["-hide_banner", "-hwaccels"]);
580
- const methods = parseHwAccelsOutput(stdout);
581
- this.logger.info("Hardware decode-accel probe complete", { meta: { methods } });
582
- return {
583
- methods,
584
- probedAt: Date.now()
585
- };
586
- } catch (err) {
587
- this.logger.warn("Hardware decode-accel probe failed — assuming none available", { meta: { error: (0, _camstack_types.errMsg)(err) } });
588
- return {
589
- methods: [],
590
- probedAt: Date.now()
591
- };
592
- }
593
- }
594
- };
595
- //#endregion
596
338
  //#region src/builtins/platform-probe/index.ts
597
339
  /**
598
340
  * The decode-hwaccel backends `ctx.kernel.hwaccel.resolve` accepts. The cap
@@ -624,8 +366,6 @@ function narrowHwAccelPrefer(value) {
624
366
  }
625
367
  var PlatformProbeNativeAddon = class extends _camstack_types.BaseAddon {
626
368
  scorer = null;
627
- encoderProber = null;
628
- decodeAccelProber = null;
629
369
  cachedCaps = null;
630
370
  /**
631
371
  * Per-boot generation stamp for the manual readiness emissions below.
@@ -673,20 +413,6 @@ var PlatformProbeNativeAddon = class extends _camstack_types.BaseAddon {
673
413
  });
674
414
  } catch {}
675
415
  }
676
- /**
677
- * Resolve the ffmpeg binary the encoder probe should test, from the cluster
678
- * `ffmpeg` config section (`binaryPath`). The probe MUST exercise the same
679
- * binary the broker/recorder spawn, or it may report encoders for a different
680
- * ffmpeg. Defaults to PATH `ffmpeg` on any miss.
681
- */
682
- async resolveFfmpegBinaryPath() {
683
- try {
684
- const bp = (await this.ctx.settings?.getSection("ffmpeg") ?? {})["binaryPath"];
685
- return typeof bp === "string" && bp.trim().length > 0 ? bp : "ffmpeg";
686
- } catch {
687
- return "ffmpeg";
688
- }
689
- }
690
416
  async onInitialize() {
691
417
  this.emitProbeReadiness("starting");
692
418
  const embeddedPython = await this.ctx.deps.ensurePython().catch((err) => {
@@ -694,9 +420,6 @@ var PlatformProbeNativeAddon = class extends _camstack_types.BaseAddon {
694
420
  return null;
695
421
  });
696
422
  this.scorer = new PlatformScorer(this.ctx.logger, embeddedPython);
697
- const ffmpegPath = await this.resolveFfmpegBinaryPath();
698
- this.encoderProber = new HardwareEncoderProber(this.ctx.logger, ffmpegPath);
699
- this.decodeAccelProber = new HardwareDecodeAccelProber(this.ctx.logger, ffmpegPath);
700
423
  const emitPhase = (phase, payload) => {
701
424
  this.ctx.eventBus?.emit({
702
425
  id: `platform-probe-${phase}-${Date.now()}`,
@@ -758,30 +481,6 @@ var PlatformProbeNativeAddon = class extends _camstack_types.BaseAddon {
758
481
  preferred: res.preferred,
759
482
  rationale: res.rationale
760
483
  };
761
- },
762
- getHardwareEncoders: async () => {
763
- const prober = this.encoderProber;
764
- if (!prober) throw new Error("Hardware encoder prober not initialized");
765
- const cached = prober.getCached();
766
- if (cached) return cached;
767
- const caps = await getCaps();
768
- return prober.probe(caps.hardware);
769
- },
770
- refreshHardwareEncoders: async () => {
771
- const prober = this.encoderProber;
772
- if (!prober) throw new Error("Hardware encoder prober not initialized");
773
- const caps = await getCaps();
774
- return prober.probe(caps.hardware, { force: true });
775
- },
776
- getHardwareDecodeAccels: async () => {
777
- const prober = this.decodeAccelProber;
778
- if (!prober) throw new Error("Hardware decode-accel prober not initialized");
779
- return prober.probe();
780
- },
781
- refreshHardwareDecodeAccels: async () => {
782
- const prober = this.decodeAccelProber;
783
- if (!prober) throw new Error("Hardware decode-accel prober not initialized");
784
- return prober.probe({ force: true });
785
484
  }
786
485
  }
787
486
  }];
@@ -789,14 +488,10 @@ var PlatformProbeNativeAddon = class extends _camstack_types.BaseAddon {
789
488
  async onShutdown() {
790
489
  this.emitProbeReadiness("down");
791
490
  this.scorer = null;
792
- this.encoderProber = null;
793
- this.decodeAccelProber = null;
794
491
  this.cachedCaps = null;
795
492
  }
796
493
  };
797
494
  //#endregion
798
- exports.HardwareDecodeAccelProber = HardwareDecodeAccelProber;
799
- exports.HardwareEncoderProber = HardwareEncoderProber;
800
495
  exports.InferenceConfigResolver = InferenceConfigResolver;
801
496
  exports.PlatformProbeNativeAddon = PlatformProbeNativeAddon;
802
497
  exports.default = PlatformProbeNativeAddon;