hyperframes 0.8.21 → 0.8.22

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.
@@ -60438,6 +60438,11 @@ var init_evenDimensions = __esm({
60438
60438
 
60439
60439
  // ../engine/src/utils/runFfmpeg.ts
60440
60440
  import { spawn as spawn2 } from "child_process";
60441
+ function isExternalFfmpegInterruption(result) {
60442
+ if (result.terminationReason !== "exit" || result.exitCode === 0) return false;
60443
+ if (result.signal === "SIGTERM") return true;
60444
+ return result.exitCode === 255 && FFMPEG_SIGTERM_EXIT_LINE.test(result.stderr);
60445
+ }
60441
60446
  function formatWindowsFfmpegExit(exitCode) {
60442
60447
  if (process.platform !== "win32" || exitCode === null) return void 0;
60443
60448
  if (exitCode === 3221225781 || exitCode === -1073741515) {
@@ -60477,22 +60482,28 @@ async function runFfmpeg(args, opts) {
60477
60482
  onStderr: opts?.onStderr
60478
60483
  });
60479
60484
  const outcome = await managed.wait();
60480
- return {
60485
+ const result = {
60481
60486
  success: outcome.reason === "exit" && outcome.exitCode === 0,
60482
60487
  exitCode: outcome.exitCode,
60488
+ signal: outcome.signal,
60483
60489
  stderr: outcome.stderr,
60484
60490
  durationMs: outcome.durationMs,
60485
60491
  terminationReason: outcome.reason,
60486
60492
  error: outcome.error
60487
60493
  };
60494
+ if (isExternalFfmpegInterruption(result)) {
60495
+ result.failureReason = "external_interruption";
60496
+ }
60497
+ return result;
60488
60498
  }
60489
- var DEFAULT_TIMEOUT, DEFAULT_STDERR_TAIL_LINES;
60499
+ var FFMPEG_SIGTERM_EXIT_LINE, DEFAULT_TIMEOUT, DEFAULT_STDERR_TAIL_LINES;
60490
60500
  var init_runFfmpeg = __esm({
60491
60501
  "../engine/src/utils/runFfmpeg.ts"() {
60492
60502
  "use strict";
60493
60503
  init_ffmpegBinaries();
60494
60504
  init_processTracker();
60495
60505
  init_managedChildProcess();
60506
+ FFMPEG_SIGTERM_EXIT_LINE = /^Exiting normally, received signal 15\.?\r?$/m;
60496
60507
  DEFAULT_TIMEOUT = 3e5;
60497
60508
  DEFAULT_STDERR_TAIL_LINES = 15;
60498
60509
  }
@@ -61441,7 +61452,8 @@ async function encodeFramesFromDir(framesDir, framePattern, outputPath, options,
61441
61452
  formatFfmpegError(result.exitCode, result.stderr),
61442
61453
  result.terminationReason === "deadline",
61443
61454
  encodeTimeout
61444
- )
61455
+ ),
61456
+ failureReason: isExternalFfmpegInterruption(result) ? "external_interruption" : void 0
61445
61457
  };
61446
61458
  }
61447
61459
  const fileSize = existsSync6(outputPath) ? statSync2(outputPath).size : 0;
@@ -61517,7 +61529,8 @@ async function encodeFramesChunkedConcat(framesDir, framePattern, outputPath, op
61517
61529
  durationMs: Date.now() - start,
61518
61530
  framesEncoded: 0,
61519
61531
  fileSize: 0,
61520
- error: chunkResult.error
61532
+ error: chunkResult.error,
61533
+ failureReason: isExternalFfmpegInterruption(processResult) ? "external_interruption" : void 0
61521
61534
  };
61522
61535
  }
61523
61536
  chunkPaths.push(chunkPath);
@@ -61545,7 +61558,8 @@ async function encodeFramesChunkedConcat(framesDir, framePattern, outputPath, op
61545
61558
  durationMs: Date.now() - start,
61546
61559
  framesEncoded: 0,
61547
61560
  fileSize: 0,
61548
- error: concatResult.error
61561
+ error: concatResult.error,
61562
+ failureReason: isExternalFfmpegInterruption(concatProcessResult) ? "external_interruption" : void 0
61549
61563
  };
61550
61564
  }
61551
61565
  const fileSize = existsSync6(outputPath) ? statSync2(outputPath).size : 0;
@@ -61598,7 +61612,8 @@ async function muxVideoWithAudio(videoPath, audioPath, outputPath, signal, confi
61598
61612
  success: result.success,
61599
61613
  outputPath,
61600
61614
  durationMs: result.durationMs,
61601
- error: !result.success ? formatFfmpegError(result.exitCode, result.stderr) : void 0
61615
+ error: !result.success ? formatFfmpegError(result.exitCode, result.stderr) : void 0,
61616
+ failureReason: result.failureReason
61602
61617
  };
61603
61618
  }
61604
61619
  async function applyFaststart(inputPath, outputPath, signal, config, fps) {
@@ -61626,7 +61641,8 @@ async function applyFaststart(inputPath, outputPath, signal, config, fps) {
61626
61641
  success: result.success,
61627
61642
  outputPath,
61628
61643
  durationMs: result.durationMs,
61629
- error: !result.success ? formatFfmpegError(result.exitCode, result.stderr) : void 0
61644
+ error: !result.success ? formatFfmpegError(result.exitCode, result.stderr) : void 0,
61645
+ failureReason: result.failureReason
61630
61646
  };
61631
61647
  }
61632
61648
  var ENCODER_PRESETS, KNOWN_NON_AAC_AUDIO_EXTENSIONS;
