@camstack/types 1.2.226 → 1.2.227

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,10 +1,36 @@
1
1
  import type { IScopedLogger } from '../interfaces/logging.js';
2
+ /**
3
+ * One artifact per platform+arch: the URL, how it is packed, and what the
4
+ * binary inside is SUPPOSED to be able to do.
5
+ *
6
+ * It is a table rather than two functions computing strings because the three
7
+ * facts belong together and drifted apart when they did not:
8
+ *
9
+ * - the darwin branch computed an arch and then discarded it, handing an
10
+ * Intel Mac an arm64 Mach-O it cannot execute under any translation;
11
+ * - a single `FFMPEG_VERSION = '7.1'` named the version of nothing — the linux
12
+ * URL is unversioned and serves 7.0.2 — so the inner path built from it never
13
+ * matched and only the extractor's recursive fallback saved it;
14
+ * - and nothing recorded what a download was expected to be capable of, which
15
+ * is how a build with no VAAPI at all served every transcode on this fleet
16
+ * for months (D536).
17
+ *
18
+ * `expectedHwaccels` is that missing claim. It is deliberately EMPTY for the
19
+ * linux static builds: they carry no hardware support and pretending otherwise
20
+ * would make the assertion a lie. That emptiness is the honest description of
21
+ * a portable build, and the reason a node that has an image prefers the image's
22
+ * ffmpeg over this one.
23
+ */
24
+ export interface FfmpegArtifact {
25
+ readonly url: string;
26
+ readonly archiveFormat: 'zip' | 'tar.gz' | 'tar.xz';
27
+ /** `-hwaccels` names this artifact is built with. Empty = none, honestly. */
28
+ readonly expectedHwaccels: readonly string[];
29
+ }
30
+ /** The artifact for this node, or a refusal naming what was asked for. */
31
+ export declare function getFfmpegArtifact(platform: string, arch: string): FfmpegArtifact;
32
+ /** The URL alone, for a caller that wants nothing else. */
2
33
  export declare function getFfmpegDownloadUrl(platform: string, arch: string): string;
3
- export declare function getFfmpegArchiveInfo(platform: string): {
4
- isArchive: boolean;
5
- archiveFormat: 'zip' | 'tar.gz' | 'tar.xz';
6
- archiveInnerPath: string;
7
- };
8
34
  /**
9
35
  * Ensure an ffmpeg binary WE provide is available on this node, and report
10
36
  * which one and what it can do.
@@ -1,3 +1,3 @@
1
1
  export { ensureBinary, downloadBinary, findInPath, getPlatformInfo, buildBinaryPath, } from './binary-downloader.js';
2
- export { ensureFfmpeg, getFfmpegDownloadUrl } from './ffmpeg-downloader.js';
2
+ export { ensureFfmpeg, getFfmpegArtifact, getFfmpegDownloadUrl } from './ffmpeg-downloader.js';
3
3
  export { ensurePython, installPythonPackages, installPythonRequirements, getPythonDownloadUrl, PYTHON_VERSION, } from './python-downloader.js';
package/dist/node.d.ts CHANGED
@@ -1,6 +1,6 @@
1
1
  export type { PlatformInfo } from './deps/binary-downloader.js';
2
2
  export { buildBinaryPath, downloadBinary, ensureBinary, findInPath, getPlatformInfo, } from './deps/binary-downloader.js';
3
- export { ensureFfmpeg, getFfmpegDownloadUrl } from './deps/ffmpeg-downloader.js';
3
+ export { ensureFfmpeg, getFfmpegArtifact, getFfmpegDownloadUrl } from './deps/ffmpeg-downloader.js';
4
4
  export { probeFfmpegBinary, parseFfmpegCapabilities, type FfmpegBinaryCapabilities, } from './ffmpeg/binary-capabilities.js';
5
5
  export { ensurePython, getPythonDownloadUrl, installPythonPackages, installPythonRequirements, PYTHON_VERSION, } from './deps/python-downloader.js';
6
6
  export type { Fmp4FragmentChildArgs, Fmp4FragmentChildDeps, } from './ffmpeg/fmp4-fragment-child.js';
package/dist/node.js CHANGED
@@ -388,40 +388,42 @@ function bundledFfmpegPath(platform) {
388
388
  * - Linux: https://johnvansickle.com/ffmpeg/ (static builds)
389
389
  * - macOS: https://www.osxexperts.net/
390
390
  */
