@poe-platform/safe-bash 0.1.835 → 0.1.837

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.
@@ -12,7 +12,7 @@ import {
12
12
  probeOggStreamMetadata,
13
13
  scanMp4Frames,
14
14
  scanMp4Packets
15
- } from "./chunk-GQQUZGIZ.js";
15
+ } from "./chunk-FH5VMAPS.js";
16
16
 
17
17
  // packages/safe-bash-command-ffprobe/src/probe-text.ts
18
18
  import { yieldTurn } from "../../safe-bash-contracts/yield.js";
@@ -20,7 +20,7 @@ import {
20
20
  sliceMp4,
21
21
  srtAst,
22
22
  webvttAst
23
- } from "../safe-bash/command-chunks/chunk-GQQUZGIZ.js";
23
+ } from "../safe-bash/command-chunks/chunk-FH5VMAPS.js";
24
24
  import "../safe-bash/command-chunks/chunk-65DS4IOB.js";
25
25
 
26
26
  // packages/safe-bash-command-ffmpeg/src/index.ts
@@ -278,19 +278,22 @@ function* lavfiSteps(spec, budget, durationOverride) {
278
278
  )
279
279
  };
280
280
  }
281
- async function ensureDecodedFrames(track, budget, signal) {
282
- if (track.decodedVideoFrames && track.decodedVideoFrames.length > 0) {
283
- return [...track.decodedVideoFrames];
284
- }
281
+ async function ensureDecodedFrames(track, movieTimescale, budget, signal, maxFrames) {
285
282
  const width = track.width ?? track.codecDescriptions[0]?.width ?? 64;
286
283
  const height = track.height ?? track.codecDescriptions[0]?.height ?? 64;
287
284
  const ts = track.timescale || 9e4;
288
285
  const frames = [];
289
- for (const frame of decodeH264Samples(track.samples, track.codecDescriptions, width, height, ts)) {
286
+ const decoded = track.decodedVideoFrames ?? decodeH264Samples(track.samples, track.codecDescriptions, width, height, ts);
287
+ for (const frame of decoded) {
290
288
  await yieldTurn(signal);
291
289
  signal?.throwIfAborted();
292
- budget.recordFrame(frame.width, frame.height);
290
+ if (!track.decodedVideoFrames) budget.recordFrame(frame.width, frame.height);
291
+ const pts = Math.round(frame.ptsSeconds * ts);
292
+ if (track.editList?.length && !track.editList.some(
293
+ (edit) => edit.mediaTime >= 0 && pts >= edit.mediaTime && pts < edit.mediaTime + edit.segmentDuration * ts / movieTimescale
294
+ )) continue;
293
295
  frames.push(frame);
296
+ if (maxFrames !== void 0 && frames.length >= maxFrames) break;
294
297
  }
295
298
  return frames;
296
299
  }
@@ -942,6 +945,8 @@ function evalSyncFfmpeg(inBytesOrArgs, maybeArgs, readFileSync, writeFileSync) {
942
945
  const plugin = registry.detect(rawBytes, inp.path, inp.format);
943
946
  if (!plugin || !plugin.canDemux) return void 0;
944
947
  doc = plugin.parse(rawBytes, { filename: inp.path, budget });
948
+ const imageOutput = (outputFormat ? registry.findByFormatName(outputFormat) : registry.findByFilename(outputTarget))?.id === "image2";
949
+ if ((imageOutput || maxVideoFrames !== void 0) && doc.tracks.some((track) => track.type === "video" && !track.decodedVideoFrames)) return void 0;
945
950
  }
946
951
  if (inp.startSeconds !== void 0 || inp.endSeconds !== void 0 || inp.durationSeconds !== void 0) {
947
952
  doc = sliceMp4(doc, { startSeconds: inp.startSeconds, endSeconds: inp.endSeconds, durationSeconds: inp.durationSeconds });
@@ -1449,11 +1454,13 @@ function createFfmpegCommand(options = {}) {
1449
1454
  } else if (filterComplex.includes("xfade") && loadedDocs.length >= 2) {
1450
1455
  const f0 = await ensureDecodedFrames(
1451
1456
  loadedDocs[0].tracks.find((t) => t.type === "video"),
1457
+ loadedDocs[0].timescale,
1452
1458
  budget,
1453
1459
  context.signal
1454
1460
  );
1455
1461
  const f1 = await ensureDecodedFrames(
1456
1462
  loadedDocs[1].tracks.find((t) => t.type === "video"),
1463
+ loadedDocs[1].timescale,
1457
1464
  budget,
1458
1465
  context.signal
1459
1466
  );
@@ -1507,11 +1514,13 @@ function createFfmpegCommand(options = {}) {
1507
1514
  } else if (filterComplex.includes("vstack") && loadedDocs.length >= 2) {
1508
1515
  const f0 = await ensureDecodedFrames(
1509
1516
  loadedDocs[0].tracks.find((t) => t.type === "video"),
1517
+ loadedDocs[0].timescale,
1510
1518
  budget,
1511
1519
  context.signal
1512
1520
  );
1513
1521
  const f1 = await ensureDecodedFrames(
1514
1522
  loadedDocs[1].tracks.find((t) => t.type === "video"),
1523
+ loadedDocs[1].timescale,
1515
1524
  budget,
1516
1525
  context.signal
1517
1526
  );
@@ -1553,11 +1562,13 @@ function createFfmpegCommand(options = {}) {
1553
1562
  } else if (filterComplex.includes("hstack") && loadedDocs.length >= 2) {
1554
1563
  const f0 = await ensureDecodedFrames(
1555
1564
  loadedDocs[0].tracks.find((t) => t.type === "video"),
1565
+ loadedDocs[0].timescale,
1556
1566
  budget,
1557
1567
  context.signal
1558
1568
  );
1559
1569
  const f1 = await ensureDecodedFrames(
1560
1570
  loadedDocs[1].tracks.find((t) => t.type === "video"),
1571
+ loadedDocs[1].timescale,
1561
1572
  budget,
1562
1573
  context.signal
1563
1574
  );
@@ -1599,11 +1610,13 @@ function createFfmpegCommand(options = {}) {
1599
1610
  } else if (filterComplex.includes("overlay") && loadedDocs.length >= 2) {
1600
1611
  const f0 = await ensureDecodedFrames(
1601
1612
  loadedDocs[0].tracks.find((t) => t.type === "video"),
1613
+ loadedDocs[0].timescale,
1602
1614
  budget,
1603
1615
  context.signal
1604
1616
  );
1605
1617
  const f1 = await ensureDecodedFrames(
1606
1618
  loadedDocs[1].tracks.find((t) => t.type === "video"),
1619
+ loadedDocs[1].timescale,
1607
1620
  budget,
1608
1621
  context.signal
1609
1622
  );
@@ -1689,20 +1702,16 @@ function createFfmpegCommand(options = {}) {
1689
1702
  if (outputFps && videoCodec !== "copy") {
1690
1703
  vfFilters.push(`fps=${outputFps}`);
1691
1704
  }
1692
- if (maxVideoFrames !== void 0 && !vfFilters.some((f) => /\b(fps|select|reverse|trim|tile|setpts)\b/i.test(f))) {
1705
+ const imageOutput = (outputFormat ? registry.findByFormatName(outputFormat) : registry.findByFilename(outputTarget))?.id === "image2";
1706
+ if (imageOutput || maxVideoFrames !== void 0 && videoCodec !== "copy") {
1693
1707
  workingDoc = {
1694
1708
  ...workingDoc,
1695
- tracks: workingDoc.tracks.map((t) => {
1696
- if (t.type !== "video") return t;
1697
- if (t.decodedVideoFrames && t.decodedVideoFrames.length > maxVideoFrames) {
1698
- return { ...t, samples: [], decodedVideoFrames: t.decodedVideoFrames.slice(0, maxVideoFrames) };
1699
- }
1700
- if (t.samples.length > maxVideoFrames) {
1701
- const slicedSamples = t.samples.slice(0, maxVideoFrames);
1702
- return { ...t, duration: slicedSamples.reduce((acc, s) => acc + s.duration, 0), samples: slicedSamples };
1703
- }
1704
- return t;
1705
- })
1709
+ tracks: await mapWork(workingDoc.tracks, async (track) => {
1710
+ if (track.type !== "video") return track;
1711
+ const limit = vfFilters.length === 0 ? maxVideoFrames : void 0;
1712
+ const frames = await ensureDecodedFrames(track, workingDoc.timescale, budget, context.signal, limit);
1713
+ return { ...track, samples: [], decodedVideoFrames: frames };
1714
+ }, context.signal)
1706
1715
  };
1707
1716
  }
1708
1717
  if (vfFilters.length > 0) {
@@ -1740,7 +1749,7 @@ function createFfmpegCommand(options = {}) {
1740
1749
  }
1741
1750
  }
1742
1751
  const offsetTicks = Math.round(presentationOffset * t.timescale);
1743
- const decoded = await ensureDecodedFrames(t, budget, context.signal);
1752
+ const decoded = await ensureDecodedFrames(t, workingDoc.timescale, budget, context.signal);
1744
1753
  const displayed = decoded.map((frame) => ({ ...frame, ptsSeconds: (Math.round(frame.ptsSeconds * t.timescale) - offsetTicks) / t.timescale }));
1745
1754
  const filtered = await applyVideoFilterChain(displayed, combinedChain, budget, loadedSubtitleCues, context.signal);
1746
1755
  const first = filtered[0];
@@ -1954,6 +1963,9 @@ function createFfmpegCommand(options = {}) {
1954
1963
  options.onMetrics?.(budget.getStats());
1955
1964
  return { exitCode: 0 };
1956
1965
  }
1966
+ if (imageOutput && !workingDoc.tracks.some((track) => track.type === "video" && track.decodedVideoFrames?.length)) {
1967
+ throw new Error("No video frame in the requested presentation interval");
1968
+ }
1957
1969
  if (/%0?\d*d/.test(outputTarget)) {
1958
1970
  const outExt2 = outputTarget.split(".").pop()?.toLowerCase() ?? "png";
1959
1971
  const imgPlugin = registry.findByFilename(`x.${outExt2}`);
@@ -1961,7 +1973,7 @@ function createFfmpegCommand(options = {}) {
1961
1973
  throw new Error(`Unsupported output format for '${outputTarget}' (AST not registered)`);
1962
1974
  }
1963
1975
  const vTrack = workingDoc.tracks.find((t) => t.type === "video");
1964
- const frames = vTrack ? await ensureDecodedFrames(vTrack, budget, context.signal) : [];
1976
+ const frames = vTrack ? await ensureDecodedFrames(vTrack, workingDoc.timescale, budget, context.signal) : [];
1965
1977
  const limit = maxVideoFrames ? Math.min(frames.length, maxVideoFrames) : frames.length;
1966
1978
  const imgFmt = outExt2 === "jpg" || outExt2 === "jpeg" ? "jpeg" : outExt2 === "webp" ? "webp" : outExt2 === "gif" ? "gif" : outExt2 === "bmp" ? "bmp" : outExt2 === "ppm" ? "ppm" : "png";
1967
1979
  for (let idx = 0; idx < limit; idx++) {
@@ -1,8 +1,8 @@
1
1
  import {
2
2
  createFfprobeCommand
3
- } from "../safe-bash/command-chunks/chunk-THJIIMGT.js";
3
+ } from "../safe-bash/command-chunks/chunk-RSFKQE2U.js";
4
4
  import "../safe-bash/command-chunks/chunk-MGBHGZEX.js";
5
- import "../safe-bash/command-chunks/chunk-GQQUZGIZ.js";
5
+ import "../safe-bash/command-chunks/chunk-FH5VMAPS.js";
6
6
  import "../safe-bash/command-chunks/chunk-65DS4IOB.js";
7
7
 
8
8
  // packages/safe-bash-command-ffprobe/src/index.ts
@@ -11,9 +11,9 @@ import {
11
11
  loadManifestResources,
12
12
  resolvePath,
13
13
  rethrowRuntimeError
14
- } from "../safe-bash/command-chunks/chunk-THJIIMGT.js";
14
+ } from "../safe-bash/command-chunks/chunk-RSFKQE2U.js";
15
15
  import "../safe-bash/command-chunks/chunk-MGBHGZEX.js";
16
- import "../safe-bash/command-chunks/chunk-GQQUZGIZ.js";
16
+ import "../safe-bash/command-chunks/chunk-FH5VMAPS.js";
17
17
  import "../safe-bash/command-chunks/chunk-65DS4IOB.js";
18
18
  export {
19
19
  createFfprobeCommand,