@@ -61916,6 +61932,7 @@ async function spawnStreamingEncoder(outputPath, options, signal, config) {
61916
61932
  let exitStatus = "running";
61917
61933
  let stderr = "";
61918
61934
  let exitCode = null;
61935
+ let exitSignal = null;
61919
61936
  let terminationReason = "exit";
61920
61937
  ffmpeg.stdin?.on("error", () => {
61921
61938
  });
@@ -61928,6 +61945,7 @@ async function spawnStreamingEncoder(outputPath, options, signal, config) {
61928
61945
  });
61929
61946
  const exitPromise = managed.wait().then((outcome) => {
61930
61947
  exitCode = outcome.exitCode;
61948
+ exitSignal = outcome.signal;
61931
61949
  stderr = outcome.stderr;
61932
61950
  terminationReason = outcome.reason;
61933
61951
  exitStatus = outcome.reason === "exit" && outcome.exitCode === 0 ? "success" : "error";
@@ -61959,7 +61977,11 @@ async function spawnStreamingEncoder(outputPath, options, signal, config) {
61959
61977
  const encoder = {
61960
61978
  writeFrame: async (buffer) => {
61961
61979
  const stdin = ffmpeg.stdin;
61962
- if (exitStatus !== "running" || !stdin || stdin.destroyed) {
61980
+ if (exitStatus !== "running") {
61981
+ return false;
61982
+ }
61983
+ if (!stdin || stdin.destroyed) {
61984
+ await exitPromise;
61963
61985
  return false;
61964
61986
  }
61965
61987
  const copy = Buffer.from(buffer);
@@ -61999,7 +62021,13 @@ FFmpeg stopped after ${streamingTimeout} ms without consuming a frame.` : "";
61999
62021
  success: false,
62000
62022
  durationMs,
62001
62023
  fileSize: 0,
62002
- error: `${formatFfmpegError(exitCode, stderr)}${inactivitySuffix}`
62024
+ error: `${formatFfmpegError(exitCode, stderr)}${inactivitySuffix}`,
62025
+ failureReason: isExternalFfmpegInterruption({
62026
+ exitCode,
62027
+ signal: exitSignal,
62028
+ stderr,
62029
+ terminationReason
62030
+ }) ? "external_interruption" : void 0
62003
62031
  };
62004
62032
  }
62005
62033
  const fileSize = existsSync7(outputPath) ? statSync3(outputPath).size : 0;
@@ -62009,6 +62037,15 @@ FFmpeg stopped after ${streamingTimeout} ms without consuming a frame.` : "";
62009
62037
  getExitError: () => {
62010
62038
  if (exitStatus !== "error") return void 0;
62011
62039
  return formatFfmpegError(exitCode, stderr);
62040
+ },
62041
+ getExitFailureReason: () => {
62042
+ if (exitStatus !== "error") return void 0;
62043
+ return isExternalFfmpegInterruption({
62044
+ exitCode,
62045
+ signal: exitSignal,
62046
+ stderr,
62047
+ terminationReason
62048
+ }) ? "external_interruption" : void 0;
62012
62049
  }
62013
62050
  };
62014
62051
  return encoder;
@@ -75236,6 +75273,14 @@ async function extractVideoFramesRange(videoPath, videoId, startTime, duration,
75236
75273
  if (format === "png") args.push("-compression_level", "1");
75237
75274
  args.push("-y", outputPattern);
75238
75275
  const processResult = await runFfmpeg(args, { signal, timeout: ffmpegProcessTimeout });
75276
+ if (processResult.failureReason === "external_interruption") {
75277
+ throw new VideoSourceExtractionError(
75278
+ "external_interruption",
75279
+ true,
75280
+ "Video frame extraction interrupted by host lifecycle",
75281
+ `FFmpeg exited with code ${processResult.exitCode}: ${processResult.stderr.slice(-500)}`
75282
+ );
75283
+ }
75239
75284
  if (processResult.terminationReason === "abort") {
75240
75285
  throw new VideoSourceExtractionError("cancelled", false, "Video extraction cancelled");
75241
75286
  }
@@ -77448,7 +77493,10 @@ function ffmpegFailure(stage, result, elementId) {
77448
77493
  let reason = "ffmpeg_failed";
77449
77494
  let owner = "system";
77450
77495
  let retryable = false;
77451
- if (result.terminationReason === "abort") {
77496
+ if (result.failureReason === "external_interruption") {
77497
+ reason = "external_interruption";
77498
+ retryable = true;
77499
+ } else if (result.terminationReason === "abort") {
77452
77500
  reason = "cancelled";
77453
77501
  owner = "user";
77454
77502
  } else if (result.terminationReason === "deadline" || result.terminationReason === "inactivity") {
@@ -77773,7 +77821,7 @@ async function mixAudioTracks(tracks, outputPath, totalDuration, signal, config)
77773
77821
  let result = await runMix(false);
77774
77822
  let degradedAutomation = false;
77775
77823
  const hasAutomation = tracks.some((track) => (track.volumeKeyframes?.length ?? 0) > 0);
77776
- if (!result.success && !signal?.aborted && hasAutomation) {
77824
+ if (!result.success && result.failureReason !== "external_interruption" && !signal?.aborted && hasAutomation) {
77777
77825
  const retry = await runMix(true);
77778
77826
  if (retry.success) {
77779
77827
  result = retry;
@@ -80723,6 +80771,7 @@ __export(src_exports, {
80723
80771
  initializeSession: () => initializeSession,
80724
80772
  injectVideoFramesBatch: () => injectVideoFramesBatch,
80725
80773
  isDrawElementVerificationError: () => isDrawElementVerificationError,
80774
+ isExternalFfmpegInterruption: () => isExternalFfmpegInterruption,
80726
80775
  isFatalCaptureFailure: () => isFatalCaptureFailure,
80727
80776
  isHdrColorSpace: () => isHdrColorSpace,
80728
80777
  isHttpUrl: () => isHttpUrl,
@@ -85147,6 +85196,25 @@ function publishRenderFailure(job, failure, onProgress) {
85147
85196
  updateJobStatus(job, "failed", `Failed: ${failure.error}`, job.progress, onProgress);
85148
85197
  }
85149
85198
 
85199
+ // ../producer/src/services/render/encoderInterruption.ts
85200
+ var ENCODER_INTERRUPTED = "ENCODER_INTERRUPTED";
85201
+ var EncoderInterruptedError = class extends Error {
85202
+ code = ENCODER_INTERRUPTED;
85203
+ owner = "system";
85204
+ retryable = true;
85205
+ /** Retained inside the producer for diagnostics; never copied to the wire envelope. */
85206
+ diagnosticMessage;
85207
+ constructor(prefix, diagnosticMessage) {
85208
+ super(`${prefix}: encoder process was interrupted by the host lifecycle`);
85209
+ this.name = "EncoderInterruptedError";
85210
+ this.diagnosticMessage = diagnosticMessage;
85211
+ }
85212
+ };
85213
+ function encoderFailureError(prefix, result) {
85214
+ const message = `${prefix}: ${result.error ?? "unknown encoder failure"}`;
85215
+ return result.failureReason === "external_interruption" ? new EncoderInterruptedError(prefix, message) : new Error(message);
85216
+ }
85217
+
85150
85218
  // ../producer/src/services/render/renderExecutionContext.ts
85151
85219
  function scopedLogger(logger, fields) {
85152
85220
  const merge = (meta) => ({ ...fields, ...meta });
@@ -85859,7 +85927,7 @@ var CaptureStageError = class extends CaptureFailure {
85859
85927
  }
85860
85928
  };
85861
85929
  function wrapCaptureStageError(error, browserConsole) {
85862
- if (error instanceof CaptureStageError) return error;
85930
+ if (error instanceof CaptureStageError || error instanceof EncoderInterruptedError) return error;
85863
85931
  return new CaptureStageError({ cause: error, browserConsole });
85864
85932
  }
85865
85933
  function getCaptureStageBrowserConsole(error) {
@@ -87921,6 +87989,12 @@ async function runAnimatedGifTranscode(request) {
87921
87989
  const timeout = request.timeoutMs ?? 3e5;
87922
87990
  const result = await runFfmpeg(request.args, { timeout });
87923
87991
  if (result.success) return;
87992
+ if (result.failureReason === "external_interruption") {
87993
+ throw encoderFailureError("Animated GIF transcode failed", {
87994
+ error: `exit ${result.exitCode}: ${result.stderr.slice(-500)}`,
87995
+ failureReason: result.failureReason
87996
+ });
87997
+ }
87924
87998
  if (result.terminationReason === "deadline") {
87925
87999
  throw new Error(`Animated GIF transcode timed out after ${timeout}ms`);
87926
88000
  }
@@ -90716,6 +90790,14 @@ var VideoExtractionStageError = class extends Error {
90716
90790
  retryable;
90717
90791
  failures;
90718
90792
  };
90793
+ function throwIfEncoderInterrupted(result) {
90794
+ const interrupted = result.errors.find((failure) => failure.kind === "external_interruption");
90795
+ if (!interrupted) return;
90796
+ throw encoderFailureError("Video frame extraction failed", {
90797
+ error: String(interrupted.error),
90798
+ failureReason: "external_interruption"
90799
+ });
90800
+ }
90719
90801
  function buildVideoExtractionStageError(result) {
90720
90802
  if (result.success && result.errors.length === 0) return null;
90721
90803
  const counts = /* @__PURE__ */ new Map();
@@ -90753,6 +90835,15 @@ function isHdrProbeFailure(failure) {
90753
90835
  }
90754
90836
  function throwHdrProbeFailures(failures, mode) {
90755
90837
  if (failures.length === 0) return;
90838
+ const interrupted = failures.find(
90839
+ (failure) => failure.classified.kind === "external_interruption"
90840
+ );
90841
+ if (interrupted) {
90842
+ throw encoderFailureError("Video HDR probe failed", {
90843
+ error: interrupted.error instanceof Error ? interrupted.error.message : String(interrupted.error),
90844
+ failureReason: "external_interruption"
90845
+ });
90846
+ }
90756
90847
  if (mode === "enforce") {
90757
90848
  throw buildHdrProbeStageError(failures.map((failure) => failure.classified));
90758
90849
  }
@@ -90885,6 +90976,7 @@ async function runExtractVideosStage(input) {
90885
90976
  );
90886
90977
  extractionResult.phaseBreakdown.transientRetries = (extractionResult.phaseBreakdown.transientRetries ?? 0) + hdrProbeTransientRetries;
90887
90978
  assertNotAborted();
90979
+ throwIfEncoderInterrupted(extractionResult);
90888
90980
  failureToEnforce = applyVideoExtractionFailurePolicy(extractionResult, extractionPolicy, log);
90889
90981
  materializeExtractedFramesForCompiledDir(extractionResult.extracted, compiledDir, {
90890
90982
  materializeSymlinks
@@ -90996,6 +91088,15 @@ async function runAudioStage(input) {
90996
91088
  };
90997
91089
  }
90998
91090
  assertNotAborted();
91091
+ const interrupted = audioResult.failures?.find(
91092
+ (failure) => failure.reason === "external_interruption"
91093
+ );
91094
+ if (interrupted) {
91095
+ throw encoderFailureError("Audio processing failed", {
91096
+ error: interrupted.detail,
91097
+ failureReason: "external_interruption"
91098
+ });
91099
+ }
90999
91100
  hasAudio = audioResult.success;
91000
91101
  audioFailures = audioResult.failures;
91001
91102
  if (!hasAudio) {
@@ -91941,9 +92042,10 @@ async function extractHdrVideoFrames(args) {
91941
92042
  srcPath,
91942
92043
  stderr: result.stderr.slice(-400)
91943
92044
  });
91944
- throw new Error(
91945
- `HDR frame extraction failed for video "${videoId}". Aborting render to avoid shipping black HDR layers.`
91946
- );
92045
+ throw encoderFailureError(`HDR frame extraction failed for video "${videoId}"`, {
92046
+ error: `Aborting render to avoid shipping black HDR layers: ${result.stderr.slice(-400)}`,
92047
+ failureReason: result.failureReason
92048
+ });
91947
92049
  }
91948
92050
  const frameSize = dims.width * dims.height * 6;
91949
92051
  const fd = openSync4(rawPath, constants2.O_RDONLY | NO_FOLLOW_FLAG);
@@ -92232,7 +92334,10 @@ function ensureFrameWritten(frameWritten, frameIndex, encoder) {
92232
92334
  if (frameWritten) return;
92233
92335
  const reason = encoder?.getExitError();
92234
92336
  const base2 = `Streaming encoder exited before frame ${frameIndex} was written`;
92235
- throw new Error(reason ? `${base2}: ${reason}` : base2);
92337
+ throw encoderFailureError(base2, {
92338
+ error: reason,
92339
+ failureReason: encoder?.getExitFailureReason?.()
92340
+ });
92236
92341
  }
92237
92342
  function cleanupEndedHdrVideos(args) {
92238
92343
  if (process.env.KEEP_TEMP === "1") return;
@@ -92737,7 +92842,7 @@ async function runCaptureStreamingStage(input) {
92737
92842
  streamingEncoderClosed = true;
92738
92843
  assertNotAborted();
92739
92844
  if (!encodeResult.success) {
92740
- throw new Error(`Streaming encode failed: ${encodeResult.error}`);
92845
+ throw encoderFailureError("Streaming encode failed", encodeResult);
92741
92846
  }
92742
92847
  return {
92743
92848
  success: true,
@@ -93671,7 +93776,7 @@ async function runCaptureHdrStage(input) {
93671
93776
  hdrEncoderClosed = true;
93672
93777
  assertNotAborted();
93673
93778
  if (!hdrEncodeResult.success) {
93674
- throw new Error(`HDR encode failed: ${hdrEncodeResult.error}`);
93779
+ throw encoderFailureError("HDR encode failed", hdrEncodeResult);
93675
93780
  }
93676
93781
  captureDurationMs = Date.now() - stageStart;
93677
93782
  encodeMs = hdrEncodeResult.durationMs;
@@ -93797,7 +93902,8 @@ async function encodeGifFromDir(framesDir, framePattern, outputPath, input) {
93797
93902
  durationMs: Date.now() - startTime,
93798
93903
  framesEncoded: 0,
93799
93904
  fileSize: 0,
93800
- error: formatFfmpegError(paletteResult.exitCode, paletteResult.stderr)
93905
+ error: formatFfmpegError(paletteResult.exitCode, paletteResult.stderr),
93906
+ failureReason: paletteResult.failureReason
93801
93907
  };
93802
93908
  }
93803
93909
  const gifResult = await runFfmpeg(buildGifPaletteuseArgs(argsInput), {
@@ -93811,7 +93917,8 @@ async function encodeGifFromDir(framesDir, framePattern, outputPath, input) {
93811
93917
  durationMs: Date.now() - startTime,
93812
93918
  framesEncoded: 0,
93813
93919
  fileSize: 0,
93814
- error: formatFfmpegError(gifResult.exitCode, gifResult.stderr)
93920
+ error: formatFfmpegError(gifResult.exitCode, gifResult.stderr),
93921
+ failureReason: gifResult.failureReason
93815
93922
  };
93816
93923
  }
93817
93924
  const fileSize = existsSync29(outputPath) ? statSync9(outputPath).size : 0;
@@ -93890,7 +93997,7 @@ async function runEncodeStage(input) {
93890
93997
  });
93891
93998
  assertNotAborted();
93892
93999
  if (!encodeResult2.success) {
93893
- throw new Error(`Encoding failed: ${encodeResult2.error}`);
94000
+ throw encoderFailureError("Encoding failed", encodeResult2);
93894
94001
  }
93895
94002
  return { encodeMs: Date.now() - stage5Start };
93896
94003
  }
@@ -93935,7 +94042,7 @@ async function runEncodeStage(input) {
93935
94042
  );
93936
94043
  assertNotAborted();
93937
94044
  if (!encodeResult.success) {
93938
- throw new Error(`Encoding failed: ${encodeResult.error}`);
94045
+ throw encoderFailureError("Encoding failed", encodeResult);
93939
94046
  }
93940
94047
  return { encodeMs: Date.now() - stage5Start };
93941
94048
  }
@@ -94078,7 +94185,8 @@ async function padOrTrimAudioToVideoFrameCount(input) {
94078
94185
  targetDurationSeconds,
94079
94186
  sourceDurationSeconds: audioInfo.durationSeconds,
94080
94187
  operation: plan2.operation,
94081
- error: ffmpegResult.error
94188
+ error: ffmpegResult.error,
94189
+ failureReason: ffmpegResult.failureReason
94082
94190
  };
94083
94191
  }
94084
94192
  }
@@ -94180,7 +94288,8 @@ async function defaultRunFfmpeg(args, signal) {
94180
94288
  if (result.success) return { success: true };
94181
94289
  return {
94182
94290
  success: false,
94183
- error: `[audioPadTrim] ${formatFfmpegError(result.exitCode, result.stderr)}`
94291
+ error: `[audioPadTrim] ${formatFfmpegError(result.exitCode, result.stderr)}`,
94292
+ failureReason: result.failureReason
94184
94293
  };
94185
94294
  }
94186
94295
  async function runFfprobeJson(args, signal) {
@@ -94237,11 +94346,12 @@ async function runAssembleStage(input) {
94237
94346
  const normalizeResult = await padOrTrimAudioToVideoFrameCount({
94238
94347
  videoPath: videoOnlyPath,
94239
94348
  audioPath: audioOutputPath,
94240
- outputPath: normalizedAudioPath
94349
+ outputPath: normalizedAudioPath,
94350
+ signal: abortSignal
94241
94351
  });
94242
94352
  assertNotAborted();
94243
94353
  if (!normalizeResult.success) {
94244
- throw new Error(`Audio duration normalization failed: ${normalizeResult.error}`);
94354
+ throw encoderFailureError("Audio duration normalization failed", normalizeResult);
94245
94355
  }
94246
94356
  const muxResult = await muxVideoWithAudio(
94247
94357
  videoOnlyPath,
@@ -94255,7 +94365,7 @@ async function runAssembleStage(input) {
94255
94365
  );
94256
94366
  assertNotAborted();
94257
94367
  if (!muxResult.success) {
94258
- throw new Error(`Audio muxing failed: ${muxResult.error}`);
94368
+ throw encoderFailureError("Audio muxing failed", muxResult);
94259
94369
  }
94260
94370
  } else {
94261
94371
  const faststartResult = await applyFaststart(
@@ -94267,7 +94377,7 @@ async function runAssembleStage(input) {
94267
94377
  );
94268
94378
  assertNotAborted();
94269
94379
  if (!faststartResult.success) {
94270
- throw new Error(`Faststart failed: ${faststartResult.error}`);
94380
+ throw encoderFailureError("Faststart failed", faststartResult);
94271
94381
  }
94272
94382
  }
94273
94383
  return { assembleMs: Date.now() - stage6Start };
@@ -94822,7 +94932,7 @@ function resolveParallelRouterRetryPlan(args) {
94822
94932
  };
94823
94933
  }
94824
94934
  function shouldRetryViaPinnedFallback(args) {
94825
- if (args.isCancellation) return false;
94935
+ if (args.isCancellation || args.isEncoderInterrupted) return false;
94826
94936
  if (args.isVerifyError) return true;
94827
94937
  return args.deWorkerInversion === "inverted" || args.deParallelRouter === "routed";
94828
94938
  }
@@ -95903,6 +96013,7 @@ async function executeRenderPipeline(input) {
95903
96013
  if (!shouldRetryViaPinnedFallback({
95904
96014
  isVerifyError,
95905
96015
  isCancellation,
96016
+ isEncoderInterrupted: err instanceof EncoderInterruptedError,
95906
96017
  deWorkerInversion,
95907
96018
  deParallelRouter
95908
96019
  }))
@@ -96254,6 +96365,12 @@ async function executeRenderPipeline(input) {
96254
96365
  await eventPublisher.flush();
96255
96366
  throw error instanceof RenderCancelledError ? error : new RenderCancelledError("render_cancelled");
96256
96367
  }
96368
+ if (error instanceof EncoderInterruptedError) {
96369
+ log.warn("[Render] encoder process interrupted by host lifecycle", {
96370
+ code: error.code,
96371
+ diagnostic: error.diagnosticMessage.slice(-2e3)
96372
+ });
96373
+ }
96257
96374
  const memoryGuidance = describeMemoryExhaustion(error, {
96258
96375
  width: captureCompositionWidth,
96259
96376
  height: captureCompositionHeight,
@@ -96770,7 +96887,8 @@ var SAFE_RENDER_ERROR_CODES = /* @__PURE__ */ new Set([
96770
96887
  "NOT_MEDIA_PAYLOAD",
96771
96888
  "INVALID_VIDEO_METADATA",
96772
96889
  "VIDEO_SOURCE_UNRENDERABLE",
96773
- "VIDEO_EXTRACTION_FAILED"
96890
+ "VIDEO_EXTRACTION_FAILED",
96891
+ "ENCODER_INTERRUPTED"
96774
96892
  ]);
96775
96893
  function extractSafeRenderErrorCode(error) {
96776
96894
  if (typeof error !== "object" || error === null || !("code" in error)) return void 0;
@@ -97589,8 +97707,8 @@ async function runFontLocalize(io, localize) {
97589
97707
  }
97590
97708
 
97591
97709
  // src/version.ts
97592
- var VERSION = true ? "0.8.21" : "0.0.0-dev";
97593
- var PRODUCER_VERSION = true ? "0.8.21" : "0.0.0-dev";
97710
+ var VERSION = true ? "0.8.22" : "0.0.0-dev";
97711
+ var PRODUCER_VERSION = true ? "0.8.22" : "0.0.0-dev";
97594
97712
 
97595
97713
  // src/fontLocalizeCli.ts
97596
97714
  async function readStdin() {
@@ -1,4 +1,4 @@
1
- "use strict";var HyperframesPlayer=(()=>{var ee=Object.defineProperty;var et=Object.getOwnPropertyDescriptor;var tt=Object.getOwnPropertyNames;var it=Object.prototype.hasOwnProperty;var rt=(r,e)=>{for(var t in e)ee(r,t,{get:e[t],enumerable:!0})},nt=(r,e,t,i)=>{if(e&&typeof e=="object"||typeof e=="function")for(let n of tt(e))!it.call(r,n)&&n!==t&&ee(r,n,{get:()=>e[n],enumerable:!(i=et(e,n))||i.enumerable});return r};var ot=r=>nt(ee({},"__esModule",{value:!0}),r);var Ht={};rt(Ht,{HyperframesPlayer:()=>K,SPEED_PRESETS:()=>re,formatSpeed:()=>O,formatTime:()=>q});function we(r){return r.hasRuntime||r.runtimeInjected?!1:!!(r.hasNestedCompositions||r.hasTimelines&&r.attempts>=5)}function P(r){return typeof r=="object"&&r!==null}function Ae(r){return P(r)&&typeof r.getDuration=="function"}function Ce(r){return P(r)&&typeof r.duration=="function"&&typeof r.time=="function"&&typeof r.seek=="function"&&typeof r.play=="function"&&typeof r.pause=="function"}var k="https://cdn.jsdelivr.net/npm/@hyperframes/core@0.8.21/dist/hyperframe.runtime.iife.js";function N(r){if(r===null)return null;let e=Number.parseInt(r,10);return Number.isFinite(e)&&e>0?e:null}function at(r){let e=r?.querySelector("[data-composition-id][data-width][data-height]")??r?.querySelector("[data-width][data-height]");if(!e)return null;let t=N(e.getAttribute("data-width")),i=N(e.getAttribute("data-height"));return t!==null&&i!==null?{width:t,height:i}:null}var W=class{constructor(e,t){this._iframe=e;this._callbacks=t}_iframe;_callbacks;_interval=null;_runtimeInjected=!1;get runtimeInjected(){return this._runtimeInjected}start(){this.stop(),this._runtimeInjected=!1;let e=0;this._interval=setInterval(()=>{e++;try{let t=this._iframe.contentWindow;if(!t)return;let i=!!(t.__hf||t.__player),n=!!(t.__timelines&&Object.keys(t.__timelines).length>0),o=!!this._iframe.contentDocument?.querySelector("[data-composition-src]");if(we({hasRuntime:i,hasTimelines:n,hasNestedCompositions:o,runtimeInjected:this._runtimeInjected,attempts:e})){this._injectRuntime();return}if(this._runtimeInjected&&!i)return;let d=this._resolvePlaybackDurationAdapter(t);if(d&&d.getDuration()>0){this.stop();let s=at(this._iframe.contentDocument);this._callbacks.onReady({duration:d.getDuration(),adapter:d,compositionSize:s});return}}catch{}e>=40&&(this.stop(),this._callbacks.onError("Composition timeline not found after 8s"))},200)}stop(){this._interval!==null&&(clearInterval(this._interval),this._interval=null)}resolveDirectTimelineAdapter(){try{let e=this._iframe.contentWindow;return e?this._resolveDirectTimelineAdapterFromWindow(e):null}catch{return null}}resolveDirectTimelineAdapterFromWindow(e){return this._resolveDirectTimelineAdapterFromWindow(e)}hasRuntimeBridge(e){return Reflect.get(e,"__hf")!==void 0||P(Reflect.get(e,"__player"))}_injectRuntime(){this._runtimeInjected=!0;try{let e=this._iframe.contentDocument;if(!e)return;let t=e.createElement("script");t.src=k,(e.head||e.documentElement).appendChild(t),this._callbacks.onRuntimeInjected?.()}catch{}}_resolveDirectTimelineAdapterFromWindow(e){if(this.hasRuntimeBridge(e))return null;let t=Reflect.get(e,"__timelines");if(!P(t))return null;let i=Object.keys(t);if(i.length===0)return null;let n=this._iframe.contentDocument?.querySelector("[data-composition-id]")?.getAttribute("data-composition-id"),o=n&&n in t?n:i[i.length-1],d=t[o];return Ce(d)?d:null}_resolvePlaybackDurationAdapter(e){let t=Reflect.get(e,"__player");if(Ae(t))return{kind:"runtime",getDuration:()=>t.getDuration()};let i=this._resolveDirectTimelineAdapterFromWindow(e);return i?{kind:"direct-timeline",timeline:i,getDuration:()=>i.duration()}:null}};var Re=`
1
+ "use strict";var HyperframesPlayer=(()=>{var ee=Object.defineProperty;var et=Object.getOwnPropertyDescriptor;var tt=Object.getOwnPropertyNames;var it=Object.prototype.hasOwnProperty;var rt=(r,e)=>{for(var t in e)ee(r,t,{get:e[t],enumerable:!0})},nt=(r,e,t,i)=>{if(e&&typeof e=="object"||typeof e=="function")for(let n of tt(e))!it.call(r,n)&&n!==t&&ee(r,n,{get:()=>e[n],enumerable:!(i=et(e,n))||i.enumerable});return r};var ot=r=>nt(ee({},"__esModule",{value:!0}),r);var Ht={};rt(Ht,{HyperframesPlayer:()=>K,SPEED_PRESETS:()=>re,formatSpeed:()=>O,formatTime:()=>q});function we(r){return r.hasRuntime||r.runtimeInjected?!1:!!(r.hasNestedCompositions||r.hasTimelines&&r.attempts>=5)}function P(r){return typeof r=="object"&&r!==null}function Ae(r){return P(r)&&typeof r.getDuration=="function"}function Ce(r){return P(r)&&typeof r.duration=="function"&&typeof r.time=="function"&&typeof r.seek=="function"&&typeof r.play=="function"&&typeof r.pause=="function"}var k="https://cdn.jsdelivr.net/npm/@hyperframes/core@0.8.22/dist/hyperframe.runtime.iife.js";function N(r){if(r===null)return null;let e=Number.parseInt(r,10);return Number.isFinite(e)&&e>0?e:null}function at(r){let e=r?.querySelector("[data-composition-id][data-width][data-height]")??r?.querySelector("[data-width][data-height]");if(!e)return null;let t=N(e.getAttribute("data-width")),i=N(e.getAttribute("data-height"));return t!==null&&i!==null?{width:t,height:i}:null}var W=class{constructor(e,t){this._iframe=e;this._callbacks=t}_iframe;_callbacks;_interval=null;_runtimeInjected=!1;get runtimeInjected(){return this._runtimeInjected}start(){this.stop(),this._runtimeInjected=!1;let e=0;this._interval=setInterval(()=>{e++;try{let t=this._iframe.contentWindow;if(!t)return;let i=!!(t.__hf||t.__player),n=!!(t.__timelines&&Object.keys(t.__timelines).length>0),o=!!this._iframe.contentDocument?.querySelector("[data-composition-src]");if(we({hasRuntime:i,hasTimelines:n,hasNestedCompositions:o,runtimeInjected:this._runtimeInjected,attempts:e})){this._injectRuntime();return}if(this._runtimeInjected&&!i)return;let d=this._resolvePlaybackDurationAdapter(t);if(d&&d.getDuration()>0){this.stop();let s=at(this._iframe.contentDocument);this._callbacks.onReady({duration:d.getDuration(),adapter:d,compositionSize:s});return}}catch{}e>=40&&(this.stop(),this._callbacks.onError("Composition timeline not found after 8s"))},200)}stop(){this._interval!==null&&(clearInterval(this._interval),this._interval=null)}resolveDirectTimelineAdapter(){try{let e=this._iframe.contentWindow;return e?this._resolveDirectTimelineAdapterFromWindow(e):null}catch{return null}}resolveDirectTimelineAdapterFromWindow(e){return this._resolveDirectTimelineAdapterFromWindow(e)}hasRuntimeBridge(e){return Reflect.get(e,"__hf")!==void 0||P(Reflect.get(e,"__player"))}_injectRuntime(){this._runtimeInjected=!0;try{let e=this._iframe.contentDocument;if(!e)return;let t=e.createElement("script");t.src=k,(e.head||e.documentElement).appendChild(t),this._callbacks.onRuntimeInjected?.()}catch{}}_resolveDirectTimelineAdapterFromWindow(e){if(this.hasRuntimeBridge(e))return null;let t=Reflect.get(e,"__timelines");if(!P(t))return null;let i=Object.keys(t);if(i.length===0)return null;let n=this._iframe.contentDocument?.querySelector("[data-composition-id]")?.getAttribute("data-composition-id"),o=n&&n in t?n:i[i.length-1],d=t[o];return Ce(d)?d:null}_resolvePlaybackDurationAdapter(e){let t=Reflect.get(e,"__player");if(Ae(t))return{kind:"runtime",getDuration:()=>t.getDuration()};let i=this._resolveDirectTimelineAdapterFromWindow(e);return i?{kind:"direct-timeline",timeline:i,getDuration:()=>i.duration()}:null}};var Re=`
2
2
  :host {
3
3
  display: block;
4
4
  position: relative;
@@ -1,4 +1,4 @@
1
- var ve=Object.defineProperty;var be=(n,i,e)=>i in n?ve(n,i,{enumerable:!0,configurable:!0,writable:!0,value:e}):n[i]=e;var u=(n,i,e)=>be(n,typeof i!="symbol"?i+"":i,e);import{r as le,i as we,a as Ae}from"./index-CgGY8dAv.js";function Ee(n){return n.hasRuntime||n.runtimeInjected?!1:!!(n.hasNestedCompositions||n.hasTimelines&&n.attempts>=5)}function V(n){return typeof n=="object"&&n!==null}function Ce(n){return V(n)&&typeof n.getDuration=="function"}function Te(n){return V(n)&&typeof n.duration=="function"&&typeof n.time=="function"&&typeof n.seek=="function"&&typeof n.play=="function"&&typeof n.pause=="function"}function Se(n){if(!/^\d+\.\d+\.\d+(?:-[0-9A-Za-z.-]+)?(?:\+[0-9A-Za-z.-]+)?$/.test(n))throw new Error(`Invalid HyperFrames runtime version: ${n}`);return`https://cdn.jsdelivr.net/npm/@hyperframes/core@${n}/dist/hyperframe.runtime.iife.js`}const H=typeof __HYPERFRAMES_RUNTIME_CDN_URL__=="string"?__HYPERFRAMES_RUNTIME_CDN_URL__:Se("0.0.0-dev");function $(n){if(n===null)return null;const i=Number.parseInt(n,10);return Number.isFinite(i)&&i>0?i:null}function Re(n){const i=(n==null?void 0:n.querySelector("[data-composition-id][data-width][data-height]"))??(n==null?void 0:n.querySelector("[data-width][data-height]"));if(!i)return null;const e=$(i.getAttribute("data-width")),t=$(i.getAttribute("data-height"));return e!==null&&t!==null?{width:e,height:t}:null}class xe{constructor(i,e){u(this,"_interval",null);u(this,"_runtimeInjected",!1);this._iframe=i,this._callbacks=e}get runtimeInjected(){return this._runtimeInjected}start(){this.stop(),this._runtimeInjected=!1;let i=0;this._interval=setInterval(()=>{var e;i++;try{const t=this._iframe.contentWindow;if(!t)return;const r=!!(t.__hf||t.__player),s=!!(t.__timelines&&Object.keys(t.__timelines).length>0),o=!!((e=this._iframe.contentDocument)!=null&&e.querySelector("[data-composition-src]"));if(Ee({hasRuntime:r,hasTimelines:s,hasNestedCompositions:o,runtimeInjected:this._runtimeInjected,attempts:i})){this._injectRuntime();return}if(this._runtimeInjected&&!r)return;const d=this._resolvePlaybackDurationAdapter(t);if(d&&d.getDuration()>0){this.stop();const p=Re(this._iframe.contentDocument);this._callbacks.onReady({duration:d.getDuration(),adapter:d,compositionSize:p});return}}catch{}i>=40&&(this.stop(),this._callbacks.onError("Composition timeline not found after 8s"))},200)}stop(){this._interval!==null&&(clearInterval(this._interval),this._interval=null)}resolveDirectTimelineAdapter(){try{const i=this._iframe.contentWindow;return i?this._resolveDirectTimelineAdapterFromWindow(i):null}catch{return null}}resolveDirectTimelineAdapterFromWindow(i){return this._resolveDirectTimelineAdapterFromWindow(i)}hasRuntimeBridge(i){return Reflect.get(i,"__hf")!==void 0||V(Reflect.get(i,"__player"))}_injectRuntime(){var i,e;this._runtimeInjected=!0;try{const t=this._iframe.contentDocument;if(!t)return;const r=t.createElement("script");r.src=H,(t.head||t.documentElement).appendChild(r),(e=(i=this._callbacks).onRuntimeInjected)==null||e.call(i)}catch{}}_resolveDirectTimelineAdapterFromWindow(i){var d,p;if(this.hasRuntimeBridge(i))return null;const e=Reflect.get(i,"__timelines");if(!V(e))return null;const t=Object.keys(e);if(t.length===0)return null;const r=(p=(d=this._iframe.contentDocument)==null?void 0:d.querySelector("[data-composition-id]"))==null?void 0:p.getAttribute("data-composition-id"),s=r&&r in e?r:t[t.length-1],o=e[s];return Te(o)?o:null}_resolvePlaybackDurationAdapter(i){const e=Reflect.get(i,"__player");if(Ce(e))return{kind:"runtime",getDuration:()=>e.getDuration()};const t=this._resolveDirectTimelineAdapterFromWindow(i);return t?{kind:"direct-timeline",timeline:t,getDuration:()=>t.duration()}:null}}const Me=`
1
+ var ve=Object.defineProperty;var be=(n,i,e)=>i in n?ve(n,i,{enumerable:!0,configurable:!0,writable:!0,value:e}):n[i]=e;var u=(n,i,e)=>be(n,typeof i!="symbol"?i+"":i,e);import{r as le,i as we,a as Ae}from"./index-BIf0zQNt.js";function Ee(n){return n.hasRuntime||n.runtimeInjected?!1:!!(n.hasNestedCompositions||n.hasTimelines&&n.attempts>=5)}function V(n){return typeof n=="object"&&n!==null}function Ce(n){return V(n)&&typeof n.getDuration=="function"}function Te(n){return V(n)&&typeof n.duration=="function"&&typeof n.time=="function"&&typeof n.seek=="function"&&typeof n.play=="function"&&typeof n.pause=="function"}function Se(n){if(!/^\d+\.\d+\.\d+(?:-[0-9A-Za-z.-]+)?(?:\+[0-9A-Za-z.-]+)?$/.test(n))throw new Error(`Invalid HyperFrames runtime version: ${n}`);return`https://cdn.jsdelivr.net/npm/@hyperframes/core@${n}/dist/hyperframe.runtime.iife.js`}const H=typeof __HYPERFRAMES_RUNTIME_CDN_URL__=="string"?__HYPERFRAMES_RUNTIME_CDN_URL__:Se("0.0.0-dev");function $(n){if(n===null)return null;const i=Number.parseInt(n,10);return Number.isFinite(i)&&i>0?i:null}function Re(n){const i=(n==null?void 0:n.querySelector("[data-composition-id][data-width][data-height]"))??(n==null?void 0:n.querySelector("[data-width][data-height]"));if(!i)return null;const e=$(i.getAttribute("data-width")),t=$(i.getAttribute("data-height"));return e!==null&&t!==null?{width:e,height:t}:null}class xe{constructor(i,e){u(this,"_interval",null);u(this,"_runtimeInjected",!1);this._iframe=i,this._callbacks=e}get runtimeInjected(){return this._runtimeInjected}start(){this.stop(),this._runtimeInjected=!1;let i=0;this._interval=setInterval(()=>{var e;i++;try{const t=this._iframe.contentWindow;if(!t)return;const r=!!(t.__hf||t.__player),s=!!(t.__timelines&&Object.keys(t.__timelines).length>0),o=!!((e=this._iframe.contentDocument)!=null&&e.querySelector("[data-composition-src]"));if(Ee({hasRuntime:r,hasTimelines:s,hasNestedCompositions:o,runtimeInjected:this._runtimeInjected,attempts:i})){this._injectRuntime();return}if(this._runtimeInjected&&!r)return;const d=this._resolvePlaybackDurationAdapter(t);if(d&&d.getDuration()>0){this.stop();const p=Re(this._iframe.contentDocument);this._callbacks.onReady({duration:d.getDuration(),adapter:d,compositionSize:p});return}}catch{}i>=40&&(this.stop(),this._callbacks.onError("Composition timeline not found after 8s"))},200)}stop(){this._interval!==null&&(clearInterval(this._interval),this._interval=null)}resolveDirectTimelineAdapter(){try{const i=this._iframe.contentWindow;return i?this._resolveDirectTimelineAdapterFromWindow(i):null}catch{return null}}resolveDirectTimelineAdapterFromWindow(i){return this._resolveDirectTimelineAdapterFromWindow(i)}hasRuntimeBridge(i){return Reflect.get(i,"__hf")!==void 0||V(Reflect.get(i,"__player"))}_injectRuntime(){var i,e;this._runtimeInjected=!0;try{const t=this._iframe.contentDocument;if(!t)return;const r=t.createElement("script");r.src=H,(t.head||t.documentElement).appendChild(r),(e=(i=this._callbacks).onRuntimeInjected)==null||e.call(i)}catch{}}_resolveDirectTimelineAdapterFromWindow(i){var d,p;if(this.hasRuntimeBridge(i))return null;const e=Reflect.get(i,"__timelines");if(!V(e))return null;const t=Object.keys(e);if(t.length===0)return null;const r=(p=(d=this._iframe.contentDocument)==null?void 0:d.querySelector("[data-composition-id]"))==null?void 0:p.getAttribute("data-composition-id"),s=r&&r in e?r:t[t.length-1],o=e[s];return Te(o)?o:null}_resolvePlaybackDurationAdapter(i){const e=Reflect.get(i,"__player");if(Ce(e))return{kind:"runtime",getDuration:()=>e.getDuration()};const t=this._resolveDirectTimelineAdapterFromWindow(i);return t?{kind:"direct-timeline",timeline:t,getDuration:()=>t.duration()}:null}}const Me=`
2
2
  :host {
3
3
  display: block;
4
4
  position: relative;