@poe-platform/safe-bash 0.1.809 → 0.1.810
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/audio-ast/index.d.ts +1 -1
- package/dist/audio-ast/index.js +6 -0
- package/dist/audio-ast/wav-source.d.ts +7 -1
- package/dist/image-ast/index.js +1 -1
- package/dist/pdf-ast/cos/mutable-object-store.d.ts +3 -0
- package/dist/pdf-ast/cos/qpdf-json-document.d.ts +42 -0
- package/dist/pdf-ast/cos/qpdf-json-values.d.ts +7 -0
- package/dist/pdf-ast/index.d.ts +1 -0
- package/dist/pdf-ast/index.js +508 -37
- package/dist/pdf-ast/retained-document.d.ts +3 -1
- package/dist/safe-bash/chunks/{chunk-RQCK77SC.js → chunk-65TFMAZU.js} +2 -2
- package/dist/safe-bash/chunks/{chunk-SOFBGDXG.js → chunk-HHSOUC3Z.js} +32 -0
- package/dist/safe-bash/chunks/{chunk-WAZEELYB.js → chunk-ZA5FQ34E.js} +10 -5
- package/dist/safe-bash/command-chunks/biff-ORSHM4YX-QYPGRDAZ.js +4937 -0
- package/dist/safe-bash/command-chunks/{chunk-62ZAHKFS.js → chunk-2VCKUNDZ.js} +130 -14
- package/dist/safe-bash/command-chunks/{chunk-GLVD3JJG.js → chunk-BYZUOF6X.js} +2858 -2816
- package/dist/safe-bash/command-chunks/{chunk-6OKH4X67.js → chunk-CAXJ4RLF.js} +264 -1
- package/dist/safe-bash/command-chunks/{chunk-YJJBGN7U.js → chunk-CHR2OD2U.js} +9 -9
- package/dist/safe-bash/command-chunks/{chunk-D7XBUF76.js → chunk-D2ASPM7R.js} +109 -23
- package/dist/safe-bash/command-chunks/chunk-D5AYP2UM.js +816 -0
- package/dist/safe-bash/command-chunks/{chunk-WFDG3N5R.js → chunk-ECDEPKKW.js} +1 -1
- package/dist/safe-bash/command-chunks/{chunk-OQCJGUI6.js → chunk-HARUYHH7.js} +10 -10
- package/dist/safe-bash/command-chunks/{chunk-NVBUC644.js → chunk-HKGNBH7Z.js} +2 -2
- package/dist/safe-bash/command-chunks/chunk-MGBHGZEX.js +12 -0
- package/dist/safe-bash/command-chunks/{chunk-4557HE3J.js → chunk-PMWW7KSB.js} +161 -42
- package/dist/safe-bash/command-chunks/{chunk-JW3KIZU6.js → chunk-RUXY7GN5.js} +1 -1
- package/dist/safe-bash/command-chunks/{chunk-KELMIFVV.js → chunk-TI52LKLL.js} +1 -1
- package/dist/safe-bash/command-chunks/{chunk-JJQ72P3V.js → chunk-VCML4T5D.js} +1 -1
- package/dist/safe-bash/command-chunks/{chunk-5HGEXQVD.js → chunk-WC2OCF4H.js} +1 -1
- package/dist/safe-bash/command-chunks/chunk-WH3TIOTS.js +326 -0
- package/dist/safe-bash/command-chunks/{chunk-45FI2IPY.js → chunk-WQ6ABTJU.js} +3 -6
- package/dist/safe-bash/command-chunks/{chunk-NB7JO7FE.js → chunk-YTFWPJ3F.js} +1 -1
- package/dist/safe-bash/command-chunks/{chunk-GKYCV6BU.js → chunk-ZEPDT6I5.js} +482 -168
- package/dist/safe-bash/command-chunks/{command-engine-P5DFM4OU.js → command-engine-BEWABZ75.js} +10 -3
- package/dist/safe-bash/command-chunks/{engine-RU4OFLPO-CPLFYD67.js → engine-MEPOXIXT-WZMRHACG.js} +1 -1
- package/dist/safe-bash/command-chunks/pdf-LOZAXXS6-ERI57IAV.js +557 -0
- package/dist/safe-bash/commands/audio/index.browser.js +2 -14
- package/dist/safe-bash/commands/diff-patch/index.js +0 -2
- package/dist/safe-bash/commands/ffprobe/index.browser.js +2 -5
- package/dist/safe-bash/commands/pandoc/index.browser.js +3 -1
- package/dist/safe-bash/commands/text.js +10 -1
- package/dist/safe-bash/core.d.ts +2 -2
- package/dist/safe-bash/core.js +2 -2
- package/dist/safe-bash/full-core.browser.js +18 -22
- package/dist/safe-bash/lazy-optional.d.ts +9 -0
- package/dist/safe-bash/lazy-optional.js +24 -0
- package/dist/safe-bash/plugins/index.browser.js +5 -3
- package/dist/safe-bash/registry-entry.browser.js +1 -1
- package/dist/safe-bash-command-apply-patch/apply.js +2 -2
- package/dist/safe-bash-command-apply-patch/index.js +2 -2
- package/dist/safe-bash-command-apply-patch/parser.d.ts +20 -1
- package/dist/safe-bash-command-apply-patch/parser.js +1 -1
- package/dist/safe-bash-command-ffprobe/index.js +2 -1
- package/dist/safe-bash-command-ffprobe/media.js +2 -1
- package/dist/safe-bash-command-ffprobe/options.d.ts +15 -0
- package/dist/safe-bash-command-ffprobe/options.js +7 -0
- package/dist/safe-bash-command-media/index.js +2 -2
- package/dist/safe-bash-command-media/plugin.js +1 -1
- package/dist/safe-bash-command-media/remote.js +2 -2
- package/dist/safe-bash-command-pandoc/command.js +6 -6
- package/dist/safe-bash-command-pandoc/index.js +31 -31
- package/dist/safe-bash-command-patch/index.js +2 -2
- package/dist/safe-bash-command-patch/patch-publication.d.ts +2 -2
- package/dist/safe-bash-command-patch/patch-publication.js +1 -1
- package/dist/safe-bash-command-patch/patch.js +2 -2
- package/dist/safe-bash-command-pptx/engine.js +1 -1
- package/dist/safe-bash-command-ssconvert/index.js +2 -2
- package/dist/safe-bash-command-xmllint/index.js +137 -30
- package/dist/safe-bash-compression-engine/bounded-codec.js +2 -2
- package/dist/safe-bash-compression-engine/codec-loader.js +1 -1
- package/dist/safe-bash-compression-engine/files.js +5 -5
- package/dist/safe-bash-compression-engine/index.js +4 -4
- package/dist/safe-bash-compression-engine/operand.js +5 -5
- package/dist/safe-bash-compression-engine/stream.js +4 -4
- package/dist/safe-bash-compression-engine/zstd-decode.js +3 -3
- package/dist/safe-bash-media-engine/imagemagick.d.ts +2 -0
- package/dist/safe-bash-media-engine/index.js +162 -72
- package/dist/safe-bash-network-engine/body.d.ts +1 -0
- package/dist/safe-bash-network-engine/body.js +1 -1
- package/dist/safe-bash-network-engine/transfer.js +11 -3
- package/dist/safe-bash-presentation-engine/command-placeholder.js +4 -3
- package/dist/safe-bash-presentation-engine/index.d.ts +1 -1
- package/dist/safe-bash-presentation-engine/index.js +9 -4
- package/dist/safe-bash-presentation-engine/presentation-model.js +3 -2
- package/dist/safe-bash-presentation-engine/retained-text.js +3 -3
- package/dist/safe-bash-presentation-engine/retained-xml-parts.d.ts +26 -0
- package/dist/safe-bash-presentation-engine/xml-parts.d.ts +1 -0
- package/dist/safe-bash-presentation-engine/xml-parts.js +7 -1
- package/dist/safe-bash-xml-engine/document.js +1 -1
- package/dist/safe-bash-xml-engine/index.js +1 -1
- package/dist/spreadsheet-engine/rendering/print/tab-layout.d.ts +11 -0
- package/dist/spreadsheet-engine/rendering/print/tab-layout.js +15 -0
- package/dist/spreadsheet-engine/rendering/print/text-lines.d.ts +2 -2
- package/dist/spreadsheet-engine/rendering/print/text-lines.js +3 -3
- package/dist/spreadsheet-format-xls/biff-encrypted-properties.d.ts +4 -0
- package/dist/spreadsheet-format-xls/biff-encrypted-properties.js +137 -56
- package/dist/spreadsheet-format-xls/biff-encryption.d.ts +1 -1
- package/dist/spreadsheet-format-xls/biff-encryption.js +8 -3
- package/dist/spreadsheet-format-xls/biff-property-bytes.d.ts +1 -1
- package/dist/spreadsheet-format-xls/biff-property-bytes.js +2 -2
- package/dist/spreadsheet-format-xls/biff.js +11 -3
- package/package.json +3 -2
- package/dist/safe-bash/chunks/chunk-I2A5ZCPD.js +0 -17
- package/dist/safe-bash/chunks/chunk-PQTT2EZP.js +0 -8
- package/dist/safe-bash/command-chunks/biff-DS263V2K-2GP4GZT7.js +0 -4868
- package/dist/safe-bash/command-chunks/chunk-6ZFYWT3U.js +0 -581
- package/dist/safe-bash/command-chunks/chunk-S244SWDH.js +0 -153
- package/dist/safe-bash/command-chunks/pdf-T7AWYZGQ-KNAYJ7YF.js +0 -552
- /package/dist/safe-bash/command-chunks/{chunk-EMMSXKEJ.js → chunk-4Q4R3VZU.js} +0 -0
|
@@ -1,3 +1,6 @@
|
|
|
1
|
+
import {
|
|
2
|
+
resolveFfprobeLimits
|
|
3
|
+
} from "./chunk-MGBHGZEX.js";
|
|
1
4
|
import {
|
|
2
5
|
MediaBudgetTracker,
|
|
3
6
|
allMediaAsts,
|
|
@@ -6,158 +9,102 @@ import {
|
|
|
6
9
|
parseStreamingManifest
|
|
7
10
|
} from "./chunk-DCD32BEY.js";
|
|
8
11
|
|
|
9
|
-
// packages/safe-bash-command-ffprobe/src/
|
|
10
|
-
import { PagedStorage } from "@poe-platform/safe-fs/storage";
|
|
11
|
-
import { writeBytes } from "../../safe-bash-contracts/io.js";
|
|
12
|
+
// packages/safe-bash-command-ffprobe/src/wav-tags.ts
|
|
13
|
+
import { IntegerTable, PagedStorage } from "@poe-platform/safe-fs/storage";
|
|
12
14
|
import { yieldTurn } from "../../safe-bash-contracts/yield.js";
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
high = "";
|
|
22
|
-
const last = text.charCodeAt(text.length - 1);
|
|
23
|
-
if (last >= 55296 && last <= 56319) {
|
|
24
|
-
high = text.at(-1);
|
|
25
|
-
text = text.slice(0, -1);
|
|
26
|
-
}
|
|
27
|
-
if (text) yield encoder.encode(text);
|
|
28
|
-
if (++steps % 256 === 0) await yieldTurn(signal);
|
|
29
|
-
}
|
|
15
|
+
var WavTags = class {
|
|
16
|
+
constructor(source, context) {
|
|
17
|
+
this.source = source;
|
|
18
|
+
this.context = context;
|
|
19
|
+
this.storage = new PagedStorage(context, 4);
|
|
20
|
+
this.close = this.storage.close.bind(this.storage);
|
|
21
|
+
this.keys = new IntegerTable(this.storage, 128);
|
|
22
|
+
this.numeric = new IntegerTable(this.storage, 128);
|
|
30
23
|
}
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
24
|
+
source;
|
|
25
|
+
context;
|
|
26
|
+
storage;
|
|
27
|
+
keys;
|
|
28
|
+
numeric;
|
|
29
|
+
head = 0;
|
|
30
|
+
tail = 0;
|
|
31
|
+
count = 0;
|
|
32
|
+
close;
|
|
33
|
+
async *decoded(offset, length) {
|
|
34
|
+
const decoder = new TextDecoder();
|
|
35
|
+
let steps = 0;
|
|
36
|
+
for (let at = 0; at < length; at += 16384) {
|
|
37
|
+
this.context.signal.throwIfAborted();
|
|
38
|
+
const bytes = await this.source.read(offset + at, Math.min(16384, length - at));
|
|
39
|
+
this.context.signal.throwIfAborted();
|
|
40
|
+
if (bytes.length !== Math.min(16384, length - at)) throw new Error("Truncated WAV tag");
|
|
41
|
+
yield decoder.decode(bytes, { stream: true });
|
|
42
|
+
if (++steps % 256 === 0) await yieldTurn(this.context.signal);
|
|
41
43
|
}
|
|
42
|
-
|
|
43
|
-
if (size === 0) await writeBytes(context.stdout, new Uint8Array(0), context.signal);
|
|
44
|
-
for (let offset = 0; offset < size; offset += 16384)
|
|
45
|
-
await writeBytes(context.stdout, await storage.read(start + offset, Math.min(16384, size - offset)), context.signal);
|
|
46
|
-
failed = false;
|
|
47
|
-
} finally {
|
|
48
|
-
if (failed) {
|
|
49
|
-
try {
|
|
50
|
-
await storage.close();
|
|
51
|
-
} catch {
|
|
52
|
-
}
|
|
53
|
-
} else await storage.close();
|
|
44
|
+
yield decoder.decode();
|
|
54
45
|
}
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
async function openProbeStream(context, path) {
|
|
63
|
-
context.signal.throwIfAborted();
|
|
64
|
-
if (path === void 0) return readBytes(context.stdin, context.signal);
|
|
65
|
-
const capabilities = await context.fs.capabilitiesFor?.(path, { signal: context.signal }) ?? context.fs.capabilities;
|
|
66
|
-
context.signal.throwIfAborted();
|
|
67
|
-
if (!context.fs.readStream || capabilities.streamingRead === false || context.fs.capabilities.streamingRead === false) return void 0;
|
|
68
|
-
return readFileStream(context.fs, path, { signal: context.signal, chunkSize: 16384 });
|
|
69
|
-
}
|
|
70
|
-
async function sniffWavStream(source, signal, account) {
|
|
71
|
-
const iterator = source[Symbol.asyncIterator](), prefix = new Uint8Array(12);
|
|
72
|
-
let size = 0, total = 0, ended = false;
|
|
73
|
-
let remainder = new Uint8Array(0);
|
|
74
|
-
try {
|
|
75
|
-
while (size < prefix.length) {
|
|
76
|
-
signal.throwIfAborted();
|
|
77
|
-
const next = await iterator.next();
|
|
78
|
-
signal.throwIfAborted();
|
|
79
|
-
if (next.done) {
|
|
80
|
-
ended = true;
|
|
81
|
-
break;
|
|
46
|
+
async add(span) {
|
|
47
|
+
let units = 0, kept = 0;
|
|
48
|
+
for await (const text of this.decoded(span.offset, span.length)) {
|
|
49
|
+
const zero = text.indexOf("\0"), part = zero < 0 ? text : text.slice(0, zero);
|
|
50
|
+
for (const unit of part) {
|
|
51
|
+
units += unit.length;
|
|
52
|
+
if (unit.trimEnd()) kept = units;
|
|
82
53
|
}
|
|
83
|
-
|
|
84
|
-
account(total);
|
|
85
|
-
const take = Math.min(prefix.length - size, next.value.length);
|
|
86
|
-
prefix.set(next.value.subarray(0, take), size);
|
|
87
|
-
size += take;
|
|
88
|
-
remainder = next.value.subarray(take);
|
|
54
|
+
if (zero >= 0) break;
|
|
89
55
|
}
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
56
|
+
let key = 0n;
|
|
57
|
+
for (let i = 0; i < span.key.length; i++) key = key << (span.key.length > 4 ? 7n : 16n) | BigInt(span.key.charCodeAt(i));
|
|
58
|
+
if (span.key.length > 4) key |= 1n << 63n;
|
|
59
|
+
const existing = await this.keys.get(key);
|
|
60
|
+
const position = existing === void 0 ? this.storage.allocate(56) : Number(existing);
|
|
61
|
+
const bytes = existing === void 0 ? new Uint8Array(56) : await this.storage.read(position, 56);
|
|
62
|
+
const view = new DataView(bytes.buffer, bytes.byteOffset, bytes.length);
|
|
63
|
+
view.setFloat64(8, span.offset, true);
|
|
64
|
+
view.setFloat64(16, span.length, true);
|
|
65
|
+
view.setFloat64(24, kept, true);
|
|
66
|
+
view.setUint16(32, span.key.length, true);
|
|
67
|
+
for (let i = 0; i < span.key.length; i++) view.setUint16(34 + i * 2, span.key.charCodeAt(i), true);
|
|
68
|
+
await this.storage.write(position, bytes);
|
|
69
|
+
if (existing !== void 0) return;
|
|
70
|
+
await this.keys.set(key, BigInt(position));
|
|
71
|
+
this.count++;
|
|
72
|
+
const numeric = Number(span.key);
|
|
73
|
+
if (Number.isInteger(numeric) && numeric >= 0 && numeric < 4294967295 && String(numeric) === span.key) await this.numeric.set(BigInt(numeric), BigInt(position));
|
|
74
|
+
else {
|
|
75
|
+
if (this.tail) {
|
|
76
|
+
const link = new Uint8Array(8);
|
|
77
|
+
new DataView(link.buffer).setFloat64(0, position, true);
|
|
78
|
+
await this.storage.write(this.tail, link);
|
|
79
|
+
} else this.head = position;
|
|
80
|
+
this.tail = position;
|
|
94
81
|
}
|
|
95
|
-
throw error;
|
|
96
82
|
}
|
|
97
|
-
async
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
const
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
break;
|
|
111
|
-
}
|
|
112
|
-
total += next.value.length;
|
|
113
|
-
account(total);
|
|
114
|
-
yield next.value;
|
|
115
|
-
}
|
|
116
|
-
} catch (error) {
|
|
117
|
-
failed = true;
|
|
118
|
-
throw error;
|
|
119
|
-
} finally {
|
|
120
|
-
if (!ended) {
|
|
121
|
-
if (failed) {
|
|
122
|
-
try {
|
|
123
|
-
await iterator.return?.();
|
|
124
|
-
} catch {
|
|
125
|
-
}
|
|
126
|
-
} else await iterator.return?.();
|
|
83
|
+
async record(position) {
|
|
84
|
+
const bytes = await this.storage.read(position, 56), view = new DataView(bytes.buffer, bytes.byteOffset, bytes.length);
|
|
85
|
+
let key = "";
|
|
86
|
+
for (let i = 0; i < view.getUint16(32, true); i++) key += String.fromCharCode(view.getUint16(34 + i * 2, true));
|
|
87
|
+
const offset = view.getFloat64(8, true), length = view.getFloat64(16, true), kept = view.getFloat64(24, true), decoded = this.decoded.bind(this);
|
|
88
|
+
return { key, next: view.getFloat64(0, true), async *text() {
|
|
89
|
+
let remaining = kept;
|
|
90
|
+
if (!remaining) return;
|
|
91
|
+
for await (const part of decoded(offset, length)) {
|
|
92
|
+
const take = Math.min(remaining, part.length);
|
|
93
|
+
if (take) yield part.slice(0, take);
|
|
94
|
+
remaining -= take;
|
|
95
|
+
if (!remaining) return;
|
|
127
96
|
}
|
|
128
|
-
}
|
|
97
|
+
} };
|
|
129
98
|
}
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
let size = 0, steps = 0, failed = true;
|
|
137
|
-
try {
|
|
138
|
-
for await (const chunk of input) {
|
|
139
|
-
context.signal.throwIfAborted();
|
|
140
|
-
size += chunk.length;
|
|
141
|
-
start ??= storage.allocate(0);
|
|
142
|
-
await storage.append(chunk);
|
|
143
|
-
if (++steps % 256 === 0) await yieldTurn2(context.signal);
|
|
99
|
+
async *entries() {
|
|
100
|
+
for await (const [, position] of this.numeric.entries()) yield await this.record(Number(position));
|
|
101
|
+
for (let position = this.head; position; ) {
|
|
102
|
+
const entry = await this.record(position);
|
|
103
|
+
position = entry.next;
|
|
104
|
+
yield entry;
|
|
144
105
|
}
|
|
145
|
-
context.signal.throwIfAborted();
|
|
146
|
-
start ??= storage.allocate(0);
|
|
147
|
-
const base = start;
|
|
148
|
-
const result = await probe2({ size, read: (offset, length) => storage.read(base + offset, length) });
|
|
149
|
-
context.signal.throwIfAborted();
|
|
150
|
-
failed = false;
|
|
151
|
-
return result;
|
|
152
|
-
} finally {
|
|
153
|
-
if (failed) {
|
|
154
|
-
try {
|
|
155
|
-
await storage.close();
|
|
156
|
-
} catch {
|
|
157
|
-
}
|
|
158
|
-
} else await storage.close();
|
|
159
106
|
}
|
|
160
|
-
}
|
|
107
|
+
};
|
|
161
108
|
|
|
162
109
|
// packages/safe-bash-command-ffprobe/src/probe.ts
|
|
163
110
|
import { parseAudio } from "../../audio-ast/index.js";
|
|
@@ -221,8 +168,8 @@ function probe(data, args) {
|
|
|
221
168
|
const parsed = parseArguments(args);
|
|
222
169
|
return formatAudioProbe(parseAudio(data, { maxAtomDepth: 64 }), data.length, parsed);
|
|
223
170
|
}
|
|
224
|
-
function
|
|
225
|
-
const { sections
|
|
171
|
+
function audioProbeRows(audio, size, parsed, retainedTags = false) {
|
|
172
|
+
const { sections } = parsed;
|
|
226
173
|
const serials = [
|
|
227
174
|
...new Set(
|
|
228
175
|
audio.nodes.filter((node) => node.type === "OggS").map((node) => node.fields?.serial)
|
|
@@ -285,11 +232,16 @@ function formatAudioProbe(audio, size, parsed) {
|
|
|
285
232
|
duration: formatDuration.toFixed(6),
|
|
286
233
|
size: String(size),
|
|
287
234
|
bit_rate: String(formatDuration ? Math.floor(size * 8 / formatDuration) : 0),
|
|
288
|
-
...Object.keys(formatTags).length ? { tags: formatTags } : {}
|
|
235
|
+
...retainedTags || Object.keys(formatTags).length ? { tags: formatTags } : {}
|
|
289
236
|
});
|
|
290
237
|
if (sections.has("format_tags")) row.tags = tags;
|
|
291
238
|
rows.push({ section: "format", row });
|
|
292
239
|
}
|
|
240
|
+
return rows;
|
|
241
|
+
}
|
|
242
|
+
function formatAudioProbe(audio, size, parsed) {
|
|
243
|
+
const { sections, format, settings } = parsed;
|
|
244
|
+
const rows = audioProbeRows(audio, size, parsed);
|
|
293
245
|
if (format === "json") {
|
|
294
246
|
const result = {};
|
|
295
247
|
if (sections.has("stream") || sections.has("stream_tags"))
|
|
@@ -334,6 +286,321 @@ function formatAudioProbe(audio, size, parsed) {
|
|
|
334
286
|
return lines.length ? lines.join("\n") + "\n" : "";
|
|
335
287
|
}
|
|
336
288
|
|
|
289
|
+
// packages/safe-bash-command-ffprobe/src/tag-format.ts
|
|
290
|
+
async function* parts(value, prefix = "") {
|
|
291
|
+
if (prefix) yield prefix;
|
|
292
|
+
if (typeof value === "function") yield* value();
|
|
293
|
+
else yield String(value);
|
|
294
|
+
}
|
|
295
|
+
async function* jsonString(input) {
|
|
296
|
+
yield '"';
|
|
297
|
+
for await (const part of input) yield JSON.stringify(part).slice(1, -1);
|
|
298
|
+
yield '"';
|
|
299
|
+
}
|
|
300
|
+
async function* replace(input, needle, replacement) {
|
|
301
|
+
let pending = "", first = true;
|
|
302
|
+
if (!needle) {
|
|
303
|
+
for await (const part of input) {
|
|
304
|
+
let text = "";
|
|
305
|
+
for (let i = 0; i < part.length; i++) {
|
|
306
|
+
text += (first ? "" : replacement) + part[i];
|
|
307
|
+
first = false;
|
|
308
|
+
if (text.length >= 4096) {
|
|
309
|
+
yield text;
|
|
310
|
+
text = "";
|
|
311
|
+
}
|
|
312
|
+
}
|
|
313
|
+
if (text) yield text;
|
|
314
|
+
}
|
|
315
|
+
return;
|
|
316
|
+
}
|
|
317
|
+
for await (const part of input) {
|
|
318
|
+
const text = pending + part;
|
|
319
|
+
let at = 0, found, output = "";
|
|
320
|
+
while ((found = text.indexOf(needle, at)) >= 0) {
|
|
321
|
+
output += text.slice(at, found) + replacement;
|
|
322
|
+
at = found + needle.length;
|
|
323
|
+
if (output.length >= 16384) {
|
|
324
|
+
yield output;
|
|
325
|
+
output = "";
|
|
326
|
+
}
|
|
327
|
+
}
|
|
328
|
+
const end = Math.max(at, text.length - needle.length + 1);
|
|
329
|
+
output += text.slice(at, end);
|
|
330
|
+
if (output) yield output;
|
|
331
|
+
pending = text.slice(end);
|
|
332
|
+
}
|
|
333
|
+
if (pending) yield pending;
|
|
334
|
+
}
|
|
335
|
+
async function needsQuotes(input, separator) {
|
|
336
|
+
if (!separator) return true;
|
|
337
|
+
let tail = "";
|
|
338
|
+
for await (const part of input) {
|
|
339
|
+
const text = tail + part;
|
|
340
|
+
if (text.includes(separator) || text.includes('"') || text.includes("\n")) return true;
|
|
341
|
+
tail = text.slice(Math.max(0, text.length - separator.length + 1));
|
|
342
|
+
}
|
|
343
|
+
return false;
|
|
344
|
+
}
|
|
345
|
+
async function* formatTaggedAudio(audio, size, args, tags) {
|
|
346
|
+
const parsed = parseArguments(args), { sections, format, settings } = parsed;
|
|
347
|
+
const rows = audioProbeRows({ ...audio, nodes: [] }, size, parsed, tags.count > 0);
|
|
348
|
+
async function* tagFields(section) {
|
|
349
|
+
const selected = sections.get(section + "_tags");
|
|
350
|
+
for await (const entry of tags.entries()) if (selected === void 0 || selected.includes(entry.key)) yield { key: entry.key, value: entry.text };
|
|
351
|
+
}
|
|
352
|
+
async function* jsonRow(row, section, indent) {
|
|
353
|
+
yield "{";
|
|
354
|
+
let first = true;
|
|
355
|
+
for (const [key, value] of Object.entries(row)) {
|
|
356
|
+
yield (first ? "\n" : ",\n") + " ".repeat(indent + 4) + JSON.stringify(key) + ": ";
|
|
357
|
+
first = false;
|
|
358
|
+
if (typeof value === "object") {
|
|
359
|
+
yield "{";
|
|
360
|
+
let firstTag = true;
|
|
361
|
+
for await (const field of tagFields(section)) {
|
|
362
|
+
yield (firstTag ? "\n" : ",\n") + " ".repeat(indent + 8) + JSON.stringify(field.key) + ": ";
|
|
363
|
+
firstTag = false;
|
|
364
|
+
yield* jsonString(parts(field.value));
|
|
365
|
+
}
|
|
366
|
+
yield (firstTag ? "" : "\n" + " ".repeat(indent + 4)) + "}";
|
|
367
|
+
} else if (typeof value === "number") yield JSON.stringify(value);
|
|
368
|
+
else yield* jsonString(parts(value));
|
|
369
|
+
}
|
|
370
|
+
yield (first ? "" : "\n" + " ".repeat(indent)) + "}";
|
|
371
|
+
}
|
|
372
|
+
if (format === "json") {
|
|
373
|
+
yield "{";
|
|
374
|
+
let first = true;
|
|
375
|
+
if (sections.has("stream") || sections.has("stream_tags")) {
|
|
376
|
+
yield '\n "streams": [';
|
|
377
|
+
first = false;
|
|
378
|
+
let firstStream = true;
|
|
379
|
+
for (const { section, row } of rows) if (section === "stream") {
|
|
380
|
+
yield (firstStream ? "\n" : ",\n") + " ";
|
|
381
|
+
firstStream = false;
|
|
382
|
+
yield* jsonRow(row, section, 8);
|
|
383
|
+
}
|
|
384
|
+
yield (firstStream ? "" : "\n ") + "]";
|
|
385
|
+
}
|
|
386
|
+
for (const { section, row } of rows) if (section === "format") {
|
|
387
|
+
yield (first ? "\n" : ",\n") + ' "format": ';
|
|
388
|
+
first = false;
|
|
389
|
+
yield* jsonRow(row, section, 4);
|
|
390
|
+
}
|
|
391
|
+
yield (first ? "" : "\n") + "}\n";
|
|
392
|
+
return;
|
|
393
|
+
}
|
|
394
|
+
const enabled = (a, b, fallback) => {
|
|
395
|
+
const value = settings.get(a) ?? settings.get(b);
|
|
396
|
+
return value === void 0 ? fallback : value === "1";
|
|
397
|
+
};
|
|
398
|
+
let streamIndex = 0;
|
|
399
|
+
for (const { section, row } of rows) {
|
|
400
|
+
async function* fields() {
|
|
401
|
+
for (const [key, value] of Object.entries(row)) {
|
|
402
|
+
if (typeof value === "object") {
|
|
403
|
+
for await (const tag of tagFields(section)) yield { key: "tag:" + tag.key, value: tag.value };
|
|
404
|
+
} else yield { key, value };
|
|
405
|
+
}
|
|
406
|
+
}
|
|
407
|
+
if (format === "compact" || format === "csv") {
|
|
408
|
+
const separator = settings.get("item_sep") ?? settings.get("s") ?? (format === "csv" ? "," : "|");
|
|
409
|
+
let first = true;
|
|
410
|
+
if (enabled("print_section", "p", true)) {
|
|
411
|
+
yield section;
|
|
412
|
+
first = false;
|
|
413
|
+
}
|
|
414
|
+
for await (const field of fields()) {
|
|
415
|
+
if (!first) yield separator;
|
|
416
|
+
first = false;
|
|
417
|
+
const prefix = enabled("nokey", "nk", format === "csv") ? "" : field.key + "=";
|
|
418
|
+
if (format === "csv") {
|
|
419
|
+
const quote = await needsQuotes(parts(field.value, prefix), separator);
|
|
420
|
+
if (quote) yield '"';
|
|
421
|
+
yield* quote ? replace(parts(field.value, prefix), '"', '""') : parts(field.value, prefix);
|
|
422
|
+
if (quote) yield '"';
|
|
423
|
+
} else yield* replace(replace(replace(replace(parts(field.value, prefix), "\\", "\\\\"), "\n", "\\n"), "\r", "\\r"), separator, "\\" + separator);
|
|
424
|
+
}
|
|
425
|
+
yield "\n";
|
|
426
|
+
} else if (format === "flat") {
|
|
427
|
+
const prefix = section === "stream" ? `streams.stream.${streamIndex++}` : "format";
|
|
428
|
+
for await (const field of fields()) {
|
|
429
|
+
yield prefix + "." + (field.key.startsWith("tag:") ? "tags." + field.key.slice(4) : field.key) + "=";
|
|
430
|
+
if (typeof field.value === "number") yield String(field.value);
|
|
431
|
+
else yield* jsonString(parts(field.value));
|
|
432
|
+
yield "\n";
|
|
433
|
+
}
|
|
434
|
+
} else {
|
|
435
|
+
if (!enabled("noprint_wrappers", "nw", false)) yield "[" + section.toUpperCase() + "]\n";
|
|
436
|
+
for await (const field of fields()) {
|
|
437
|
+
if (!enabled("nokey", "nk", false)) yield (field.key.startsWith("tag:") ? "TAG:" + field.key.slice(4) : field.key) + "=";
|
|
438
|
+
yield* parts(field.value);
|
|
439
|
+
yield "\n";
|
|
440
|
+
}
|
|
441
|
+
if (!enabled("noprint_wrappers", "nw", false)) yield "[/" + section.toUpperCase() + "]\n";
|
|
442
|
+
}
|
|
443
|
+
}
|
|
444
|
+
}
|
|
445
|
+
|
|
446
|
+
// packages/safe-bash-command-ffprobe/src/probe-output.ts
|
|
447
|
+
import { PagedStorage as PagedStorage2 } from "@poe-platform/safe-fs/storage";
|
|
448
|
+
import { writeBytes } from "../../safe-bash-contracts/io.js";
|
|
449
|
+
import { yieldTurn as yieldTurn2 } from "../../safe-bash-contracts/yield.js";
|
|
450
|
+
async function* encodeParts(parts2, signal) {
|
|
451
|
+
const encoder = new TextEncoder();
|
|
452
|
+
let high = "", steps = 0;
|
|
453
|
+
for await (const part of parts2) {
|
|
454
|
+
signal.throwIfAborted();
|
|
455
|
+
for (let offset = 0; offset < part.length; offset += 4096) {
|
|
456
|
+
signal.throwIfAborted();
|
|
457
|
+
let text = high + part.slice(offset, offset + 4096);
|
|
458
|
+
high = "";
|
|
459
|
+
const last = text.charCodeAt(text.length - 1);
|
|
460
|
+
if (last >= 55296 && last <= 56319) {
|
|
461
|
+
high = text.at(-1);
|
|
462
|
+
text = text.slice(0, -1);
|
|
463
|
+
}
|
|
464
|
+
if (text) yield encoder.encode(text);
|
|
465
|
+
if (++steps % 256 === 0) await yieldTurn2(signal);
|
|
466
|
+
}
|
|
467
|
+
}
|
|
468
|
+
if (high) yield encoder.encode(high);
|
|
469
|
+
}
|
|
470
|
+
async function writeProbeOutput(context, parts2, check, beforePublish) {
|
|
471
|
+
const storage = new PagedStorage2(context, 4), start = storage.allocate(0);
|
|
472
|
+
let size = 0, failed = true;
|
|
473
|
+
try {
|
|
474
|
+
for await (const bytes of encodeParts(parts2, context.signal)) {
|
|
475
|
+
size += bytes.length;
|
|
476
|
+
check(size);
|
|
477
|
+
await storage.append(bytes);
|
|
478
|
+
}
|
|
479
|
+
context.signal.throwIfAborted();
|
|
480
|
+
await beforePublish?.();
|
|
481
|
+
context.signal.throwIfAborted();
|
|
482
|
+
if (size === 0) await writeBytes(context.stdout, new Uint8Array(0), context.signal);
|
|
483
|
+
for (let offset = 0; offset < size; offset += 16384)
|
|
484
|
+
await writeBytes(context.stdout, await storage.read(start + offset, Math.min(16384, size - offset)), context.signal);
|
|
485
|
+
failed = false;
|
|
486
|
+
} finally {
|
|
487
|
+
if (failed) {
|
|
488
|
+
try {
|
|
489
|
+
await storage.close();
|
|
490
|
+
} catch {
|
|
491
|
+
}
|
|
492
|
+
} else await storage.close();
|
|
493
|
+
}
|
|
494
|
+
}
|
|
495
|
+
|
|
496
|
+
// packages/safe-bash-command-ffprobe/src/stream-input.ts
|
|
497
|
+
import { PagedStorage as PagedStorage3 } from "@poe-platform/safe-fs/storage";
|
|
498
|
+
import { readBytes } from "../../safe-bash-contracts/io.js";
|
|
499
|
+
import { readFileStream } from "../../safe-bash-contracts/filesystem.js";
|
|
500
|
+
import { yieldTurn as yieldTurn3 } from "../../safe-bash-contracts/yield.js";
|
|
501
|
+
async function openProbeStream(context, path) {
|
|
502
|
+
context.signal.throwIfAborted();
|
|
503
|
+
if (path === void 0) return readBytes(context.stdin, context.signal);
|
|
504
|
+
const capabilities = await context.fs.capabilitiesFor?.(path, { signal: context.signal }) ?? context.fs.capabilities;
|
|
505
|
+
context.signal.throwIfAborted();
|
|
506
|
+
if (!context.fs.readStream || capabilities.streamingRead === false || context.fs.capabilities.streamingRead === false) return void 0;
|
|
507
|
+
return readFileStream(context.fs, path, { signal: context.signal, chunkSize: 16384 });
|
|
508
|
+
}
|
|
509
|
+
async function sniffWavStream(source, signal, account) {
|
|
510
|
+
const iterator = source[Symbol.asyncIterator](), prefix = new Uint8Array(12);
|
|
511
|
+
let size = 0, total = 0, ended = false;
|
|
512
|
+
let remainder = new Uint8Array(0);
|
|
513
|
+
try {
|
|
514
|
+
while (size < prefix.length) {
|
|
515
|
+
signal.throwIfAborted();
|
|
516
|
+
const next = await iterator.next();
|
|
517
|
+
signal.throwIfAborted();
|
|
518
|
+
if (next.done) {
|
|
519
|
+
ended = true;
|
|
520
|
+
break;
|
|
521
|
+
}
|
|
522
|
+
total += next.value.length;
|
|
523
|
+
account(total);
|
|
524
|
+
const take = Math.min(prefix.length - size, next.value.length);
|
|
525
|
+
prefix.set(next.value.subarray(0, take), size);
|
|
526
|
+
size += take;
|
|
527
|
+
remainder = next.value.subarray(take);
|
|
528
|
+
}
|
|
529
|
+
} catch (error) {
|
|
530
|
+
try {
|
|
531
|
+
await iterator.return?.();
|
|
532
|
+
} catch {
|
|
533
|
+
}
|
|
534
|
+
throw error;
|
|
535
|
+
}
|
|
536
|
+
async function* replay() {
|
|
537
|
+
let failed = false;
|
|
538
|
+
try {
|
|
539
|
+
signal.throwIfAborted();
|
|
540
|
+
if (size) yield prefix.subarray(0, size);
|
|
541
|
+
if (remainder.length) yield remainder;
|
|
542
|
+
remainder = new Uint8Array(0);
|
|
543
|
+
while (!ended) {
|
|
544
|
+
signal.throwIfAborted();
|
|
545
|
+
const next = await iterator.next();
|
|
546
|
+
signal.throwIfAborted();
|
|
547
|
+
if (next.done) {
|
|
548
|
+
ended = true;
|
|
549
|
+
break;
|
|
550
|
+
}
|
|
551
|
+
total += next.value.length;
|
|
552
|
+
account(total);
|
|
553
|
+
yield next.value;
|
|
554
|
+
}
|
|
555
|
+
} catch (error) {
|
|
556
|
+
failed = true;
|
|
557
|
+
throw error;
|
|
558
|
+
} finally {
|
|
559
|
+
if (!ended) {
|
|
560
|
+
if (failed) {
|
|
561
|
+
try {
|
|
562
|
+
await iterator.return?.();
|
|
563
|
+
} catch {
|
|
564
|
+
}
|
|
565
|
+
} else await iterator.return?.();
|
|
566
|
+
}
|
|
567
|
+
}
|
|
568
|
+
}
|
|
569
|
+
const text = new TextDecoder().decode(prefix);
|
|
570
|
+
return { wav: size === 12 && text.slice(0, 4) === "RIFF" && text.slice(8) === "WAVE", stream: replay() };
|
|
571
|
+
}
|
|
572
|
+
async function withStagedProbeSource(context, input, probe2, retain) {
|
|
573
|
+
const storage = new PagedStorage3(context, 4);
|
|
574
|
+
retain?.(storage.close.bind(storage));
|
|
575
|
+
let start;
|
|
576
|
+
let size = 0, steps = 0, failed = true;
|
|
577
|
+
try {
|
|
578
|
+
for await (const chunk of input) {
|
|
579
|
+
context.signal.throwIfAborted();
|
|
580
|
+
size += chunk.length;
|
|
581
|
+
start ??= storage.allocate(0);
|
|
582
|
+
await storage.append(chunk);
|
|
583
|
+
if (++steps % 256 === 0) await yieldTurn3(context.signal);
|
|
584
|
+
}
|
|
585
|
+
context.signal.throwIfAborted();
|
|
586
|
+
start ??= storage.allocate(0);
|
|
587
|
+
const base = start;
|
|
588
|
+
const result = await probe2({ size, read: (offset, length) => storage.read(base + offset, length) });
|
|
589
|
+
context.signal.throwIfAborted();
|
|
590
|
+
failed = false;
|
|
591
|
+
return result;
|
|
592
|
+
} finally {
|
|
593
|
+
if (!retain) {
|
|
594
|
+
if (failed) {
|
|
595
|
+
try {
|
|
596
|
+
await storage.close();
|
|
597
|
+
} catch {
|
|
598
|
+
}
|
|
599
|
+
} else await storage.close();
|
|
600
|
+
}
|
|
601
|
+
}
|
|
602
|
+
}
|
|
603
|
+
|
|
337
604
|
// packages/safe-bash-command-ffprobe/src/media.ts
|
|
338
605
|
import { probeWavSource } from "../../audio-ast/index.js";
|
|
339
606
|
import { commandRuntimeIdentity, getCommandArguments } from "../../safe-bash-contracts/command.js";
|
|
@@ -411,9 +678,9 @@ function resolvePath(cwd, p) {
|
|
|
411
678
|
return normalizePath(`${cwd.endsWith("/") ? cwd : `${cwd}/`}${p}`);
|
|
412
679
|
}
|
|
413
680
|
function normalizePath(p) {
|
|
414
|
-
const
|
|
681
|
+
const parts2 = p.split("/");
|
|
415
682
|
const stack = [];
|
|
416
|
-
for (const part of
|
|
683
|
+
for (const part of parts2) {
|
|
417
684
|
if (!part || part === ".") continue;
|
|
418
685
|
if (part === "..") {
|
|
419
686
|
stack.pop();
|
|
@@ -840,7 +1107,7 @@ function parseProbeArguments(args) {
|
|
|
840
1107
|
inputTarget
|
|
841
1108
|
};
|
|
842
1109
|
}
|
|
843
|
-
async function probeSourceMetadata(context, plugin, input, filename, budget, records, onAudio) {
|
|
1110
|
+
async function probeSourceMetadata(context, plugin, input, filename, budget, records, onAudio, retain, detect = false) {
|
|
844
1111
|
let sourceFailed = false;
|
|
845
1112
|
const source = { size: input.size, async read(offset, length) {
|
|
846
1113
|
try {
|
|
@@ -852,7 +1119,7 @@ async function probeSourceMetadata(context, plugin, input, filename, budget, rec
|
|
|
852
1119
|
throw error;
|
|
853
1120
|
}
|
|
854
1121
|
} };
|
|
855
|
-
if (onAudio) {
|
|
1122
|
+
if (detect || onAudio) {
|
|
856
1123
|
if (input.size < 12) {
|
|
857
1124
|
return void 0;
|
|
858
1125
|
}
|
|
@@ -865,8 +1132,17 @@ async function probeSourceMetadata(context, plugin, input, filename, budget, rec
|
|
|
865
1132
|
}
|
|
866
1133
|
const result = await plugin.probeMetadata(source, { ...records, filename, signal: context.signal, budget, limits: budget.limits });
|
|
867
1134
|
if (onAudio) {
|
|
1135
|
+
const tags = new WavTags(source, context);
|
|
1136
|
+
retain(tags.close);
|
|
868
1137
|
try {
|
|
869
|
-
onAudio(await probeWavSource(source, { signal: context.signal
|
|
1138
|
+
onAudio(await probeWavSource(source, { signal: context.signal, onTag: async (span) => {
|
|
1139
|
+
try {
|
|
1140
|
+
await tags.add(span);
|
|
1141
|
+
} catch (error) {
|
|
1142
|
+
sourceFailed = true;
|
|
1143
|
+
throw error;
|
|
1144
|
+
}
|
|
1145
|
+
} }), input.size, tags);
|
|
870
1146
|
} catch (error) {
|
|
871
1147
|
context.signal.throwIfAborted();
|
|
872
1148
|
if (sourceFailed) throw error;
|
|
@@ -874,13 +1150,14 @@ async function probeSourceMetadata(context, plugin, input, filename, budget, rec
|
|
|
874
1150
|
}
|
|
875
1151
|
return result;
|
|
876
1152
|
}
|
|
877
|
-
async function probeRetainedMetadata(context, plugin, path, filename, budget, records, onAudio) {
|
|
1153
|
+
async function probeRetainedMetadata(context, plugin, path, filename, budget, records, onAudio, retain, detect = false) {
|
|
878
1154
|
if (!plugin.canDemux || !plugin.probeMetadata || !context.fs.openReadFile) return void 0;
|
|
879
1155
|
context.signal.throwIfAborted();
|
|
880
1156
|
const capabilities = await context.fs.capabilitiesFor?.(path, { signal: context.signal }) ?? context.fs.capabilities;
|
|
881
1157
|
context.signal.throwIfAborted();
|
|
882
1158
|
if (capabilities.retainedRead !== true) return void 0;
|
|
883
1159
|
const handle = await context.fs.openReadFile(path, { signal: context.signal });
|
|
1160
|
+
if (onAudio) retain(handle.close.bind(handle));
|
|
884
1161
|
let failed = true;
|
|
885
1162
|
try {
|
|
886
1163
|
context.signal.throwIfAborted();
|
|
@@ -892,17 +1169,19 @@ async function probeRetainedMetadata(context, plugin, path, filename, budget, re
|
|
|
892
1169
|
const result = await probeSourceMetadata(context, plugin, {
|
|
893
1170
|
size: stat.size,
|
|
894
1171
|
read: (offset, length) => handle.read(offset, length, { signal: context.signal })
|
|
895
|
-
}, filename, budget, records, onAudio);
|
|
1172
|
+
}, filename, budget, records, onAudio, retain, detect);
|
|
896
1173
|
context.signal.throwIfAborted();
|
|
897
1174
|
failed = false;
|
|
898
1175
|
return result;
|
|
899
1176
|
} finally {
|
|
900
|
-
if (
|
|
901
|
-
|
|
902
|
-
|
|
903
|
-
|
|
904
|
-
|
|
905
|
-
|
|
1177
|
+
if (!onAudio) {
|
|
1178
|
+
if (failed) {
|
|
1179
|
+
try {
|
|
1180
|
+
await handle.close();
|
|
1181
|
+
} catch {
|
|
1182
|
+
}
|
|
1183
|
+
} else await handle.close();
|
|
1184
|
+
}
|
|
906
1185
|
}
|
|
907
1186
|
}
|
|
908
1187
|
async function probeStreamMetadata(context, plugin, filename, budget, records) {
|
|
@@ -926,10 +1205,7 @@ async function probeStreamMetadata(context, plugin, filename, budget, records) {
|
|
|
926
1205
|
return result;
|
|
927
1206
|
}
|
|
928
1207
|
function createFfprobeCommand(options = {}) {
|
|
929
|
-
const limits =
|
|
930
|
-
for (const value of [limits.maxInputBytes, limits.maxOutputBytes]) {
|
|
931
|
-
if (value !== void 0 && (!Number.isSafeInteger(value) || value < 1)) throw new RangeError("Invalid ffprobe limit");
|
|
932
|
-
}
|
|
1208
|
+
const limits = resolveFfprobeLimits(options.limits);
|
|
933
1209
|
const astPlugins = options.asts ?? getDefaultMediaRegistry().astPlugins;
|
|
934
1210
|
const registry = options.asts ? createMediaAstRegistry(astPlugins) : getDefaultMediaRegistry().registry;
|
|
935
1211
|
return {
|
|
@@ -967,6 +1243,25 @@ function createFfprobeCommand(options = {}) {
|
|
|
967
1243
|
return { exitCode: 0 };
|
|
968
1244
|
}
|
|
969
1245
|
}
|
|
1246
|
+
const retained = [];
|
|
1247
|
+
const retain = (close) => {
|
|
1248
|
+
retained.push(close);
|
|
1249
|
+
};
|
|
1250
|
+
const closeInputs = async () => {
|
|
1251
|
+
let failure, failed = false;
|
|
1252
|
+
while (retained.length) {
|
|
1253
|
+
try {
|
|
1254
|
+
await retained.pop()();
|
|
1255
|
+
} catch (error) {
|
|
1256
|
+
if (!failed) {
|
|
1257
|
+
failed = true;
|
|
1258
|
+
failure = error;
|
|
1259
|
+
}
|
|
1260
|
+
}
|
|
1261
|
+
}
|
|
1262
|
+
if (failed) throw failure;
|
|
1263
|
+
};
|
|
1264
|
+
let storedTags;
|
|
970
1265
|
try {
|
|
971
1266
|
const {
|
|
972
1267
|
printFormat,
|
|
@@ -992,12 +1287,13 @@ function createFfprobeCommand(options = {}) {
|
|
|
992
1287
|
automaticAudio = false;
|
|
993
1288
|
}
|
|
994
1289
|
}
|
|
995
|
-
const automaticPlugin =
|
|
1290
|
+
const automaticPlugin = !options.asts && !explicitFormat ? registry.findByFormatName("wav") : void 0;
|
|
996
1291
|
const explicitPlugin = explicitFormat ? registry.findByFormatName(explicitFormat) : void 0;
|
|
997
1292
|
const retainedPlugin = explicitPlugin ?? automaticPlugin;
|
|
998
|
-
let probeResult = retainedPlugin && !isStdin(inputTarget) ? await probeRetainedMetadata(context, retainedPlugin, resolvePath(context.cwd, inputTarget), inputTarget, budget, { showPackets, showFrames }, automaticAudio ? (audio, size) => {
|
|
1293
|
+
let probeResult = retainedPlugin && !isStdin(inputTarget) ? await probeRetainedMetadata(context, retainedPlugin, resolvePath(context.cwd, inputTarget), inputTarget, budget, { showPackets, showFrames }, automaticAudio ? (audio, size, tags) => {
|
|
999
1294
|
audioInput = { audio, size, args };
|
|
1000
|
-
|
|
1295
|
+
storedTags = tags;
|
|
1296
|
+
} : void 0, retain, automaticPlugin !== void 0) : void 0;
|
|
1001
1297
|
if (!probeResult && explicitPlugin)
|
|
1002
1298
|
probeResult = await probeStreamMetadata(context, explicitPlugin, inputTarget, budget, { showPackets, showFrames });
|
|
1003
1299
|
let replay;
|
|
@@ -1009,9 +1305,22 @@ function createFfprobeCommand(options = {}) {
|
|
|
1009
1305
|
budget.checkInputBytes(total);
|
|
1010
1306
|
});
|
|
1011
1307
|
if (sniffed.wav) {
|
|
1012
|
-
|
|
1013
|
-
|
|
1014
|
-
|
|
1308
|
+
if (!automaticAudio && automaticPlugin.probeMetadataStream) {
|
|
1309
|
+
probeResult = await automaticPlugin.probeMetadataStream(sniffed.stream, {
|
|
1310
|
+
showPackets,
|
|
1311
|
+
showFrames,
|
|
1312
|
+
filename: inputTarget,
|
|
1313
|
+
signal: context.signal,
|
|
1314
|
+
budget,
|
|
1315
|
+
limits: budget.limits
|
|
1316
|
+
});
|
|
1317
|
+
context.signal.throwIfAborted();
|
|
1318
|
+
} else {
|
|
1319
|
+
probeResult = await withStagedProbeSource(context, sniffed.stream, (source2) => probeSourceMetadata(context, automaticPlugin, source2, inputTarget, budget, { showPackets, showFrames }, automaticAudio ? (audio, size, tags) => {
|
|
1320
|
+
audioInput = { audio, size, args };
|
|
1321
|
+
storedTags = tags;
|
|
1322
|
+
} : void 0, retain), retain);
|
|
1323
|
+
}
|
|
1015
1324
|
} else replay = sniffed.stream;
|
|
1016
1325
|
}
|
|
1017
1326
|
}
|
|
@@ -1022,6 +1331,7 @@ function createFfprobeCommand(options = {}) {
|
|
|
1022
1331
|
const msg = explicitFormat ? `ffprobe: Unknown input format: '${explicitFormat}' (AST not registered)
|
|
1023
1332
|
` : `ffprobe: ${inputTarget}: Invalid data found when processing input or format AST not registered
|
|
1024
1333
|
`;
|
|
1334
|
+
await closeInputs();
|
|
1025
1335
|
if (!quiet) await writeBytes2(context.stderr, encodeUtf8(msg), context.signal);
|
|
1026
1336
|
return { exitCode: 1 };
|
|
1027
1337
|
}
|
|
@@ -1036,7 +1346,7 @@ function createFfprobeCommand(options = {}) {
|
|
|
1036
1346
|
});
|
|
1037
1347
|
if (!options.asts && !explicitFormat) audioInput = { bytes, args };
|
|
1038
1348
|
}
|
|
1039
|
-
const formatted = formatFfprobeResultChunks(probeResult, {
|
|
1349
|
+
const formatted = storedTags && audioInput && "audio" in audioInput ? formatTaggedAudio(audioInput.audio, audioInput.size, audioInput.args, storedTags) : formatFfprobeResultChunks(probeResult, {
|
|
1040
1350
|
printFormat,
|
|
1041
1351
|
showFormat,
|
|
1042
1352
|
showStreams,
|
|
@@ -1049,10 +1359,14 @@ function createFfprobeCommand(options = {}) {
|
|
|
1049
1359
|
countFrames,
|
|
1050
1360
|
countPackets
|
|
1051
1361
|
}, audioInput);
|
|
1052
|
-
await writeProbeOutput(context, formatted, (total) => budget.checkOutputBytes(total));
|
|
1362
|
+
await writeProbeOutput(context, formatted, (total) => budget.checkOutputBytes(total), closeInputs);
|
|
1053
1363
|
options.onMetrics?.(budget.getStats());
|
|
1054
1364
|
return { exitCode: 0 };
|
|
1055
1365
|
} catch (err) {
|
|
1366
|
+
try {
|
|
1367
|
+
await closeInputs();
|
|
1368
|
+
} catch {
|
|
1369
|
+
}
|
|
1056
1370
|
rethrowRuntimeError(context, err);
|
|
1057
1371
|
const msg = err instanceof Error ? err.message : String(err);
|
|
1058
1372
|
if (!quiet)
|