@poe-platform/safe-bash 0.1.829 → 0.1.831
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/mp4-ast/codecs.d.ts +1 -0
- package/dist/mp4-ast/types.d.ts +1 -0
- package/dist/safe-bash/command-chunks/{chunk-MWPL7AFP.js → chunk-M3QUDUEM.js} +1 -1
- package/dist/safe-bash/command-chunks/{chunk-BXOBM4HJ.js → chunk-R6PMUP4E.js} +76 -24
- package/dist/safe-bash-command-ffmpeg/index.js +1 -1
- package/dist/safe-bash-command-ffprobe/index.js +2 -2
- package/dist/safe-bash-command-ffprobe/media.js +2 -2
- package/dist/safe-bash-command-imagemagick/index.js +2 -0
- package/package.json +2 -2
package/dist/mp4-ast/codecs.d.ts
CHANGED
|
@@ -18,6 +18,7 @@ export interface ParsedH264Sps {
|
|
|
18
18
|
readonly sarHeight: number;
|
|
19
19
|
readonly fps?: number | undefined;
|
|
20
20
|
readonly maxNumRefFrames: number;
|
|
21
|
+
readonly maxNumReorderFrames?: number | undefined;
|
|
21
22
|
}
|
|
22
23
|
export declare function parseH264Sps(nalu: Uint8Array): ParsedH264Sps;
|
|
23
24
|
export declare function parseAvcC(payload: Uint8Array): Mp4AvcCConfig;
|
package/dist/mp4-ast/types.d.ts
CHANGED
|
@@ -171,6 +171,7 @@ export interface MediaCodecDescription {
|
|
|
171
171
|
readonly codecTagString?: string | undefined;
|
|
172
172
|
readonly profile?: string | undefined;
|
|
173
173
|
readonly level?: number | undefined;
|
|
174
|
+
readonly maxNumReorderFrames?: number | undefined;
|
|
174
175
|
readonly width?: number | undefined;
|
|
175
176
|
readonly height?: number | undefined;
|
|
176
177
|
readonly pixFmt?: string | undefined;
|
|
@@ -12,7 +12,7 @@ import {
|
|
|
12
12
|
probeOggStreamMetadata,
|
|
13
13
|
scanMp4Frames,
|
|
14
14
|
scanMp4Packets
|
|
15
|
-
} from "./chunk-
|
|
15
|
+
} from "./chunk-R6PMUP4E.js";
|
|
16
16
|
|
|
17
17
|
// packages/safe-bash-command-ffprobe/src/probe-text.ts
|
|
18
18
|
import { yieldTurn } from "../../safe-bash-contracts/yield.js";
|
|
@@ -332075,6 +332075,7 @@ function parseH264Sps(nalu) {
|
|
|
332075
332075
|
let sarWidth = 1;
|
|
332076
332076
|
let sarHeight = 1;
|
|
332077
332077
|
let fps;
|
|
332078
|
+
let maxNumReorderFrames;
|
|
332078
332079
|
const vuiPresent = bits.readBit();
|
|
332079
332080
|
if (vuiPresent && bits.bitsRemaining > 0) {
|
|
332080
332081
|
const aspectRatioInfoPresent = bits.readBit();
|
|
@@ -332108,10 +332109,34 @@ function parseH264Sps(nalu) {
|
|
|
332108
332109
|
if (timingInfoPresent && bits.bitsRemaining >= 64) {
|
|
332109
332110
|
const numUnitsInTick = bits.readBits(32);
|
|
332110
332111
|
const timeScale = bits.readBits(32);
|
|
332112
|
+
bits.readBit();
|
|
332111
332113
|
if (numUnitsInTick > 0 && timeScale > 0) {
|
|
332112
332114
|
fps = timeScale / (2 * numUnitsInTick);
|
|
332113
332115
|
}
|
|
332114
332116
|
}
|
|
332117
|
+
let hrdPresent = false;
|
|
332118
|
+
for (let kind = 0; kind < 2; kind++) {
|
|
332119
|
+
if (!bits.readBit()) continue;
|
|
332120
|
+
hrdPresent = true;
|
|
332121
|
+
const cpbCount = bits.readUE() + 1;
|
|
332122
|
+
bits.readBits(8);
|
|
332123
|
+
for (let i = 0; i < cpbCount && bits.bitsRemaining > 0; i++) {
|
|
332124
|
+
bits.readUE();
|
|
332125
|
+
bits.readUE();
|
|
332126
|
+
bits.readBit();
|
|
332127
|
+
}
|
|
332128
|
+
bits.readBits(20);
|
|
332129
|
+
}
|
|
332130
|
+
if (hrdPresent) bits.readBit();
|
|
332131
|
+
bits.readBit();
|
|
332132
|
+
if (bits.readBit()) {
|
|
332133
|
+
bits.readBit();
|
|
332134
|
+
bits.readUE();
|
|
332135
|
+
bits.readUE();
|
|
332136
|
+
bits.readUE();
|
|
332137
|
+
bits.readUE();
|
|
332138
|
+
maxNumReorderFrames = bits.readUE();
|
|
332139
|
+
}
|
|
332115
332140
|
}
|
|
332116
332141
|
let profileName = H264_PROFILES[profileIdc] ?? `Profile ${profileIdc}`;
|
|
332117
332142
|
if (profileIdc === 66 && (constraintFlags & 64) !== 0) {
|
|
@@ -332135,7 +332160,8 @@ function parseH264Sps(nalu) {
|
|
|
332135
332160
|
sarWidth,
|
|
332136
332161
|
sarHeight,
|
|
332137
332162
|
fps,
|
|
332138
|
-
maxNumRefFrames
|
|
332163
|
+
maxNumRefFrames,
|
|
332164
|
+
maxNumReorderFrames
|
|
332139
332165
|
};
|
|
332140
332166
|
}
|
|
332141
332167
|
function parseAvcC(payload) {
|
|
@@ -332895,6 +332921,7 @@ function applyCodecMetadata(state, child) {
|
|
|
332895
332921
|
metadata.level = child.levelIdc;
|
|
332896
332922
|
if (child.sps) {
|
|
332897
332923
|
const sps = parseH264Sps(child.sps);
|
|
332924
|
+
metadata.maxNumReorderFrames = sps.maxNumReorderFrames;
|
|
332898
332925
|
metadata.profile = sps.profileName;
|
|
332899
332926
|
metadata.width = sps.width || metadata.width;
|
|
332900
332927
|
metadata.height = sps.height || metadata.height;
|
|
@@ -333036,7 +333063,7 @@ function buildProbeStream(track, desc, stats, idx, containerFormat) {
|
|
|
333036
333063
|
height: h,
|
|
333037
333064
|
coded_width: w ? Math.ceil(w / 16) * 16 : void 0,
|
|
333038
333065
|
coded_height: h ? Math.ceil(h / 16) * 16 : void 0,
|
|
333039
|
-
has_b_frames: track.type === "video" ? stats.hasCts ? 1 : 0 : void 0,
|
|
333066
|
+
has_b_frames: track.type === "video" ? desc?.maxNumReorderFrames ?? (stats.hasCts ? 1 : 0) : void 0,
|
|
333040
333067
|
sample_aspect_ratio: track.type === "video" ? `${desc?.sarWidth ?? 1}:${desc?.sarHeight ?? 1}` : void 0,
|
|
333041
333068
|
display_aspect_ratio: track.type === "video" && w && h ? `${w / darGcd}:${h / darGcd}` : void 0,
|
|
333042
333069
|
pix_fmt: track.type === "video" ? desc?.pixFmt ?? "yuv420p" : void 0,
|
|
@@ -334937,15 +334964,31 @@ function buildProbeResultFromDoc(doc, byteLength, filename = "input.mp4", option
|
|
|
334937
334964
|
const streams = [];
|
|
334938
334965
|
const packets = [];
|
|
334939
334966
|
const frames = [];
|
|
334967
|
+
let formatStart = Infinity, formatEnd = -Infinity;
|
|
334940
334968
|
for (let idx = 0; idx < doc.tracks.length; idx++) {
|
|
334941
334969
|
const track = doc.tracks[idx];
|
|
334942
334970
|
const materialized = materializeTrackSamples(track);
|
|
334943
334971
|
const desc = materialized.codecDescriptions[0];
|
|
334944
|
-
|
|
334972
|
+
let firstPts = materialized.samples[0]?.pts ?? 0;
|
|
334973
|
+
if (track.editList?.length) {
|
|
334974
|
+
let delay = 0;
|
|
334975
|
+
for (const edit of track.editList) {
|
|
334976
|
+
if (edit.mediaTime >= 0) break;
|
|
334977
|
+
delay += edit.segmentDuration;
|
|
334978
|
+
}
|
|
334979
|
+
firstPts = Math.round(delay * track.timescale / Math.max(1, doc.timescale));
|
|
334980
|
+
}
|
|
334981
|
+
const duration2 = Math.max(0, track.duration - (track.editList?.length ? firstPts : 0));
|
|
334982
|
+
if (doc.containerFormat === "mp4" || doc.containerFormat === "mov") {
|
|
334983
|
+
const start = firstPts / Math.max(1, track.timescale);
|
|
334984
|
+
formatStart = Math.min(formatStart, start);
|
|
334985
|
+
formatEnd = Math.max(formatEnd, start + duration2 / Math.max(1, track.timescale));
|
|
334986
|
+
}
|
|
334987
|
+
const stream = buildProbeStream({ ...track, duration: duration2 }, desc, {
|
|
334945
334988
|
totalBytes: materialized.samples.reduce((total, sample) => total + sample.size, 0),
|
|
334946
334989
|
count: materialized.samples.length,
|
|
334947
334990
|
ticks: materialized.samples.reduce((total, sample) => total + sample.duration, 0),
|
|
334948
|
-
firstPts
|
|
334991
|
+
firstPts,
|
|
334949
334992
|
hasCts: materialized.samples.some((sample) => sample.cts !== 0)
|
|
334950
334993
|
}, idx, doc.containerFormat);
|
|
334951
334994
|
streams.push(stream);
|
|
@@ -335008,7 +335051,9 @@ function buildProbeResultFromDoc(doc, byteLength, filename = "input.mp4", option
|
|
|
335008
335051
|
const value = doc.metadata[key];
|
|
335009
335052
|
if (value) formatTags[key] = value;
|
|
335010
335053
|
}
|
|
335011
|
-
const
|
|
335054
|
+
const startTime = Number.isFinite(formatStart) ? formatStart : 0;
|
|
335055
|
+
const duration = Number.isFinite(formatEnd) ? Math.max(0, formatEnd - startTime) : doc.durationSeconds;
|
|
335056
|
+
const overallBitRate = duration > 0 ? String(Math.round(byteLength * 8 / duration)) : "0";
|
|
335012
335057
|
return {
|
|
335013
335058
|
streams,
|
|
335014
335059
|
format: {
|
|
@@ -335017,8 +335062,8 @@ function buildProbeResultFromDoc(doc, byteLength, filename = "input.mp4", option
|
|
|
335017
335062
|
nb_programs: 0,
|
|
335018
335063
|
format_name: options.formatName ?? "mov,mp4,m4a,3gp,3g2,mj2",
|
|
335019
335064
|
format_long_name: options.formatLongName ?? "QuickTime / MOV",
|
|
335020
|
-
start_time:
|
|
335021
|
-
duration:
|
|
335065
|
+
start_time: startTime.toFixed(6),
|
|
335066
|
+
duration: duration.toFixed(6),
|
|
335022
335067
|
size: String(byteLength),
|
|
335023
335068
|
bit_rate: overallBitRate,
|
|
335024
335069
|
probe_score: 100,
|
|
@@ -339872,7 +339917,7 @@ async function* scanProbeRecords(source, options, mode) {
|
|
|
339872
339917
|
movieDuration = version === 1 ? movie.readU64BE() : movie.readU32BE();
|
|
339873
339918
|
}
|
|
339874
339919
|
const mvex = await first(moov, "mvex");
|
|
339875
|
-
let trackIndex = 0, maxDuration = movieDuration / Math.max(1, movieTimescale);
|
|
339920
|
+
let trackIndex = 0, maxDuration = movieDuration / Math.max(1, movieTimescale), formatStart = Infinity, formatEnd = -Infinity;
|
|
339876
339921
|
for await (const trak of scanMp4Boxes(source, { ...moov.children, ...work })) {
|
|
339877
339922
|
if (trak.type !== "trak") continue;
|
|
339878
339923
|
const index = trackIndex++;
|
|
@@ -339965,8 +340010,9 @@ async function* scanProbeRecords(source, options, mode) {
|
|
|
339965
340010
|
}
|
|
339966
340011
|
}
|
|
339967
340012
|
}
|
|
339968
|
-
let duration = 0, mediaEnd = 0, allPacked = true, count = 0;
|
|
340013
|
+
let duration = 0, mediaEnd = 0, allPacked = true, count = 0, firstPts = 0;
|
|
339969
340014
|
for await (const sample of samples()) {
|
|
340015
|
+
if (!count) firstPts = sample.pts;
|
|
339970
340016
|
count++;
|
|
339971
340017
|
duration += sample.duration;
|
|
339972
340018
|
mediaEnd = Math.max(mediaEnd, sample.pts + sample.duration);
|
|
@@ -339982,28 +340028,34 @@ async function* scanProbeRecords(source, options, mode) {
|
|
|
339982
340028
|
const version = header2.readU8();
|
|
339983
340029
|
header2.skip(3);
|
|
339984
340030
|
const count2 = header2.readU32BE(), width2 = version === 1 ? 20 : 12;
|
|
339985
|
-
let total = 0, entries = 0;
|
|
340031
|
+
let total = 0, entries = 0, delay = 0, foundMedia = false;
|
|
339986
340032
|
for (let i = 0; i < count2 && 8 + i * width2 < elst.payloadSize; i++) {
|
|
339987
340033
|
const row = new BinaryReader(yield { kind: "read", table: elst, offset: elst.payloadOffset + 8 + i * width2, length: Math.min(width2, elst.payloadSize - 8 - i * width2) });
|
|
339988
340034
|
let segment = version === 1 ? row.readU64BE() : row.readU32BE();
|
|
339989
340035
|
const mediaTime = version === 1 ? row.readI64BE() : row.readI32BE();
|
|
339990
340036
|
if (fragmented && segment === 0 && mediaTime >= 0) segment = Math.round(Math.max(0, mediaEnd - mediaTime) * movieTimescale / timescale);
|
|
340037
|
+
if (mediaTime >= 0) foundMedia = true;
|
|
340038
|
+
else if (!foundMedia) delay += segment;
|
|
339991
340039
|
total += segment;
|
|
339992
340040
|
entries++;
|
|
339993
340041
|
}
|
|
339994
|
-
return entries ? Math.round(total * timescale / movieTimescale) : void 0;
|
|
340042
|
+
return entries ? { duration: Math.round(total * timescale / movieTimescale), start: Math.round(delay * timescale / movieTimescale) } : void 0;
|
|
339995
340043
|
}
|
|
339996
340044
|
const edits = consumeMp4SampleSteps(source, editDuration(), sampleOptions), result = await edits.next();
|
|
339997
340045
|
if (!result.done) throw new Error("Unexpected MP4 edit sample");
|
|
339998
|
-
const trackDuration = result.value ?? (duration || declaredDuration || Math.round(headerDuration / Math.max(1, movieTimescale) * timescale));
|
|
340046
|
+
const trackDuration = result.value?.duration ?? (duration || declaredDuration || Math.round(headerDuration / Math.max(1, movieTimescale) * timescale));
|
|
339999
340047
|
maxDuration = Math.max(maxDuration, trackDuration / Math.max(1, timescale));
|
|
340000
340048
|
budget.checkDuration(maxDuration);
|
|
340049
|
+
const startPts = result.value?.start ?? (type === "subtitle" && count && !allPacked ? 0 : firstPts);
|
|
340050
|
+
const probeDuration = Math.max(0, trackDuration - (result.value?.start ?? 0));
|
|
340051
|
+
const start = startPts / Math.max(1, timescale);
|
|
340052
|
+
formatStart = Math.min(formatStart, start);
|
|
340053
|
+
formatEnd = Math.max(formatEnd, start + probeDuration / Math.max(1, timescale));
|
|
340001
340054
|
if (mode === "summary") continue;
|
|
340002
340055
|
let bytePos = 0, cursor = 0;
|
|
340003
|
-
const stats = { totalBytes: 0, count: 0, ticks: 0, firstPts:
|
|
340056
|
+
const stats = { totalBytes: 0, count: 0, ticks: 0, firstPts: startPts, hasCts: false };
|
|
340004
340057
|
const packet = (sample) => {
|
|
340005
340058
|
if (mode === "streams") {
|
|
340006
|
-
if (!stats.count) stats.firstPts = sample.pts;
|
|
340007
340059
|
stats.count++;
|
|
340008
340060
|
stats.totalBytes += sample.size;
|
|
340009
340061
|
stats.ticks += sample.duration;
|
|
@@ -340019,27 +340071,27 @@ async function* scanProbeRecords(source, options, mode) {
|
|
|
340019
340071
|
if (mode !== "streams") yield row2;
|
|
340020
340072
|
continue;
|
|
340021
340073
|
}
|
|
340022
|
-
const
|
|
340023
|
-
if (
|
|
340024
|
-
const row2 = packet({ pts: cursor, dts: cursor, duration:
|
|
340074
|
+
const start2 = Math.max(cursor, Math.round(sample.pts));
|
|
340075
|
+
if (start2 > cursor) {
|
|
340076
|
+
const row2 = packet({ pts: cursor, dts: cursor, duration: start2 - cursor, size: 2, isKeyframe: true });
|
|
340025
340077
|
if (mode !== "streams") yield row2;
|
|
340026
|
-
cursor =
|
|
340078
|
+
cursor = start2;
|
|
340027
340079
|
}
|
|
340028
340080
|
const duration2 = Math.max(1, Math.round(sample.duration));
|
|
340029
340081
|
const row = packet({ pts: cursor, dts: cursor, duration: duration2, size: sample.size + 2, isKeyframe: true });
|
|
340030
340082
|
if (mode !== "streams") yield row;
|
|
340031
340083
|
cursor += duration2;
|
|
340032
340084
|
}
|
|
340033
|
-
if (mode === "streams") yield buildProbeStream({ ...track, duration:
|
|
340085
|
+
if (mode === "streams") yield buildProbeStream({ ...track, duration: probeDuration }, codec, stats, index, "mp4");
|
|
340034
340086
|
}
|
|
340035
340087
|
budget.checkDuration(maxDuration);
|
|
340036
|
-
return { duration: maxDuration, tracks: trackIndex };
|
|
340088
|
+
return { duration: maxDuration, start: trackIndex ? formatStart : 0, presentationDuration: trackIndex ? Math.max(0, formatEnd - formatStart) : maxDuration, tracks: trackIndex };
|
|
340037
340089
|
}
|
|
340038
340090
|
async function probeMp4Source(source, options = {}) {
|
|
340039
340091
|
const work = { ...options, budget: options.budget ?? new MediaBudgetTracker(options.limits) };
|
|
340040
340092
|
const scan = scanProbeRecords(source, work, "summary"), summary = await scan.next();
|
|
340041
340093
|
if (!summary.done) throw new Error("Unexpected MP4 summary row");
|
|
340042
|
-
const { duration, tracks } = summary.value, metadata = await probeMp4MetadataSource(source, duration, work);
|
|
340094
|
+
const { duration, start, presentationDuration, tracks } = summary.value, metadata = await probeMp4MetadataSource(source, duration, work);
|
|
340043
340095
|
async function* streams() {
|
|
340044
340096
|
for await (const row of scanProbeRecords(source, work, "streams")) if (!("sample" in row)) yield row;
|
|
340045
340097
|
}
|
|
@@ -340051,10 +340103,10 @@ async function probeMp4Source(source, options = {}) {
|
|
|
340051
340103
|
nb_programs: 0,
|
|
340052
340104
|
format_name: "mov,mp4,m4a,3gp,3g2,mj2",
|
|
340053
340105
|
format_long_name: "QuickTime / MOV",
|
|
340054
|
-
start_time:
|
|
340055
|
-
duration:
|
|
340106
|
+
start_time: start.toFixed(6),
|
|
340107
|
+
duration: presentationDuration.toFixed(6),
|
|
340056
340108
|
size: String(source.size),
|
|
340057
|
-
bit_rate:
|
|
340109
|
+
bit_rate: presentationDuration > 0 ? String(Math.round(source.size * 8 / presentationDuration)) : "0",
|
|
340058
340110
|
probe_score: 100,
|
|
340059
340111
|
tags: metadata.tags
|
|
340060
340112
|
},
|
|
@@ -20,7 +20,7 @@ import {
|
|
|
20
20
|
sliceMp4,
|
|
21
21
|
srtAst,
|
|
22
22
|
webvttAst
|
|
23
|
-
} from "../safe-bash/command-chunks/chunk-
|
|
23
|
+
} from "../safe-bash/command-chunks/chunk-R6PMUP4E.js";
|
|
24
24
|
import "../safe-bash/command-chunks/chunk-65DS4IOB.js";
|
|
25
25
|
|
|
26
26
|
// packages/safe-bash-command-ffmpeg/src/index.ts
|
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
import {
|
|
2
2
|
createFfprobeCommand
|
|
3
|
-
} from "../safe-bash/command-chunks/chunk-
|
|
3
|
+
} from "../safe-bash/command-chunks/chunk-M3QUDUEM.js";
|
|
4
4
|
import "../safe-bash/command-chunks/chunk-MGBHGZEX.js";
|
|
5
|
-
import "../safe-bash/command-chunks/chunk-
|
|
5
|
+
import "../safe-bash/command-chunks/chunk-R6PMUP4E.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-
|
|
14
|
+
} from "../safe-bash/command-chunks/chunk-M3QUDUEM.js";
|
|
15
15
|
import "../safe-bash/command-chunks/chunk-MGBHGZEX.js";
|
|
16
|
-
import "../safe-bash/command-chunks/chunk-
|
|
16
|
+
import "../safe-bash/command-chunks/chunk-R6PMUP4E.js";
|
|
17
17
|
import "../safe-bash/command-chunks/chunk-65DS4IOB.js";
|
|
18
18
|
export {
|
|
19
19
|
createFfprobeCommand,
|
|
@@ -4321,6 +4321,8 @@ function* magickDrawSteps(img, drawCmd, state) {
|
|
|
4321
4321
|
} else if (cmd === "path") {
|
|
4322
4322
|
const d = tokens[i++] ?? "";
|
|
4323
4323
|
svgElements.push(`<path d="${escapeXml(d)}" fill="${fill}" stroke="${stroke}" stroke-width="${strokeWidth}"/>`);
|
|
4324
|
+
} else {
|
|
4325
|
+
throw new Error(`Unsupported drawing primitive: ${cmd}`);
|
|
4324
4326
|
}
|
|
4325
4327
|
}
|
|
4326
4328
|
if (svgElements.length > 0) yield { kind: "svg", svg: `<svg xmlns="http://www.w3.org/2000/svg" width="${img.width}" height="${img.height}">${svgElements.join("")}</svg>` };
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@poe-platform/safe-bash",
|
|
3
|
-
"version": "0.1.
|
|
3
|
+
"version": "0.1.831",
|
|
4
4
|
"description": "Extensible virtual shell with pluggable filesystems and streaming commands",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"license": "MIT",
|
|
@@ -1415,7 +1415,7 @@
|
|
|
1415
1415
|
"access": "public"
|
|
1416
1416
|
},
|
|
1417
1417
|
"dependencies": {
|
|
1418
|
-
"@poe-platform/safe-fs": "0.1.
|
|
1418
|
+
"@poe-platform/safe-fs": "0.1.831",
|
|
1419
1419
|
"pdf-lib": "1.17.1",
|
|
1420
1420
|
"@types/node": "^25.2.2",
|
|
1421
1421
|
"@formatjs/intl-numberformat": "9.4.0",
|