391
- var FFMPEG_VERSION = "7.1";
392
- function getFfmpegDownloadUrl(platform, arch) {
393
- switch (platform) {
394
- case "linux": {
395
- const a = {
396
- x64: "amd64",
397
- arm64: "arm64"
398
- }[arch];
399
- if (!a) throw new Error(`Unsupported Linux architecture: ${arch}`);
400
- return `https://johnvansickle.com/ffmpeg/releases/ffmpeg-release-${a}-static.tar.xz`;
401
- }
402
- case "darwin":
403
- if (!{
404
- arm64: "arm64",
405
- x64: "amd64"
406
- }[arch]) throw new Error(`Unsupported macOS architecture: ${arch}`);
407
- return `https://www.osxexperts.net/ffmpeg${FFMPEG_VERSION.replace(".", "")}arm.zip`;
408
- default: throw new Error(`Unsupported platform: ${platform}`);
391
+ /**
392
+ * johnvansickle for linux (unversioned "release" URLs, so no version appears
393
+ * here), osxexperts for macOS — two different builds, and the Intel one is a
394
+ * different file at a different version from the arm one.
395
+ */
396
+ var FFMPEG_ARTIFACTS = {
397
+ "linux-x64": {
398
+ url: "https://johnvansickle.com/ffmpeg/releases/ffmpeg-release-amd64-static.tar.xz",
399
+ archiveFormat: "tar.xz",
400
+ expectedHwaccels: []
401
+ },
402
+ "linux-arm64": {
403
+ url: "https://johnvansickle.com/ffmpeg/releases/ffmpeg-release-arm64-static.tar.xz",
404
+ archiveFormat: "tar.xz",
405
+ expectedHwaccels: []
406
+ },
407
+ "darwin-arm64": {
408
+ url: "https://www.osxexperts.net/ffmpeg71arm.zip",
409
+ archiveFormat: "zip",
410
+ expectedHwaccels: ["videotoolbox"]
411
+ },
412
+ "darwin-x64": {
413
+ url: "https://www.osxexperts.net/ffmpeg80intel.zip",
414
+ archiveFormat: "zip",
415
+ expectedHwaccels: ["videotoolbox"]
409
416
  }
417
+ };
418
+ /** The artifact for this node, or a refusal naming what was asked for. */
419
+ function getFfmpegArtifact(platform, arch) {
420
+ const artifact = FFMPEG_ARTIFACTS[`${platform}-${arch}`];
421
+ if (!artifact) throw new Error(`Unsupported platform/architecture for ffmpeg: ${platform}-${arch}`);
422
+ return artifact;
410
423
  }
411
- function getFfmpegArchiveInfo(platform) {
412
- switch (platform) {
413
- case "linux": return {
414
- isArchive: true,
415
- archiveFormat: "tar.xz",
416
- archiveInnerPath: `ffmpeg-${FFMPEG_VERSION}-amd64-static/ffmpeg`
417
- };
418
- case "darwin": return {
419
- isArchive: true,
420
- archiveFormat: "zip",
421
- archiveInnerPath: "ffmpeg"
422
- };
423
- default: throw new Error(`Unsupported platform: ${platform}`);
424
- }
424
+ /** The URL alone, for a caller that wants nothing else. */
425
+ function getFfmpegDownloadUrl(platform, arch) {
426
+ return getFfmpegArtifact(platform, arch).url;
425
427
  }
426
428
  /**
427
429
  * Ensure an ffmpeg binary WE provide is available on this node, and report
@@ -450,13 +452,15 @@ async function ensureFfmpeg(dataDir, logger) {
450
452
  exists: node_fs.existsSync
451
453
  });
452
454
  if (override !== void 0 && override.trim().length > 0 && chosen?.origin !== "override") logger.error(`${FFMPEG_PATH_ENV} names a binary that does not exist — ignoring it`, { meta: { [FFMPEG_PATH_ENV]: override } });
455
+ const artifact = chosen === null ? getFfmpegArtifact(platform, arch) : null;
453
456
  const path = chosen?.path ?? await downloadBinary({
454
457
  name: "ffmpeg",
455
- url: getFfmpegDownloadUrl(platform, arch),
458
+ url: artifact?.url ?? getFfmpegDownloadUrl(platform, arch),
456
459
  targetDir: depsDir,
457
460
  targetName: `ffmpeg${ext}`,
458
461
  logger,
459
- ...getFfmpegArchiveInfo(platform)
462
+ isArchive: true,
463
+ archiveFormat: artifact?.archiveFormat ?? "tar.xz"
460
464
  });
461
465
  const capabilities = await probeFfmpegBinary(path);
462
466
  logger.info("ffmpeg binary resolved", { meta: {
@@ -465,6 +469,15 @@ async function ensureFfmpeg(dataDir, logger) {
465
469
  version: capabilities.version,
466
470
  hwaccels: [...capabilities.hwaccels].join(",") || "none"
467
471
  } });
472
+ if (artifact !== null) {
473
+ const missing = artifact.expectedHwaccels.filter((name) => !capabilities.hwaccels.has(name));
474
+ if (missing.length > 0) logger.error("the ffmpeg we downloaded cannot do what this artifact is supposed to — the source changed under us", { meta: {
475
+ url: artifact.url,
476
+ expected: artifact.expectedHwaccels.join(","),
477
+ missing: missing.join(","),
478
+ got: [...capabilities.hwaccels].join(",") || "none"
479
+ } });
480
+ }
468
481
  return path;
469
482
  }
470
483
  //#endregion
@@ -1964,6 +1977,7 @@ exports.ensureBinary = ensureBinary;
1964
1977
  exports.ensureFfmpeg = ensureFfmpeg;
1965
1978
  exports.ensurePython = ensurePython;
1966
1979
  exports.findInPath = findInPath;
1980
+ exports.getFfmpegArtifact = getFfmpegArtifact;
1967
1981
  exports.getFfmpegDownloadUrl = getFfmpegDownloadUrl;
1968
1982
  exports.getPlatformInfo = getPlatformInfo;
1969
1983
  exports.getPythonDownloadUrl = getPythonDownloadUrl;
package/dist/node.mjs CHANGED
@@ -365,40 +365,42 @@ function bundledFfmpegPath(platform) {
365
365
  * - Linux: https://johnvansickle.com/ffmpeg/ (static builds)
366
366
  * - macOS: https://www.osxexperts.net/
367
367
  */
368
- var FFMPEG_VERSION = "7.1";
369
- function getFfmpegDownloadUrl(platform, arch) {
370
- switch (platform) {
371
- case "linux": {
372
- const a = {
373
- x64: "amd64",
374
- arm64: "arm64"
375
- }[arch];
376
- if (!a) throw new Error(`Unsupported Linux architecture: ${arch}`);
377
- return `https://johnvansickle.com/ffmpeg/releases/ffmpeg-release-${a}-static.tar.xz`;
378
- }
379
- case "darwin":
380
- if (!{
381
- arm64: "arm64",
382
- x64: "amd64"
383
- }[arch]) throw new Error(`Unsupported macOS architecture: ${arch}`);
384
- return `https://www.osxexperts.net/ffmpeg${FFMPEG_VERSION.replace(".", "")}arm.zip`;
385
- default: throw new Error(`Unsupported platform: ${platform}`);
368
+ /**
369
+ * johnvansickle for linux (unversioned "release" URLs, so no version appears
370
+ * here), osxexperts for macOS — two different builds, and the Intel one is a
371
+ * different file at a different version from the arm one.
372
+ */
373
+ var FFMPEG_ARTIFACTS = {
374
+ "linux-x64": {
375
+ url: "https://johnvansickle.com/ffmpeg/releases/ffmpeg-release-amd64-static.tar.xz",
376
+ archiveFormat: "tar.xz",
377
+ expectedHwaccels: []
378
+ },
379
+ "linux-arm64": {
380
+ url: "https://johnvansickle.com/ffmpeg/releases/ffmpeg-release-arm64-static.tar.xz",
381
+ archiveFormat: "tar.xz",
382
+ expectedHwaccels: []
383
+ },
384
+ "darwin-arm64": {
385
+ url: "https://www.osxexperts.net/ffmpeg71arm.zip",
386
+ archiveFormat: "zip",
387
+ expectedHwaccels: ["videotoolbox"]
388
+ },
389
+ "darwin-x64": {
390
+ url: "https://www.osxexperts.net/ffmpeg80intel.zip",
391
+ archiveFormat: "zip",
392
+ expectedHwaccels: ["videotoolbox"]
386
393
  }
394
+ };
395
+ /** The artifact for this node, or a refusal naming what was asked for. */
396
+ function getFfmpegArtifact(platform, arch) {
397
+ const artifact = FFMPEG_ARTIFACTS[`${platform}-${arch}`];
398
+ if (!artifact) throw new Error(`Unsupported platform/architecture for ffmpeg: ${platform}-${arch}`);
399
+ return artifact;
387
400
  }
388
- function getFfmpegArchiveInfo(platform) {
389
- switch (platform) {
390
- case "linux": return {
391
- isArchive: true,
392
- archiveFormat: "tar.xz",
393
- archiveInnerPath: `ffmpeg-${FFMPEG_VERSION}-amd64-static/ffmpeg`
394
- };
395
- case "darwin": return {
396
- isArchive: true,
397
- archiveFormat: "zip",
398
- archiveInnerPath: "ffmpeg"
399
- };
400
- default: throw new Error(`Unsupported platform: ${platform}`);
401
- }
401
+ /** The URL alone, for a caller that wants nothing else. */
402
+ function getFfmpegDownloadUrl(platform, arch) {
403
+ return getFfmpegArtifact(platform, arch).url;
402
404
  }
403
405
  /**
404
406
  * Ensure an ffmpeg binary WE provide is available on this node, and report
@@ -427,13 +429,15 @@ async function ensureFfmpeg(dataDir, logger) {
427
429
  exists: existsSync
428
430
  });
429
431
  if (override !== void 0 && override.trim().length > 0 && chosen?.origin !== "override") logger.error(`${FFMPEG_PATH_ENV} names a binary that does not exist — ignoring it`, { meta: { [FFMPEG_PATH_ENV]: override } });
432
+ const artifact = chosen === null ? getFfmpegArtifact(platform, arch) : null;
430
433
  const path = chosen?.path ?? await downloadBinary({
431
434
  name: "ffmpeg",
432
- url: getFfmpegDownloadUrl(platform, arch),
435
+ url: artifact?.url ?? getFfmpegDownloadUrl(platform, arch),
433
436
  targetDir: depsDir,
434
437
  targetName: `ffmpeg${ext}`,
435
438
  logger,
436
- ...getFfmpegArchiveInfo(platform)
439
+ isArchive: true,
440
+ archiveFormat: artifact?.archiveFormat ?? "tar.xz"
437
441
  });
438
442
  const capabilities = await probeFfmpegBinary(path);
439
443
  logger.info("ffmpeg binary resolved", { meta: {
@@ -442,6 +446,15 @@ async function ensureFfmpeg(dataDir, logger) {
442
446
  version: capabilities.version,
443
447
  hwaccels: [...capabilities.hwaccels].join(",") || "none"
444
448
  } });
449
+ if (artifact !== null) {
450
+ const missing = artifact.expectedHwaccels.filter((name) => !capabilities.hwaccels.has(name));
451
+ if (missing.length > 0) logger.error("the ffmpeg we downloaded cannot do what this artifact is supposed to — the source changed under us", { meta: {
452
+ url: artifact.url,
453
+ expected: artifact.expectedHwaccels.join(","),
454
+ missing: missing.join(","),
455
+ got: [...capabilities.hwaccels].join(",") || "none"
456
+ } });
457
+ }
445
458
  return path;
446
459
  }
447
460
  //#endregion
@@ -1924,4 +1937,4 @@ function resolveExportFingerprint(input) {
1924
1937
  return input.persisted ?? input.fresh;
1925
1938
  }
1926
1939
  //#endregion
1927
- export { ChildCostRegistry, FfmpegProcess, FilesystemStorageProvider, Fmp4FragmentChild, Fmp4FragmentPlane, NO_COST_CLAIM, PYTHON_VERSION, buildBinaryPath, canonicalDeviceFingerprint, canonicalHash, containsOrEquals, diffExportTargets, downloadBinary, ensureBinary, ensureFfmpeg, ensurePython, findInPath, getFfmpegDownloadUrl, getPlatformInfo, getPythonDownloadUrl, installPythonPackages, installPythonRequirements, nodeProcStatReader, parseFfmpegCapabilities, parseProcCpuSeconds, parseProcRssBytes, physicalRootOf, probeFfmpegBinary, readProcessCost, resolveExportFingerprint, signExpiringUrl, verifyExpiringUrl };
1940
+ export { ChildCostRegistry, FfmpegProcess, FilesystemStorageProvider, Fmp4FragmentChild, Fmp4FragmentPlane, NO_COST_CLAIM, PYTHON_VERSION, buildBinaryPath, canonicalDeviceFingerprint, canonicalHash, containsOrEquals, diffExportTargets, downloadBinary, ensureBinary, ensureFfmpeg, ensurePython, findInPath, getFfmpegArtifact, getFfmpegDownloadUrl, getPlatformInfo, getPythonDownloadUrl, installPythonPackages, installPythonRequirements, nodeProcStatReader, parseFfmpegCapabilities, parseProcCpuSeconds, parseProcRssBytes, physicalRootOf, probeFfmpegBinary, readProcessCost, resolveExportFingerprint, signExpiringUrl, verifyExpiringUrl };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@camstack/types",
3
- "version": "1.2.226",
3
+ "version": "1.2.227",
4
4
  "description": "Shared types, interfaces, and model catalogs for the CamStack detection ecosystem",
5
5
  "keywords": [
6
6
  "camstack",