@nodetool-ai/runtime 0.8.8 → 0.8.9-beta.2
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/.nodetool-build-stamp +1 -1
- package/dist/context.d.ts +6 -2
- package/dist/context.d.ts.map +1 -1
- package/dist/context.js +13 -24
- package/dist/context.js.map +1 -1
- package/dist/host-binaries.d.ts +5 -5
- package/dist/host-binaries.js +5 -5
- package/dist/index.d.ts +2 -0
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +2 -0
- package/dist/index.js.map +1 -1
- package/dist/invocation-account.d.ts +1 -42
- package/dist/invocation-account.d.ts.map +1 -1
- package/dist/invocation-account.js +1 -59
- package/dist/invocation-account.js.map +1 -1
- package/dist/media/abort.d.ts +8 -0
- package/dist/media/abort.d.ts.map +1 -0
- package/dist/media/abort.js +18 -0
- package/dist/media/abort.js.map +1 -0
- package/dist/media/audio-encoder.d.ts +37 -0
- package/dist/media/audio-encoder.d.ts.map +1 -0
- package/dist/media/audio-encoder.js +118 -0
- package/dist/media/audio-encoder.js.map +1 -0
- package/dist/media/audio.d.ts +36 -0
- package/dist/media/audio.d.ts.map +1 -0
- package/dist/media/audio.js +84 -0
- package/dist/media/audio.js.map +1 -0
- package/dist/media/av.d.ts +51 -0
- package/dist/media/av.d.ts.map +1 -0
- package/dist/media/av.js +146 -0
- package/dist/media/av.js.map +1 -0
- package/dist/media/codecs.d.ts +9 -0
- package/dist/media/codecs.d.ts.map +1 -0
- package/dist/media/codecs.js +17 -0
- package/dist/media/codecs.js.map +1 -0
- package/dist/media/concat.d.ts +56 -0
- package/dist/media/concat.d.ts.map +1 -0
- package/dist/media/concat.js +319 -0
- package/dist/media/concat.js.map +1 -0
- package/dist/media/convert.d.ts +31 -0
- package/dist/media/convert.d.ts.map +1 -0
- package/dist/media/convert.js +114 -0
- package/dist/media/convert.js.map +1 -0
- package/dist/media/decode.d.ts +31 -0
- package/dist/media/decode.d.ts.map +1 -0
- package/dist/media/decode.js +85 -0
- package/dist/media/decode.js.map +1 -0
- package/dist/media/filter-graph.d.ts +53 -0
- package/dist/media/filter-graph.d.ts.map +1 -0
- package/dist/media/filter-graph.js +260 -0
- package/dist/media/filter-graph.js.map +1 -0
- package/dist/media/frames.d.ts +31 -0
- package/dist/media/frames.d.ts.map +1 -0
- package/dist/media/frames.js +112 -0
- package/dist/media/frames.js.map +1 -0
- package/dist/media/index.d.ts +26 -0
- package/dist/media/index.d.ts.map +1 -0
- package/dist/media/index.js +26 -0
- package/dist/media/index.js.map +1 -0
- package/dist/media/mux.d.ts +58 -0
- package/dist/media/mux.d.ts.map +1 -0
- package/dist/media/mux.js +234 -0
- package/dist/media/mux.js.map +1 -0
- package/dist/media/probe.d.ts +84 -0
- package/dist/media/probe.d.ts.map +1 -0
- package/dist/media/probe.js +133 -0
- package/dist/media/probe.js.map +1 -0
- package/dist/media/rgba.d.ts +78 -0
- package/dist/media/rgba.d.ts.map +1 -0
- package/dist/media/rgba.js +285 -0
- package/dist/media/rgba.js.map +1 -0
- package/dist/media/testing.d.ts +119 -0
- package/dist/media/testing.d.ts.map +1 -0
- package/dist/media/testing.js +343 -0
- package/dist/media/testing.js.map +1 -0
- package/dist/media/transcode.d.ts +17 -0
- package/dist/media/transcode.d.ts.map +1 -0
- package/dist/media/transcode.js +19 -0
- package/dist/media/transcode.js.map +1 -0
- package/dist/media/transform.d.ts +61 -0
- package/dist/media/transform.d.ts.map +1 -0
- package/dist/media/transform.js +371 -0
- package/dist/media/transform.js.map +1 -0
- package/dist/media/verify.d.ts +17 -0
- package/dist/media/verify.d.ts.map +1 -0
- package/dist/media/verify.js +65 -0
- package/dist/media/verify.js.map +1 -0
- package/dist/media-loader.d.ts +8 -0
- package/dist/media-loader.d.ts.map +1 -0
- package/dist/media-loader.js +10 -0
- package/dist/media-loader.js.map +1 -0
- package/dist/prefixed-storage-adapter.d.ts.map +1 -1
- package/dist/prefixed-storage-adapter.js +1 -1
- package/dist/prefixed-storage-adapter.js.map +1 -1
- package/dist/providers/anthropic-provider.d.ts.map +1 -1
- package/dist/providers/anthropic-provider.js +1 -17
- package/dist/providers/anthropic-provider.js.map +1 -1
- package/dist/providers/data-uri.d.ts +6 -0
- package/dist/providers/data-uri.d.ts.map +1 -0
- package/dist/providers/data-uri.js +19 -0
- package/dist/providers/data-uri.js.map +1 -0
- package/dist/providers/fake-provider.js +1 -1
- package/dist/providers/meta-transcription.d.ts +1 -5
- package/dist/providers/meta-transcription.d.ts.map +1 -1
- package/dist/providers/meta-transcription.js +9 -55
- package/dist/providers/meta-transcription.js.map +1 -1
- package/dist/providers/node-llama-cpp-trending.generated.js +132 -132
- package/dist/providers/node-llama-cpp-trending.generated.js.map +1 -1
- package/dist/providers/ollama-provider.d.ts.map +1 -1
- package/dist/providers/ollama-provider.js +1 -17
- package/dist/providers/ollama-provider.js.map +1 -1
- package/dist/providers/openai-provider.js +2 -2
- package/dist/providers/openai-provider.js.map +1 -1
- package/dist/providers/openrouter-provider.d.ts.map +1 -1
- package/dist/providers/openrouter-provider.js +1 -0
- package/dist/providers/openrouter-provider.js.map +1 -1
- package/dist/providers/safe-url.d.ts +1 -69
- package/dist/providers/safe-url.d.ts.map +1 -1
- package/dist/providers/safe-url.js +1 -284
- package/dist/providers/safe-url.js.map +1 -1
- package/dist/providers/topaz-provider.d.ts +1 -1
- package/dist/providers/topaz-provider.js +1 -1
- package/dist/providers/video-frame-fallback.d.ts +1 -1
- package/dist/providers/video-frame-fallback.js +4 -4
- package/dist/providers/video-frame-fallback.js.map +1 -1
- package/dist/providers/video-frames.d.ts +6 -16
- package/dist/providers/video-frames.d.ts.map +1 -1
- package/dist/providers/video-frames.js +48 -116
- package/dist/providers/video-frames.js.map +1 -1
- package/dist/storage-workspace.d.ts +1 -61
- package/dist/storage-workspace.d.ts.map +1 -1
- package/dist/storage-workspace.js +2 -430
- package/dist/storage-workspace.js.map +1 -1
- package/dist/testing.d.ts.map +1 -1
- package/dist/testing.js +57 -1
- package/dist/testing.js.map +1 -1
- package/dist/trim-video-window.d.ts.map +1 -1
- package/dist/trim-video-window.js +2 -32
- package/dist/trim-video-window.js.map +1 -1
- package/dist/workspace.d.ts +1 -118
- package/dist/workspace.d.ts.map +1 -1
- package/dist/workspace.js +1 -111
- package/dist/workspace.js.map +1 -1
- package/dist/yt-dlp-format.d.ts +22 -0
- package/dist/yt-dlp-format.d.ts.map +1 -0
- package/dist/yt-dlp-format.js +90 -0
- package/dist/yt-dlp-format.js.map +1 -0
- package/package.json +23 -6
|
@@ -0,0 +1,343 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Test media without the ffmpeg CLI: generate inputs from libavfilter
|
|
3
|
+
* sources (`testsrc2`, `color`, `sine`, `anullsrc`) or from RGBA frames, and
|
|
4
|
+
* measure outputs (duration, size, frame times, pixels, PCM loudness).
|
|
5
|
+
*
|
|
6
|
+
* These run on the same node-av build the server uses, so a test that passes
|
|
7
|
+
* here needs no `ffmpeg` on PATH.
|
|
8
|
+
*/
|
|
9
|
+
import { ALL_FORMATS, EncodedPacketSink, FilePathSource, Input } from "mediabunny";
|
|
10
|
+
import { avGetCodecName, avGetPixFmtName, Decoder, Demuxer, Encoder, FilterAPI } from "node-av";
|
|
11
|
+
import { findEncoder, openFileMuxer, quietLibav } from "./av.js";
|
|
12
|
+
import { decodeAudioToPcm } from "./audio.js";
|
|
13
|
+
import { AudioEncoder } from "./audio-encoder.js";
|
|
14
|
+
import { packetTimes, probeMedia } from "./probe.js";
|
|
15
|
+
import { openRgbaFrameReader, openVideoFrameEncoder } from "./rgba.js";
|
|
16
|
+
async function encodeSource(stream, kind, output) {
|
|
17
|
+
const codecName = stream.codec ?? (kind === "video" ? "libx264" : "aac");
|
|
18
|
+
const demuxer = await Demuxer.open(stream.source, { format: "lavfi" });
|
|
19
|
+
const source = demuxer.streams[0];
|
|
20
|
+
if (!source) {
|
|
21
|
+
await demuxer.close();
|
|
22
|
+
throw new Error(`lavfi source produced no stream: ${stream.source}`);
|
|
23
|
+
}
|
|
24
|
+
const decoder = await Decoder.create(source);
|
|
25
|
+
const steps = [stream.filter, kind === "video" ? `format=${stream.pixelFormat ?? "yuv420p"}` : undefined];
|
|
26
|
+
const chain = steps.filter((step) => Boolean(step)).join(",");
|
|
27
|
+
const filter = FilterAPI.create(chain.length > 0 ? chain : kind === "video" ? "null" : "anull");
|
|
28
|
+
let encode;
|
|
29
|
+
let flush;
|
|
30
|
+
let closeEncoder;
|
|
31
|
+
let index;
|
|
32
|
+
if (kind === "video") {
|
|
33
|
+
const codec = findEncoder(codecName);
|
|
34
|
+
if (!codec)
|
|
35
|
+
throw new Error(`This libav build has no ${codecName} encoder`);
|
|
36
|
+
const encoder = await Encoder.create(codec, { options: stream.options });
|
|
37
|
+
// The muxer sets the global-header flag, which only an unopened encoder takes.
|
|
38
|
+
index = output.muxer.addStream(encoder);
|
|
39
|
+
encode = (frame) => encoder.encodeAll(frame);
|
|
40
|
+
flush = () => encoder.encodeAll(null);
|
|
41
|
+
closeEncoder = () => encoder.close();
|
|
42
|
+
}
|
|
43
|
+
else {
|
|
44
|
+
const encoder = await AudioEncoder.create(codecName, {
|
|
45
|
+
sampleRate: source.codecpar.sampleRate,
|
|
46
|
+
channels: source.codecpar.channels,
|
|
47
|
+
options: stream.options
|
|
48
|
+
});
|
|
49
|
+
index = output.muxer.addStream(encoder.encoder);
|
|
50
|
+
encode = (frame) => encoder.encode(frame);
|
|
51
|
+
flush = () => encoder.flush();
|
|
52
|
+
closeEncoder = () => encoder.close();
|
|
53
|
+
}
|
|
54
|
+
const packets = [];
|
|
55
|
+
try {
|
|
56
|
+
for await (const decoded of decoder.frames(demuxer.packets(source.index))) {
|
|
57
|
+
if (!decoded)
|
|
58
|
+
continue;
|
|
59
|
+
for (const frame of await filter.processAll(decoded)) {
|
|
60
|
+
packets.push(...(await encode(frame)));
|
|
61
|
+
frame.free();
|
|
62
|
+
}
|
|
63
|
+
decoded.free();
|
|
64
|
+
}
|
|
65
|
+
for (const frame of await filter.processAll(null)) {
|
|
66
|
+
packets.push(...(await encode(frame)));
|
|
67
|
+
frame.free();
|
|
68
|
+
}
|
|
69
|
+
packets.push(...(await flush()));
|
|
70
|
+
}
|
|
71
|
+
finally {
|
|
72
|
+
filter.close();
|
|
73
|
+
decoder.close();
|
|
74
|
+
await demuxer.close();
|
|
75
|
+
}
|
|
76
|
+
return {
|
|
77
|
+
packets,
|
|
78
|
+
index,
|
|
79
|
+
close() {
|
|
80
|
+
for (const packet of packets)
|
|
81
|
+
packet.free();
|
|
82
|
+
closeEncoder();
|
|
83
|
+
}
|
|
84
|
+
};
|
|
85
|
+
}
|
|
86
|
+
/**
|
|
87
|
+
* Write a file holding the given streams, as
|
|
88
|
+
* `ffmpeg -f lavfi -i <video> -f lavfi -i <audio> <encoder args> out` did.
|
|
89
|
+
*/
|
|
90
|
+
export async function generateMedia(opts) {
|
|
91
|
+
quietLibav();
|
|
92
|
+
if (!opts.video && !opts.audio)
|
|
93
|
+
throw new Error("Give a video or an audio stream");
|
|
94
|
+
const output = await openFileMuxer(opts.outPath, { muxerOptions: opts.muxerOptions });
|
|
95
|
+
const encoded = [];
|
|
96
|
+
try {
|
|
97
|
+
if (opts.video)
|
|
98
|
+
encoded.push(await encodeSource(opts.video, "video", output));
|
|
99
|
+
if (opts.audio)
|
|
100
|
+
encoded.push(await encodeSource(opts.audio, "audio", output));
|
|
101
|
+
const timed = [];
|
|
102
|
+
for (const { packets, index } of encoded) {
|
|
103
|
+
for (const packet of packets) {
|
|
104
|
+
const { timeBase } = packet;
|
|
105
|
+
timed.push({
|
|
106
|
+
packet,
|
|
107
|
+
stream: index,
|
|
108
|
+
sec: (Number(packet.dts) * timeBase.num) / timeBase.den
|
|
109
|
+
});
|
|
110
|
+
}
|
|
111
|
+
}
|
|
112
|
+
timed.sort((a, b) => a.sec - b.sec);
|
|
113
|
+
for (const { packet, stream } of timed) {
|
|
114
|
+
await output.muxer.writePacket(packet, stream);
|
|
115
|
+
}
|
|
116
|
+
await output.close();
|
|
117
|
+
}
|
|
118
|
+
finally {
|
|
119
|
+
await output.close();
|
|
120
|
+
for (const source of encoded)
|
|
121
|
+
source.close();
|
|
122
|
+
}
|
|
123
|
+
}
|
|
124
|
+
/**
|
|
125
|
+
* Encode frames produced by `frameAt` (packed RGBA8) at `fps`. Defaults to
|
|
126
|
+
* lossless FFV1 so a test reads back exactly what it wrote.
|
|
127
|
+
*/
|
|
128
|
+
export async function writeRgbaVideo(opts) {
|
|
129
|
+
const encoder = await openVideoFrameEncoder({
|
|
130
|
+
outPath: opts.outPath,
|
|
131
|
+
fps: opts.fps,
|
|
132
|
+
input: "rgba",
|
|
133
|
+
width: opts.width,
|
|
134
|
+
height: opts.height,
|
|
135
|
+
spec: opts.spec ?? { codec: "ffv1", pixelFormat: "bgra", options: { level: "3" } }
|
|
136
|
+
});
|
|
137
|
+
try {
|
|
138
|
+
for (let index = 0; index < opts.frames; index++) {
|
|
139
|
+
await encoder.write(opts.frameAt(index));
|
|
140
|
+
}
|
|
141
|
+
await encoder.finish();
|
|
142
|
+
}
|
|
143
|
+
catch (error) {
|
|
144
|
+
await encoder.abort();
|
|
145
|
+
throw error;
|
|
146
|
+
}
|
|
147
|
+
}
|
|
148
|
+
/** A solid RGBA frame. */
|
|
149
|
+
export function solidRgba(width, height, [r, g, b, a]) {
|
|
150
|
+
const frame = new Uint8Array(width * height * 4);
|
|
151
|
+
for (let i = 0; i < frame.length; i += 4) {
|
|
152
|
+
frame[i] = r;
|
|
153
|
+
frame[i + 1] = g;
|
|
154
|
+
frame[i + 2] = b;
|
|
155
|
+
frame[i + 3] = a;
|
|
156
|
+
}
|
|
157
|
+
return frame;
|
|
158
|
+
}
|
|
159
|
+
/** Write 16-bit PCM WAV bytes for interleaved float `samples`. */
|
|
160
|
+
export function encodeWav(samples, sampleRate, channels) {
|
|
161
|
+
const data = samples.length * 2;
|
|
162
|
+
const bytes = new Uint8Array(44 + data);
|
|
163
|
+
const view = new DataView(bytes.buffer);
|
|
164
|
+
const ascii = (offset, text) => {
|
|
165
|
+
for (let i = 0; i < text.length; i++)
|
|
166
|
+
view.setUint8(offset + i, text.charCodeAt(i));
|
|
167
|
+
};
|
|
168
|
+
ascii(0, "RIFF");
|
|
169
|
+
view.setUint32(4, 36 + data, true);
|
|
170
|
+
ascii(8, "WAVE");
|
|
171
|
+
ascii(12, "fmt ");
|
|
172
|
+
view.setUint32(16, 16, true);
|
|
173
|
+
view.setUint16(20, 1, true);
|
|
174
|
+
view.setUint16(22, channels, true);
|
|
175
|
+
view.setUint32(24, sampleRate, true);
|
|
176
|
+
view.setUint32(28, sampleRate * channels * 2, true);
|
|
177
|
+
view.setUint16(32, channels * 2, true);
|
|
178
|
+
view.setUint16(34, 16, true);
|
|
179
|
+
ascii(36, "data");
|
|
180
|
+
view.setUint32(40, data, true);
|
|
181
|
+
for (let i = 0; i < samples.length; i++) {
|
|
182
|
+
const clamped = Math.max(-1, Math.min(1, samples[i] ?? 0));
|
|
183
|
+
view.setInt16(44 + i * 2, Math.round(clamped * 32767), true);
|
|
184
|
+
}
|
|
185
|
+
return bytes;
|
|
186
|
+
}
|
|
187
|
+
/** Interleaved samples of a sine, or silence at `amplitude: 0`. */
|
|
188
|
+
export function sineSamples(opts) {
|
|
189
|
+
const frames = Math.round(opts.sampleRate * opts.durationSec);
|
|
190
|
+
const amplitude = opts.amplitude ?? 0.5;
|
|
191
|
+
const samples = new Float32Array(frames * opts.channels);
|
|
192
|
+
for (let i = 0; i < frames; i++) {
|
|
193
|
+
const value = amplitude * Math.sin((2 * Math.PI * opts.frequency * i) / opts.sampleRate);
|
|
194
|
+
for (let c = 0; c < opts.channels; c++)
|
|
195
|
+
samples[i * opts.channels + c] = value;
|
|
196
|
+
}
|
|
197
|
+
return samples;
|
|
198
|
+
}
|
|
199
|
+
/** Probe `filePath` and list its video frame times. */
|
|
200
|
+
export async function inspectMedia(filePath) {
|
|
201
|
+
const probe = await probeMedia(filePath, { frameRatePackets: Number.POSITIVE_INFINITY });
|
|
202
|
+
const times = probe.video ? ((await packetTimes(filePath)) ?? []) : [];
|
|
203
|
+
return { ...probe, frameTimes: [...times].sort((a, b) => a - b) };
|
|
204
|
+
}
|
|
205
|
+
/**
|
|
206
|
+
* Every video packet's presentation time (seconds, rounded to the
|
|
207
|
+
* microsecond as ffprobe prints `pts_time`) and keyframe flag, in
|
|
208
|
+
* presentation order.
|
|
209
|
+
*/
|
|
210
|
+
export async function videoPacketInfo(filePath) {
|
|
211
|
+
const input = new Input({ source: new FilePathSource(filePath), formats: ALL_FORMATS });
|
|
212
|
+
try {
|
|
213
|
+
const track = await input.getPrimaryVideoTrack();
|
|
214
|
+
if (!track)
|
|
215
|
+
return [];
|
|
216
|
+
const packets = [];
|
|
217
|
+
for await (const packet of new EncodedPacketSink(track).packets(undefined, undefined, {
|
|
218
|
+
metadataOnly: true
|
|
219
|
+
})) {
|
|
220
|
+
packets.push({ pts: Math.round(packet.timestamp * 1e6) / 1e6, key: packet.type === "key" });
|
|
221
|
+
}
|
|
222
|
+
return packets.sort((a, b) => a.pts - b.pts);
|
|
223
|
+
}
|
|
224
|
+
finally {
|
|
225
|
+
input.dispose();
|
|
226
|
+
}
|
|
227
|
+
}
|
|
228
|
+
/** Every video frame of `filePath` as RGBA at `width`x`height`, in order. */
|
|
229
|
+
export async function readRgbaFrames(filePath, size) {
|
|
230
|
+
const reader = await openRgbaFrameReader({
|
|
231
|
+
filePath,
|
|
232
|
+
filter: `scale=${size.width}:${size.height}:flags=accurate_rnd+full_chroma_int,format=rgba`
|
|
233
|
+
});
|
|
234
|
+
if (!reader)
|
|
235
|
+
return [];
|
|
236
|
+
const frames = [];
|
|
237
|
+
try {
|
|
238
|
+
for (let frame = await reader.next(); frame; frame = await reader.next()) {
|
|
239
|
+
frames.push(frame.rgba);
|
|
240
|
+
}
|
|
241
|
+
}
|
|
242
|
+
finally {
|
|
243
|
+
await reader.close();
|
|
244
|
+
}
|
|
245
|
+
return frames;
|
|
246
|
+
}
|
|
247
|
+
/** Mean of each RGBA channel over a frame. */
|
|
248
|
+
export function meanRgba(rgba) {
|
|
249
|
+
const sums = [0, 0, 0, 0];
|
|
250
|
+
for (let i = 0; i < rgba.length; i += 4) {
|
|
251
|
+
for (let c = 0; c < 4; c++)
|
|
252
|
+
sums[c] += rgba[i + c] ?? 0;
|
|
253
|
+
}
|
|
254
|
+
const pixels = Math.max(1, rgba.length / 4);
|
|
255
|
+
return [sums[0] / pixels, sums[1] / pixels, sums[2] / pixels, sums[3] / pixels];
|
|
256
|
+
}
|
|
257
|
+
/** `filePath`'s audio as interleaved float PCM. */
|
|
258
|
+
export function readPcm(filePath, options) {
|
|
259
|
+
return decodeAudioToPcm(filePath, options);
|
|
260
|
+
}
|
|
261
|
+
/** RMS of `audio` between two times, over every channel. */
|
|
262
|
+
export function rmsBetween(audio, startSec, endSec) {
|
|
263
|
+
const first = Math.max(0, Math.floor(startSec * audio.sampleRate)) * audio.channels;
|
|
264
|
+
const last = Math.min(audio.samples.length, Math.floor(endSec * audio.sampleRate) * audio.channels);
|
|
265
|
+
if (last <= first)
|
|
266
|
+
return 0;
|
|
267
|
+
let sum = 0;
|
|
268
|
+
for (let i = first; i < last; i++)
|
|
269
|
+
sum += (audio.samples[i] ?? 0) ** 2;
|
|
270
|
+
return Math.sqrt(sum / (last - first));
|
|
271
|
+
}
|
|
272
|
+
/** ffprobe's names for the color tags a test checks; anything else reads as its number. */
|
|
273
|
+
const COLOR_SPACES = { 0: "gbr", 1: "bt709", 2: "unknown", 5: "bt470bg", 6: "smpte170m", 9: "bt2020nc" };
|
|
274
|
+
const COLOR_PRIMARIES = { 1: "bt709", 2: "unknown", 5: "bt470bg", 6: "smpte170m", 9: "bt2020" };
|
|
275
|
+
const COLOR_TRANSFERS = { 1: "bt709", 2: "unknown", 6: "smpte170m", 13: "iec61966-2-1", 14: "bt2020-10" };
|
|
276
|
+
const COLOR_RANGES = { 0: "unknown", 1: "tv", 2: "pc" };
|
|
277
|
+
/** The first video stream's codec, pixel format and tags, or null without one. */
|
|
278
|
+
export async function videoStreamFormat(filePath) {
|
|
279
|
+
const demuxer = await Demuxer.open(filePath);
|
|
280
|
+
try {
|
|
281
|
+
const stream = demuxer.video();
|
|
282
|
+
if (!stream)
|
|
283
|
+
return null;
|
|
284
|
+
const { codecpar } = stream;
|
|
285
|
+
const name = (table, value) => table[value] ?? String(value);
|
|
286
|
+
return {
|
|
287
|
+
codec: avGetCodecName(codecpar.codecId) ?? "",
|
|
288
|
+
// SAFETY: a video stream's `format` is a pixel format.
|
|
289
|
+
pixelFormat: avGetPixFmtName(codecpar.format) ?? "",
|
|
290
|
+
colorSpace: name(COLOR_SPACES, codecpar.colorSpace),
|
|
291
|
+
colorPrimaries: name(COLOR_PRIMARIES, codecpar.colorPrimaries),
|
|
292
|
+
colorTransfer: name(COLOR_TRANSFERS, codecpar.colorTrc),
|
|
293
|
+
colorRange: name(COLOR_RANGES, codecpar.colorRange),
|
|
294
|
+
tags: stream.metadata?.getAll() ?? {}
|
|
295
|
+
};
|
|
296
|
+
}
|
|
297
|
+
finally {
|
|
298
|
+
await demuxer.close();
|
|
299
|
+
}
|
|
300
|
+
}
|
|
301
|
+
/**
|
|
302
|
+
* Every video frame of `filePath` as RGBA at `width`x`height`, decoded by the
|
|
303
|
+
* named libav decoder rather than the default one. A test of VP9 alpha needs
|
|
304
|
+
* `libvpx-vp9`: libav's native vp9 decoder drops the alpha plane WebM keeps
|
|
305
|
+
* in BlockAdditions, as `ffmpeg -c:v libvpx-vp9 -i` was needed to read it.
|
|
306
|
+
*/
|
|
307
|
+
export async function readRgbaFramesWith(filePath, decoderName, size) {
|
|
308
|
+
quietLibav();
|
|
309
|
+
const demuxer = await Demuxer.open(filePath);
|
|
310
|
+
let decoder = null;
|
|
311
|
+
let filter = null;
|
|
312
|
+
try {
|
|
313
|
+
const stream = demuxer.video();
|
|
314
|
+
if (!stream)
|
|
315
|
+
return [];
|
|
316
|
+
// SAFETY: `decoderName` is a libav decoder name; an unknown one makes
|
|
317
|
+
// `create` throw, which fails the test that named it.
|
|
318
|
+
decoder = await Decoder.create(stream, decoderName);
|
|
319
|
+
const activeFilter = FilterAPI.create(`scale=${size.width}:${size.height}:flags=accurate_rnd+full_chroma_int,format=rgba`);
|
|
320
|
+
filter = activeFilter;
|
|
321
|
+
const frames = [];
|
|
322
|
+
const take = async (frame) => {
|
|
323
|
+
for (const out of await activeFilter.processAll(frame)) {
|
|
324
|
+
frames.push(new Uint8Array(out.toBuffer()));
|
|
325
|
+
out.free();
|
|
326
|
+
}
|
|
327
|
+
};
|
|
328
|
+
for await (const frame of decoder.frames(demuxer.packets(stream.index))) {
|
|
329
|
+
if (!frame)
|
|
330
|
+
continue;
|
|
331
|
+
await take(frame);
|
|
332
|
+
frame.free();
|
|
333
|
+
}
|
|
334
|
+
await take(null);
|
|
335
|
+
return frames;
|
|
336
|
+
}
|
|
337
|
+
finally {
|
|
338
|
+
filter?.close();
|
|
339
|
+
decoder?.close();
|
|
340
|
+
await demuxer.close();
|
|
341
|
+
}
|
|
342
|
+
}
|
|
343
|
+
//# sourceMappingURL=testing.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"testing.js","sourceRoot":"","sources":["../../src/media/testing.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Re-encode a file's video through a filter chain with node-av: the
|
|
3
|
+
* in-process form of `ffmpeg -i in -map 0:v:0 -vf <filter> <codec args> out`.
|
|
4
|
+
* Frame timestamps pass through, so a variable-rate source stays variable.
|
|
5
|
+
*/
|
|
6
|
+
import type { VideoEncoderSpec } from "./rgba.js";
|
|
7
|
+
export declare function transcodeVideo(opts: {
|
|
8
|
+
inputPath: string;
|
|
9
|
+
outPath: string;
|
|
10
|
+
spec: VideoEncoderSpec;
|
|
11
|
+
/** Container muxer name; defaults to the one for the extension. */
|
|
12
|
+
format?: string;
|
|
13
|
+
/** Muxer AVOptions, e.g. `{ movflags: "+faststart" }`. */
|
|
14
|
+
muxerOptions?: Record<string, string>;
|
|
15
|
+
signal?: AbortSignal;
|
|
16
|
+
}): Promise<void>;
|
|
17
|
+
//# sourceMappingURL=transcode.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"transcode.d.ts","sourceRoot":"","sources":["../../src/media/transcode.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAEH,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,WAAW,CAAC;AAGlD,wBAAsB,cAAc,CAAC,IAAI,EAAE;IACzC,SAAS,EAAE,MAAM,CAAC;IAClB,OAAO,EAAE,MAAM,CAAC;IAChB,IAAI,EAAE,gBAAgB,CAAC;IACvB,mEAAmE;IACnE,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,0DAA0D;IAC1D,YAAY,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;IACtC,MAAM,CAAC,EAAE,WAAW,CAAC;CACtB,GAAG,OAAO,CAAC,IAAI,CAAC,CAWhB"}
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Re-encode a file's video through a filter chain with node-av: the
|
|
3
|
+
* in-process form of `ffmpeg -i in -map 0:v:0 -vf <filter> <codec args> out`.
|
|
4
|
+
* Frame timestamps pass through, so a variable-rate source stays variable.
|
|
5
|
+
*/
|
|
6
|
+
import { transformMedia } from "./transform.js";
|
|
7
|
+
export async function transcodeVideo(opts) {
|
|
8
|
+
await transformMedia({
|
|
9
|
+
inputs: [{ filePath: opts.inputPath }],
|
|
10
|
+
outPath: opts.outPath,
|
|
11
|
+
video: { filter: "null" },
|
|
12
|
+
audio: null,
|
|
13
|
+
videoEncoder: opts.spec,
|
|
14
|
+
format: opts.format,
|
|
15
|
+
muxerOptions: opts.muxerOptions,
|
|
16
|
+
signal: opts.signal
|
|
17
|
+
});
|
|
18
|
+
}
|
|
19
|
+
//# sourceMappingURL=transcode.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"transcode.js","sourceRoot":"","sources":["../../src/media/transcode.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAGH,OAAO,EAAE,cAAc,EAAE,MAAM,gBAAgB,CAAC;AAEhD,MAAM,CAAC,KAAK,UAAU,cAAc,CAAC,IASpC;IACC,MAAM,cAAc,CAAC;QACnB,MAAM,EAAE,CAAC,EAAE,QAAQ,EAAE,IAAI,CAAC,SAAS,EAAE,CAAC;QACtC,OAAO,EAAE,IAAI,CAAC,OAAO;QACrB,KAAK,EAAE,EAAE,MAAM,EAAE,MAAM,EAAE;QACzB,KAAK,EAAE,IAAI;QACX,YAAY,EAAE,IAAI,CAAC,IAAI;QACvB,MAAM,EAAE,IAAI,CAAC,MAAM;QACnB,YAAY,EAAE,IAAI,CAAC,YAAY;QAC/B,MAAM,EAAE,IAAI,CAAC,MAAM;KACpB,CAAC,CAAC;AACL,CAAC"}
|
|
@@ -0,0 +1,61 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* One output file from filtered or copied input streams: the in-process form
|
|
3
|
+
* of the ffmpeg CLI invocations the video nodes ran, `-vf`, `-af`,
|
|
4
|
+
* `-filter_complex` with `-map`, `-c copy` and `-shortest`. The graph strings
|
|
5
|
+
* are the CLI's, unchanged.
|
|
6
|
+
*/
|
|
7
|
+
import type { VideoEncoderSpec } from "./rgba.js";
|
|
8
|
+
/** An input file, as `-ss S -to E -i path` named it. */
|
|
9
|
+
export interface TransformInput {
|
|
10
|
+
filePath: string;
|
|
11
|
+
/** Source seconds to start at (`-ss` before `-i`). */
|
|
12
|
+
seekSec?: number;
|
|
13
|
+
/** Source seconds to stop reading at (`-to` before `-i`). */
|
|
14
|
+
toSec?: number;
|
|
15
|
+
}
|
|
16
|
+
/**
|
|
17
|
+
* Where one output stream comes from.
|
|
18
|
+
*
|
|
19
|
+
* - `copy`: the input's first stream of the kind, packets unchanged (`-c copy`).
|
|
20
|
+
* - `filter`: a `-vf` or `-af` chain over the input's first stream of the kind.
|
|
21
|
+
* - `graph`: a `-filter_complex` graph whose inputs are labelled `[N:v]` and
|
|
22
|
+
* `[N:a]` after the input index, read at link `output`.
|
|
23
|
+
*
|
|
24
|
+
* A missing stream throws, as the CLI failed on a stream specifier that
|
|
25
|
+
* matched nothing, unless `optional` is set: then the output has no such
|
|
26
|
+
* stream, as the CLI's default stream selection left it out.
|
|
27
|
+
*/
|
|
28
|
+
export type StreamPlan = {
|
|
29
|
+
copy: number;
|
|
30
|
+
optional?: boolean;
|
|
31
|
+
} | {
|
|
32
|
+
filter: string;
|
|
33
|
+
input?: number;
|
|
34
|
+
optional?: boolean;
|
|
35
|
+
} | {
|
|
36
|
+
graph: string;
|
|
37
|
+
output: string;
|
|
38
|
+
};
|
|
39
|
+
/** The CLI's defaults for an `.mp4` output: H.264 in yuv420p. */
|
|
40
|
+
export declare const DEFAULT_VIDEO_ENCODER: VideoEncoderSpec;
|
|
41
|
+
/**
|
|
42
|
+
* Write `outPath` from `inputs`. `video` and `audio` name where each output
|
|
43
|
+
* stream comes from, or `null` for none. Filtered streams are encoded with
|
|
44
|
+
* `videoEncoder` (H.264 yuv420p by default) and `audioCodec` (AAC by default,
|
|
45
|
+
* at the filtered rate and channel count). `shortest` ends the file when its
|
|
46
|
+
* first stream ends, as `-shortest` did.
|
|
47
|
+
*/
|
|
48
|
+
export declare function transformMedia(opts: {
|
|
49
|
+
inputs: TransformInput[];
|
|
50
|
+
outPath: string;
|
|
51
|
+
video: StreamPlan | null;
|
|
52
|
+
audio: StreamPlan | null;
|
|
53
|
+
videoEncoder?: VideoEncoderSpec;
|
|
54
|
+
audioCodec?: string;
|
|
55
|
+
shortest?: boolean;
|
|
56
|
+
/** Container muxer name; defaults to the one for the extension. */
|
|
57
|
+
format?: string;
|
|
58
|
+
muxerOptions?: Record<string, string>;
|
|
59
|
+
signal?: AbortSignal;
|
|
60
|
+
}): Promise<void>;
|
|
61
|
+
//# sourceMappingURL=transform.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"transform.d.ts","sourceRoot":"","sources":["../../src/media/transform.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AA6BH,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,WAAW,CAAC;AAElD,wDAAwD;AACxD,MAAM,WAAW,cAAc;IAC7B,QAAQ,EAAE,MAAM,CAAC;IACjB,sDAAsD;IACtD,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,6DAA6D;IAC7D,KAAK,CAAC,EAAE,MAAM,CAAC;CAChB;AAED;;;;;;;;;;;GAWG;AACH,MAAM,MAAM,UAAU,GAClB;IAAE,IAAI,EAAE,MAAM,CAAC;IAAC,QAAQ,CAAC,EAAE,OAAO,CAAA;CAAE,GACpC;IAAE,MAAM,EAAE,MAAM,CAAC;IAAC,KAAK,CAAC,EAAE,MAAM,CAAC;IAAC,QAAQ,CAAC,EAAE,OAAO,CAAA;CAAE,GACtD;IAAE,KAAK,EAAE,MAAM,CAAC;IAAC,MAAM,EAAE,MAAM,CAAA;CAAE,CAAC;AAEtC,iEAAiE;AACjE,eAAO,MAAM,qBAAqB,EAAE,gBAGnC,CAAC;AAmSF;;;;;;GAMG;AACH,wBAAsB,cAAc,CAAC,IAAI,EAAE;IACzC,MAAM,EAAE,cAAc,EAAE,CAAC;IACzB,OAAO,EAAE,MAAM,CAAC;IAChB,KAAK,EAAE,UAAU,GAAG,IAAI,CAAC;IACzB,KAAK,EAAE,UAAU,GAAG,IAAI,CAAC;IACzB,YAAY,CAAC,EAAE,gBAAgB,CAAC;IAChC,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,QAAQ,CAAC,EAAE,OAAO,CAAC;IACnB,mEAAmE;IACnE,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,YAAY,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;IACtC,MAAM,CAAC,EAAE,WAAW,CAAC;CACtB,GAAG,OAAO,CAAC,IAAI,CAAC,CA6ChB"}
|