@nodetool-ai/runtime 0.8.7 → 0.8.9-beta.1
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 +21 -0
- package/dist/providers/anthropic-provider.d.ts.map +1 -1
- package/dist/providers/anthropic-provider.js +82 -17
- package/dist/providers/anthropic-provider.js.map +1 -1
- package/dist/providers/claude-agent-provider.js +14 -2
- package/dist/providers/claude-agent-provider.js.map +1 -1
- package/dist/providers/codex-provider.d.ts +10 -0
- package/dist/providers/codex-provider.d.ts.map +1 -1
- package/dist/providers/codex-provider.js +29 -3
- package/dist/providers/codex-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/dreamina-provider.d.ts +1 -1
- package/dist/providers/dreamina-provider.d.ts.map +1 -1
- package/dist/providers/dreamina-provider.js +54 -72
- package/dist/providers/dreamina-provider.js.map +1 -1
- package/dist/providers/fake-provider.js +1 -1
- package/dist/providers/gemini-provider.d.ts.map +1 -1
- package/dist/providers/gemini-provider.js +23 -0
- package/dist/providers/gemini-provider.js.map +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 +121 -121
- 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.d.ts +12 -0
- package/dist/providers/openai-provider.d.ts.map +1 -1
- package/dist/providers/openai-provider.js +27 -2
- package/dist/providers/openai-provider.js.map +1 -1
- package/dist/providers/openrouter-provider.js +1 -1
- package/dist/providers/openrouter-provider.js.map +1 -1
- package/dist/providers/requesty-provider.js +1 -1
- package/dist/providers/requesty-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/python-bridge-base.d.ts +2 -0
- package/dist/python-bridge-base.d.ts.map +1 -1
- package/dist/python-bridge-base.js +9 -26
- package/dist/python-bridge-base.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
package/dist/media/av.js
ADDED
|
@@ -0,0 +1,146 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* node-av plumbing shared by the media module: logging, encoder lookup,
|
|
3
|
+
* container names and a file muxer that does not leak descriptors.
|
|
4
|
+
*/
|
|
5
|
+
import { closeSync, openSync, readSync, writeSync } from "node:fs";
|
|
6
|
+
import path from "node:path";
|
|
7
|
+
import { AV_LOG_ERROR, AVSEEK_CUR, AVSEEK_END, AVSEEK_SET, AVSEEK_SIZE, Codec, Log, Muxer } from "node-av";
|
|
8
|
+
let logLevelSet = false;
|
|
9
|
+
/**
|
|
10
|
+
* Keep libav quiet unless something failed. Its default level prints every
|
|
11
|
+
* encoder's settings banner to stderr, once per open.
|
|
12
|
+
*/
|
|
13
|
+
export function quietLibav() {
|
|
14
|
+
if (logLevelSet)
|
|
15
|
+
return;
|
|
16
|
+
logLevelSet = true;
|
|
17
|
+
Log.setLevel(AV_LOG_ERROR);
|
|
18
|
+
}
|
|
19
|
+
export { abortError, throwIfAborted } from "./abort.js";
|
|
20
|
+
/** The encoder named `name`, or `null` when this build has none. */
|
|
21
|
+
export function findEncoder(name) {
|
|
22
|
+
// SAFETY: `FFEncoderCodec` is node-av's list of known encoder names. A name
|
|
23
|
+
// outside it is a lookup that returns null, which is what callers test for.
|
|
24
|
+
return Codec.findEncoderByName(name);
|
|
25
|
+
}
|
|
26
|
+
/** Container short names for the extensions the server writes. */
|
|
27
|
+
const FORMAT_BY_EXTENSION = {
|
|
28
|
+
".mp4": "mp4",
|
|
29
|
+
".m4a": "ipod",
|
|
30
|
+
".mov": "mov",
|
|
31
|
+
".webm": "webm",
|
|
32
|
+
".mkv": "matroska",
|
|
33
|
+
".wav": "wav",
|
|
34
|
+
".mp3": "mp3",
|
|
35
|
+
".ogg": "ogg",
|
|
36
|
+
".opus": "opus",
|
|
37
|
+
".flac": "flac",
|
|
38
|
+
".h264": "h264"
|
|
39
|
+
};
|
|
40
|
+
/** The libav muxer name for `filePath`, from its extension. */
|
|
41
|
+
export function muxerFormatFor(filePath) {
|
|
42
|
+
const format = FORMAT_BY_EXTENSION[path.extname(filePath).toLowerCase()];
|
|
43
|
+
if (!format) {
|
|
44
|
+
throw new Error(`No muxer is configured for ${path.basename(filePath)}`);
|
|
45
|
+
}
|
|
46
|
+
return format;
|
|
47
|
+
}
|
|
48
|
+
/**
|
|
49
|
+
* Open a muxer over a file descriptor this module owns.
|
|
50
|
+
*
|
|
51
|
+
* `Muxer.open(path)` leaks one file descriptor and a few hundred kilobytes on
|
|
52
|
+
* every open and close in node-av 6.1.1 (see risk R6 in
|
|
53
|
+
* docs/ffmpeg-in-process-plan.md), so a server that renders all day runs out of
|
|
54
|
+
* descriptors. Custom IO closes cleanly. The callbacks read and write at an
|
|
55
|
+
* explicit position because MP4 and MOV seek back to rewrite their headers.
|
|
56
|
+
*
|
|
57
|
+
* The callbacks are synchronous on purpose. libav calls them from a libuv
|
|
58
|
+
* pool thread that blocks until the JS callback returns; an async `fs` call
|
|
59
|
+
* inside it needs a pool thread of its own, so as many concurrent muxers as
|
|
60
|
+
* the pool has threads (4 by default) deadlocked the process.
|
|
61
|
+
*/
|
|
62
|
+
export async function openFileMuxer(filePath, options = {}) {
|
|
63
|
+
const fd = openSync(filePath, "w+");
|
|
64
|
+
let position = 0;
|
|
65
|
+
let size = 0;
|
|
66
|
+
let muxer;
|
|
67
|
+
try {
|
|
68
|
+
muxer = await Muxer.open({
|
|
69
|
+
write: (buffer) => {
|
|
70
|
+
const written = writeSync(fd, buffer, 0, buffer.length, position);
|
|
71
|
+
position += written;
|
|
72
|
+
size = Math.max(size, position);
|
|
73
|
+
return written;
|
|
74
|
+
},
|
|
75
|
+
// `movflags=+faststart` reads the finished file back to move its index
|
|
76
|
+
// to the front.
|
|
77
|
+
read: (length) => {
|
|
78
|
+
const buffer = Buffer.alloc(length);
|
|
79
|
+
const read = readSync(fd, buffer, 0, length, position);
|
|
80
|
+
if (read === 0)
|
|
81
|
+
return null;
|
|
82
|
+
position += read;
|
|
83
|
+
return buffer.subarray(0, read);
|
|
84
|
+
},
|
|
85
|
+
seek: (offset, whence) => {
|
|
86
|
+
const delta = Number(offset);
|
|
87
|
+
if (whence === AVSEEK_SIZE)
|
|
88
|
+
return size;
|
|
89
|
+
if (whence === AVSEEK_SET)
|
|
90
|
+
position = delta;
|
|
91
|
+
else if (whence === AVSEEK_CUR)
|
|
92
|
+
position += delta;
|
|
93
|
+
else if (whence === AVSEEK_END)
|
|
94
|
+
position = size + delta;
|
|
95
|
+
else
|
|
96
|
+
return -1;
|
|
97
|
+
return position;
|
|
98
|
+
}
|
|
99
|
+
}, {
|
|
100
|
+
format: options.format ?? muxerFormatFor(filePath),
|
|
101
|
+
signal: options.signal,
|
|
102
|
+
options: options.muxerOptions,
|
|
103
|
+
// MOV's `+faststart` re-opens the output by name to read it back.
|
|
104
|
+
configure: (context) => {
|
|
105
|
+
context.url = filePath;
|
|
106
|
+
}
|
|
107
|
+
});
|
|
108
|
+
}
|
|
109
|
+
catch (error) {
|
|
110
|
+
closeSync(fd);
|
|
111
|
+
throw error;
|
|
112
|
+
}
|
|
113
|
+
let closing = null;
|
|
114
|
+
return {
|
|
115
|
+
muxer,
|
|
116
|
+
close() {
|
|
117
|
+
closing ??= (async () => {
|
|
118
|
+
try {
|
|
119
|
+
await muxer.close();
|
|
120
|
+
}
|
|
121
|
+
finally {
|
|
122
|
+
closeSync(fd);
|
|
123
|
+
}
|
|
124
|
+
})();
|
|
125
|
+
return closing;
|
|
126
|
+
}
|
|
127
|
+
};
|
|
128
|
+
}
|
|
129
|
+
/** Seconds from a format or stream start time, or 0 when libav has none. */
|
|
130
|
+
export function startTimeSeconds(startTime, timeBase) {
|
|
131
|
+
// AV_NOPTS_VALUE is INT64_MIN.
|
|
132
|
+
if (startTime <= -(2n ** 62n))
|
|
133
|
+
return 0;
|
|
134
|
+
return (Number(startTime) * timeBase.num) / timeBase.den;
|
|
135
|
+
}
|
|
136
|
+
/** A rational for `value`, exact for integer and NTSC-style rates. */
|
|
137
|
+
export function rationalFor(value) {
|
|
138
|
+
if (Number.isInteger(value))
|
|
139
|
+
return { num: value, den: 1 };
|
|
140
|
+
const ntsc = Math.round(value * 1001);
|
|
141
|
+
if (Math.abs(ntsc / 1001 - value) < 1e-9)
|
|
142
|
+
return { num: ntsc, den: 1001 };
|
|
143
|
+
const scaled = Math.round(value * 1000);
|
|
144
|
+
return { num: scaled, den: 1000 };
|
|
145
|
+
}
|
|
146
|
+
//# sourceMappingURL=av.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"av.js","sourceRoot":"","sources":["../../src/media/av.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
/** What the bundled libav build can do, asked of node-av directly. */
|
|
2
|
+
/**
|
|
3
|
+
* Whether the bundled libav has encoder `name` (`libx264`, `prores_ks`, ...).
|
|
4
|
+
* Replaces scanning `ffmpeg -encoders`.
|
|
5
|
+
*/
|
|
6
|
+
export declare function hasEncoder(name: string, signal?: AbortSignal): Promise<boolean>;
|
|
7
|
+
/** Whether the bundled libav has filter `name` (`xfade`, `drawtext`, ...). */
|
|
8
|
+
export declare function hasFilter(name: string, signal?: AbortSignal): Promise<boolean>;
|
|
9
|
+
//# sourceMappingURL=codecs.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"codecs.d.ts","sourceRoot":"","sources":["../../src/media/codecs.ts"],"names":[],"mappings":"AAAA,sEAAsE;AAMtE;;;GAGG;AACH,wBAAsB,UAAU,CAAC,IAAI,EAAE,MAAM,EAAE,MAAM,CAAC,EAAE,WAAW,GAAG,OAAO,CAAC,OAAO,CAAC,CAGrF;AAED,8EAA8E;AAC9E,wBAAsB,SAAS,CAAC,IAAI,EAAE,MAAM,EAAE,MAAM,CAAC,EAAE,WAAW,GAAG,OAAO,CAAC,OAAO,CAAC,CAGpF"}
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
/** What the bundled libav build can do, asked of node-av directly. */
|
|
2
|
+
import { Filter } from "node-av";
|
|
3
|
+
import { findEncoder, throwIfAborted } from "./av.js";
|
|
4
|
+
/**
|
|
5
|
+
* Whether the bundled libav has encoder `name` (`libx264`, `prores_ks`, ...).
|
|
6
|
+
* Replaces scanning `ffmpeg -encoders`.
|
|
7
|
+
*/
|
|
8
|
+
export async function hasEncoder(name, signal) {
|
|
9
|
+
throwIfAborted(signal);
|
|
10
|
+
return findEncoder(name) !== null;
|
|
11
|
+
}
|
|
12
|
+
/** Whether the bundled libav has filter `name` (`xfade`, `drawtext`, ...). */
|
|
13
|
+
export async function hasFilter(name, signal) {
|
|
14
|
+
throwIfAborted(signal);
|
|
15
|
+
return Filter.getByName(name) !== null;
|
|
16
|
+
}
|
|
17
|
+
//# sourceMappingURL=codecs.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"codecs.js","sourceRoot":"","sources":["../../src/media/codecs.ts"],"names":[],"mappings":"AAAA,sEAAsE;AAEtE,OAAO,EAAE,MAAM,EAAE,MAAM,SAAS,CAAC;AAEjC,OAAO,EAAE,WAAW,EAAE,cAAc,EAAE,MAAM,SAAS,CAAC;AAEtD;;;GAGG;AACH,MAAM,CAAC,KAAK,UAAU,UAAU,CAAC,IAAY,EAAE,MAAoB;IACjE,cAAc,CAAC,MAAM,CAAC,CAAC;IACvB,OAAO,WAAW,CAAC,IAAI,CAAC,KAAK,IAAI,CAAC;AACpC,CAAC;AAED,8EAA8E;AAC9E,MAAM,CAAC,KAAK,UAAU,SAAS,CAAC,IAAY,EAAE,MAAoB;IAChE,cAAc,CAAC,MAAM,CAAC,CAAC;IACvB,OAAO,MAAM,CAAC,SAAS,CAAC,IAAI,CAAC,KAAK,IAAI,CAAC;AACzC,CAAC"}
|
|
@@ -0,0 +1,56 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Normalize clips to one frame size, rate and audio format and write them end
|
|
3
|
+
* to end into one file: the in-process form of encoding a segment per clip
|
|
4
|
+
* with `-vf <filter>` and joining them with the concat demuxer and `-c copy`.
|
|
5
|
+
* Doing it in one pass leaves no segment files and no remux.
|
|
6
|
+
*/
|
|
7
|
+
import type { VideoEncoderSpec } from "./rgba.js";
|
|
8
|
+
/** One piece of the output, `durationSec` long. */
|
|
9
|
+
export type ConcatSegment = {
|
|
10
|
+
kind: "video";
|
|
11
|
+
filePath: string;
|
|
12
|
+
/** Source seconds to start at (`-ss` before `-i`). */
|
|
13
|
+
inSec?: number;
|
|
14
|
+
/** Source seconds to stop reading at (`-to` before `-i`). */
|
|
15
|
+
outSec?: number;
|
|
16
|
+
durationSec: number;
|
|
17
|
+
/** Use the clip's own sound; otherwise, or when it has none, silence. */
|
|
18
|
+
withAudio: boolean;
|
|
19
|
+
} | {
|
|
20
|
+
kind: "image";
|
|
21
|
+
filePath: string;
|
|
22
|
+
durationSec: number;
|
|
23
|
+
}
|
|
24
|
+
/** Black picture and silence. */
|
|
25
|
+
| {
|
|
26
|
+
kind: "blank";
|
|
27
|
+
durationSec: number;
|
|
28
|
+
};
|
|
29
|
+
export declare function concatSegments(opts: {
|
|
30
|
+
outPath: string;
|
|
31
|
+
width: number;
|
|
32
|
+
height: number;
|
|
33
|
+
fps: number;
|
|
34
|
+
segments: ConcatSegment[];
|
|
35
|
+
/**
|
|
36
|
+
* A `-vf` chain that fits any picture to `width`x`height`, e.g. scale and
|
|
37
|
+
* pad. A video segment is then resampled to `fps`, and every segment
|
|
38
|
+
* converted to the spec's pixel format.
|
|
39
|
+
*/
|
|
40
|
+
videoFilter: string;
|
|
41
|
+
video: VideoEncoderSpec;
|
|
42
|
+
audioCodec: string;
|
|
43
|
+
signal?: AbortSignal;
|
|
44
|
+
}): Promise<void>;
|
|
45
|
+
/**
|
|
46
|
+
* Join files whose streams share codec, size and rate without re-encoding:
|
|
47
|
+
* the in-process form of the concat demuxer with `-c copy`. Each file's
|
|
48
|
+
* packets follow the previous file's, offset by where that file ended. The
|
|
49
|
+
* output takes its stream parameters from the first file.
|
|
50
|
+
*/
|
|
51
|
+
export declare function concatCopy(opts: {
|
|
52
|
+
inputPaths: string[];
|
|
53
|
+
outPath: string;
|
|
54
|
+
signal?: AbortSignal;
|
|
55
|
+
}): Promise<void>;
|
|
56
|
+
//# sourceMappingURL=concat.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"concat.d.ts","sourceRoot":"","sources":["../../src/media/concat.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AA0BH,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,WAAW,CAAC;AAElD,mDAAmD;AACnD,MAAM,MAAM,aAAa,GACrB;IACE,IAAI,EAAE,OAAO,CAAC;IACd,QAAQ,EAAE,MAAM,CAAC;IACjB,sDAAsD;IACtD,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,6DAA6D;IAC7D,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,WAAW,EAAE,MAAM,CAAC;IACpB,yEAAyE;IACzE,SAAS,EAAE,OAAO,CAAC;CACpB,GACD;IAAE,IAAI,EAAE,OAAO,CAAC;IAAC,QAAQ,EAAE,MAAM,CAAC;IAAC,WAAW,EAAE,MAAM,CAAA;CAAE;AAC1D,iCAAiC;GAC/B;IAAE,IAAI,EAAE,OAAO,CAAC;IAAC,WAAW,EAAE,MAAM,CAAA;CAAE,CAAC;AAK3C,wBAAsB,cAAc,CAAC,IAAI,EAAE;IACzC,OAAO,EAAE,MAAM,CAAC;IAChB,KAAK,EAAE,MAAM,CAAC;IACd,MAAM,EAAE,MAAM,CAAC;IACf,GAAG,EAAE,MAAM,CAAC;IACZ,QAAQ,EAAE,aAAa,EAAE,CAAC;IAC1B;;;;OAIG;IACH,WAAW,EAAE,MAAM,CAAC;IACpB,KAAK,EAAE,gBAAgB,CAAC;IACxB,UAAU,EAAE,MAAM,CAAC;IACnB,MAAM,CAAC,EAAE,WAAW,CAAC;CACtB,GAAG,OAAO,CAAC,IAAI,CAAC,CA0NhB;AAED;;;;;GAKG;AACH,wBAAsB,UAAU,CAAC,IAAI,EAAE;IACrC,UAAU,EAAE,MAAM,EAAE,CAAC;IACrB,OAAO,EAAE,MAAM,CAAC;IAChB,MAAM,CAAC,EAAE,WAAW,CAAC;CACtB,GAAG,OAAO,CAAC,IAAI,CAAC,CA2DhB"}
|
|
@@ -0,0 +1,319 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Normalize clips to one frame size, rate and audio format and write them end
|
|
3
|
+
* to end into one file: the in-process form of encoding a segment per clip
|
|
4
|
+
* with `-vf <filter>` and joining them with the concat demuxer and `-c copy`.
|
|
5
|
+
* Doing it in one pass leaves no segment files and no remux.
|
|
6
|
+
*/
|
|
7
|
+
import { AV_NOPTS_VALUE, AV_PIX_FMT_RGBA, AV_SAMPLE_FMT_FLT, avChannelLayoutDefault, Demuxer, Encoder, FilterAPI, Frame, Rational } from "node-av";
|
|
8
|
+
import { AudioEncoder } from "./audio-encoder.js";
|
|
9
|
+
import { abortError, findEncoder, openFileMuxer, quietLibav, rationalFor, startTimeSeconds, throwIfAborted } from "./av.js";
|
|
10
|
+
import { openFilterGraph } from "./filter-graph.js";
|
|
11
|
+
const AUDIO_RATE = 48000;
|
|
12
|
+
const AUDIO_CHANNELS = 2;
|
|
13
|
+
export async function concatSegments(opts) {
|
|
14
|
+
const { signal, fps } = opts;
|
|
15
|
+
throwIfAborted(signal);
|
|
16
|
+
quietLibav();
|
|
17
|
+
const codec = findEncoder(opts.video.codec);
|
|
18
|
+
if (!codec)
|
|
19
|
+
throw new Error(`This libav build has no ${opts.video.codec} encoder`);
|
|
20
|
+
const rate = rationalFor(fps);
|
|
21
|
+
const frameTimeBase = new Rational(rate.den, rate.num);
|
|
22
|
+
const output = await openFileMuxer(opts.outPath, { signal });
|
|
23
|
+
let videoEncoder = null;
|
|
24
|
+
let audioEncoder = null;
|
|
25
|
+
try {
|
|
26
|
+
videoEncoder = await Encoder.create(codec, {
|
|
27
|
+
options: opts.video.options,
|
|
28
|
+
context: { framerate: new Rational(rate.num, rate.den) },
|
|
29
|
+
signal
|
|
30
|
+
});
|
|
31
|
+
const videoIndex = output.muxer.addStream(videoEncoder);
|
|
32
|
+
audioEncoder = await AudioEncoder.create(opts.audioCodec, {
|
|
33
|
+
sampleRate: AUDIO_RATE,
|
|
34
|
+
channels: AUDIO_CHANNELS,
|
|
35
|
+
signal
|
|
36
|
+
});
|
|
37
|
+
const audioIndex = output.muxer.addStream(audioEncoder.encoder);
|
|
38
|
+
const activeVideo = videoEncoder;
|
|
39
|
+
const activeAudio = audioEncoder;
|
|
40
|
+
const writeVideoPackets = async (packets) => {
|
|
41
|
+
for (const packet of packets) {
|
|
42
|
+
await output.muxer.writePacket(packet, videoIndex);
|
|
43
|
+
packet.free();
|
|
44
|
+
}
|
|
45
|
+
};
|
|
46
|
+
const writeAudioPackets = async (packets) => {
|
|
47
|
+
for (const packet of packets) {
|
|
48
|
+
await output.muxer.writePacket(packet, audioIndex);
|
|
49
|
+
packet.free();
|
|
50
|
+
}
|
|
51
|
+
};
|
|
52
|
+
let frameIndex = 0;
|
|
53
|
+
let sampleIndex = 0;
|
|
54
|
+
const pixelFilter = `format=${opts.video.pixelFormat}`;
|
|
55
|
+
/** Encode `frame` as the next output frame. */
|
|
56
|
+
const putFrame = async (frame) => {
|
|
57
|
+
frame.pts = BigInt(frameIndex);
|
|
58
|
+
frame.timeBase = frameTimeBase;
|
|
59
|
+
frameIndex += 1;
|
|
60
|
+
await writeVideoPackets(await activeVideo.encodeAll(frame));
|
|
61
|
+
};
|
|
62
|
+
/** Encode silence until the audio reaches the video. */
|
|
63
|
+
const padAudio = async () => {
|
|
64
|
+
const target = Math.round((frameIndex * AUDIO_RATE * rate.den) / rate.num);
|
|
65
|
+
while (sampleIndex < target) {
|
|
66
|
+
const count = Math.min(4096, target - sampleIndex);
|
|
67
|
+
const silence = Frame.fromAudioBuffer(Buffer.alloc(count * AUDIO_CHANNELS * 4), {
|
|
68
|
+
nbSamples: count,
|
|
69
|
+
format: AV_SAMPLE_FMT_FLT,
|
|
70
|
+
sampleRate: AUDIO_RATE,
|
|
71
|
+
channelLayout: avChannelLayoutDefault(AUDIO_CHANNELS),
|
|
72
|
+
timeBase: { num: 1, den: AUDIO_RATE },
|
|
73
|
+
pts: BigInt(sampleIndex)
|
|
74
|
+
});
|
|
75
|
+
try {
|
|
76
|
+
sampleIndex += count;
|
|
77
|
+
await writeAudioPackets(await activeAudio.encode(silence));
|
|
78
|
+
}
|
|
79
|
+
finally {
|
|
80
|
+
silence.free();
|
|
81
|
+
}
|
|
82
|
+
}
|
|
83
|
+
};
|
|
84
|
+
/** A blank frame at the output size, through the same pixel conversion. */
|
|
85
|
+
const blankFrame = () => Frame.fromVideoBuffer(Buffer.alloc(opts.width * opts.height * 4), {
|
|
86
|
+
width: opts.width,
|
|
87
|
+
height: opts.height,
|
|
88
|
+
format: AV_PIX_FMT_RGBA,
|
|
89
|
+
timeBase: frameTimeBase
|
|
90
|
+
});
|
|
91
|
+
for (const segment of opts.segments) {
|
|
92
|
+
if (signal?.aborted)
|
|
93
|
+
throw abortError(signal);
|
|
94
|
+
const frameCount = Math.ceil(segment.durationSec * fps - 1e-9);
|
|
95
|
+
const segmentStart = frameIndex;
|
|
96
|
+
if (segment.kind === "video") {
|
|
97
|
+
const inSec = segment.inSec && segment.inSec > 0 ? segment.inSec : 0;
|
|
98
|
+
const trims = [
|
|
99
|
+
inSec > 0 ? "trim=start=0" : null,
|
|
100
|
+
segment.outSec !== undefined && segment.outSec > inSec
|
|
101
|
+
? `trim=end=${segment.outSec - inSec}`
|
|
102
|
+
: null
|
|
103
|
+
].filter((step) => step !== null);
|
|
104
|
+
const run = await openFilterGraph({
|
|
105
|
+
filePath: segment.filePath,
|
|
106
|
+
kind: "video",
|
|
107
|
+
filter: [...trims, opts.videoFilter, `fps=${fps}`, pixelFilter].join(","),
|
|
108
|
+
seekSec: inSec,
|
|
109
|
+
signal
|
|
110
|
+
});
|
|
111
|
+
if (!run)
|
|
112
|
+
throw new Error(`${segment.filePath} has no video stream`);
|
|
113
|
+
try {
|
|
114
|
+
for await (const frame of run.frames()) {
|
|
115
|
+
try {
|
|
116
|
+
if (frameIndex - segmentStart >= frameCount)
|
|
117
|
+
break;
|
|
118
|
+
await putFrame(frame);
|
|
119
|
+
}
|
|
120
|
+
finally {
|
|
121
|
+
frame.free();
|
|
122
|
+
}
|
|
123
|
+
}
|
|
124
|
+
}
|
|
125
|
+
finally {
|
|
126
|
+
await run.close();
|
|
127
|
+
}
|
|
128
|
+
// The segment's sound: the clip's own, trimmed alike and no longer
|
|
129
|
+
// than the picture it got, else silence.
|
|
130
|
+
const pictureSec = (frameIndex - segmentStart) / fps;
|
|
131
|
+
const audio = segment.withAudio && pictureSec > 0
|
|
132
|
+
? await openFilterGraph({
|
|
133
|
+
filePath: segment.filePath,
|
|
134
|
+
kind: "audio",
|
|
135
|
+
filter: [
|
|
136
|
+
inSec > 0 ? "atrim=start=0" : null,
|
|
137
|
+
segment.outSec !== undefined && segment.outSec > inSec
|
|
138
|
+
? `atrim=end=${segment.outSec - inSec}`
|
|
139
|
+
: null,
|
|
140
|
+
`atrim=end=${pictureSec}`,
|
|
141
|
+
`aresample=${AUDIO_RATE}`,
|
|
142
|
+
`aformat=sample_fmts=flt:channel_layouts=stereo`
|
|
143
|
+
]
|
|
144
|
+
.filter((step) => step !== null)
|
|
145
|
+
.join(","),
|
|
146
|
+
seekSec: inSec,
|
|
147
|
+
signal
|
|
148
|
+
})
|
|
149
|
+
: null;
|
|
150
|
+
if (audio) {
|
|
151
|
+
try {
|
|
152
|
+
for await (const frame of audio.frames()) {
|
|
153
|
+
try {
|
|
154
|
+
frame.pts = BigInt(sampleIndex);
|
|
155
|
+
frame.timeBase = new Rational(1, AUDIO_RATE);
|
|
156
|
+
sampleIndex += frame.nbSamples;
|
|
157
|
+
await writeAudioPackets(await activeAudio.encode(frame));
|
|
158
|
+
}
|
|
159
|
+
finally {
|
|
160
|
+
frame.free();
|
|
161
|
+
}
|
|
162
|
+
}
|
|
163
|
+
}
|
|
164
|
+
finally {
|
|
165
|
+
await audio.close();
|
|
166
|
+
}
|
|
167
|
+
}
|
|
168
|
+
await padAudio();
|
|
169
|
+
}
|
|
170
|
+
else if (segment.kind === "image") {
|
|
171
|
+
const still = await openFilterGraph({
|
|
172
|
+
filePath: segment.filePath,
|
|
173
|
+
kind: "video",
|
|
174
|
+
filter: [opts.videoFilter, pixelFilter].join(","),
|
|
175
|
+
signal
|
|
176
|
+
});
|
|
177
|
+
if (!still)
|
|
178
|
+
throw new Error(`${segment.filePath} has no picture`);
|
|
179
|
+
let picture = null;
|
|
180
|
+
try {
|
|
181
|
+
for await (const frame of still.frames()) {
|
|
182
|
+
picture = frame;
|
|
183
|
+
break;
|
|
184
|
+
}
|
|
185
|
+
}
|
|
186
|
+
finally {
|
|
187
|
+
await still.close();
|
|
188
|
+
}
|
|
189
|
+
if (!picture)
|
|
190
|
+
throw new Error(`${segment.filePath} decoded to no picture`);
|
|
191
|
+
try {
|
|
192
|
+
for (let i = 0; i < frameCount; i++) {
|
|
193
|
+
const copy = picture.clone();
|
|
194
|
+
if (!copy)
|
|
195
|
+
throw new Error("Out of memory copying a still");
|
|
196
|
+
try {
|
|
197
|
+
await putFrame(copy);
|
|
198
|
+
}
|
|
199
|
+
finally {
|
|
200
|
+
copy.free();
|
|
201
|
+
}
|
|
202
|
+
}
|
|
203
|
+
}
|
|
204
|
+
finally {
|
|
205
|
+
picture.free();
|
|
206
|
+
}
|
|
207
|
+
await padAudio();
|
|
208
|
+
}
|
|
209
|
+
else {
|
|
210
|
+
const convert = FilterAPI.create(pixelFilter, { signal });
|
|
211
|
+
try {
|
|
212
|
+
for (let i = 0; i < frameCount; i++) {
|
|
213
|
+
const blank = blankFrame();
|
|
214
|
+
try {
|
|
215
|
+
for (const converted of await convert.processAll(blank)) {
|
|
216
|
+
try {
|
|
217
|
+
await putFrame(converted);
|
|
218
|
+
}
|
|
219
|
+
finally {
|
|
220
|
+
converted.free();
|
|
221
|
+
}
|
|
222
|
+
}
|
|
223
|
+
}
|
|
224
|
+
finally {
|
|
225
|
+
blank.free();
|
|
226
|
+
}
|
|
227
|
+
}
|
|
228
|
+
}
|
|
229
|
+
finally {
|
|
230
|
+
convert.close();
|
|
231
|
+
}
|
|
232
|
+
await padAudio();
|
|
233
|
+
}
|
|
234
|
+
}
|
|
235
|
+
if (frameIndex === 0)
|
|
236
|
+
throw new Error("No segment produced a frame");
|
|
237
|
+
await writeVideoPackets(await activeVideo.encodeAll(null));
|
|
238
|
+
await writeAudioPackets(await activeAudio.flush());
|
|
239
|
+
await output.close();
|
|
240
|
+
}
|
|
241
|
+
finally {
|
|
242
|
+
videoEncoder?.close();
|
|
243
|
+
audioEncoder?.close();
|
|
244
|
+
await output.close();
|
|
245
|
+
}
|
|
246
|
+
}
|
|
247
|
+
/**
|
|
248
|
+
* Join files whose streams share codec, size and rate without re-encoding:
|
|
249
|
+
* the in-process form of the concat demuxer with `-c copy`. Each file's
|
|
250
|
+
* packets follow the previous file's, offset by where that file ended. The
|
|
251
|
+
* output takes its stream parameters from the first file.
|
|
252
|
+
*/
|
|
253
|
+
export async function concatCopy(opts) {
|
|
254
|
+
const { signal } = opts;
|
|
255
|
+
throwIfAborted(signal);
|
|
256
|
+
quietLibav();
|
|
257
|
+
if (opts.inputPaths.length === 0)
|
|
258
|
+
throw new Error("Nothing to join");
|
|
259
|
+
const output = await openFileMuxer(opts.outPath, { signal });
|
|
260
|
+
try {
|
|
261
|
+
let outVideo = -1;
|
|
262
|
+
let outAudio = -1;
|
|
263
|
+
let offsetSec = 0;
|
|
264
|
+
for (const [fileIndex, inputPath] of opts.inputPaths.entries()) {
|
|
265
|
+
const demuxer = await Demuxer.open(inputPath, { signal });
|
|
266
|
+
try {
|
|
267
|
+
const video = demuxer.video();
|
|
268
|
+
const audio = demuxer.audio();
|
|
269
|
+
if (fileIndex === 0) {
|
|
270
|
+
if (video)
|
|
271
|
+
outVideo = output.muxer.addStream(video);
|
|
272
|
+
if (audio)
|
|
273
|
+
outAudio = output.muxer.addStream(audio);
|
|
274
|
+
}
|
|
275
|
+
const formatStart = startTimeSeconds(demuxer.getFormatContext().startTime, {
|
|
276
|
+
num: 1,
|
|
277
|
+
den: 1_000_000
|
|
278
|
+
});
|
|
279
|
+
let fileEnd = 0;
|
|
280
|
+
for await (const packet of demuxer.packets()) {
|
|
281
|
+
if (!packet)
|
|
282
|
+
continue;
|
|
283
|
+
try {
|
|
284
|
+
if (signal?.aborted)
|
|
285
|
+
throw abortError(signal);
|
|
286
|
+
const target = video && packet.streamIndex === video.index
|
|
287
|
+
? outVideo
|
|
288
|
+
: audio && packet.streamIndex === audio.index
|
|
289
|
+
? outAudio
|
|
290
|
+
: -1;
|
|
291
|
+
if (target < 0)
|
|
292
|
+
continue;
|
|
293
|
+
const timeBase = packet.timeBase;
|
|
294
|
+
const shift = BigInt(Math.round(((offsetSec - formatStart) * timeBase.den) / timeBase.num));
|
|
295
|
+
if (packet.pts !== AV_NOPTS_VALUE) {
|
|
296
|
+
fileEnd = Math.max(fileEnd, (Number(packet.pts + packet.duration) * timeBase.num) / timeBase.den - formatStart);
|
|
297
|
+
packet.pts += shift;
|
|
298
|
+
}
|
|
299
|
+
if (packet.dts !== AV_NOPTS_VALUE)
|
|
300
|
+
packet.dts += shift;
|
|
301
|
+
await output.muxer.writePacket(packet, target);
|
|
302
|
+
}
|
|
303
|
+
finally {
|
|
304
|
+
packet.free();
|
|
305
|
+
}
|
|
306
|
+
}
|
|
307
|
+
offsetSec += fileEnd;
|
|
308
|
+
}
|
|
309
|
+
finally {
|
|
310
|
+
await demuxer.close();
|
|
311
|
+
}
|
|
312
|
+
}
|
|
313
|
+
await output.close();
|
|
314
|
+
}
|
|
315
|
+
finally {
|
|
316
|
+
await output.close();
|
|
317
|
+
}
|
|
318
|
+
}
|
|
319
|
+
//# sourceMappingURL=concat.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"concat.js","sourceRoot":"","sources":["../../src/media/concat.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Whole-file conversions on Mediabunny: trim with re-encode, and audio to WAV.
|
|
3
|
+
* Mediabunny encodes through `@mediabunny/server`, which runs node-av's codecs.
|
|
4
|
+
*/
|
|
5
|
+
import type { MediaSource } from "./probe.js";
|
|
6
|
+
/**
|
|
7
|
+
* Register Mediabunny's Node codecs once per process. Hardware acceleration
|
|
8
|
+
* stays off: a server render must not depend on which GPU the host has, and
|
|
9
|
+
* probing every hardware API on each codec open costs time and log noise.
|
|
10
|
+
*/
|
|
11
|
+
export declare function ensureMediabunnyServer(): void;
|
|
12
|
+
/**
|
|
13
|
+
* Re-encode `[startSec, endSec)` of `source` as an MP4 that starts at zero,
|
|
14
|
+
* H.264 and AAC with the index at the front: the in-process form of
|
|
15
|
+
* `ffmpeg -i in -ss S -t D -c:v libx264 -c:a aac -movflags +faststart`.
|
|
16
|
+
*/
|
|
17
|
+
export declare function trimVideo(source: MediaSource, startSec: number, endSec: number, options?: {
|
|
18
|
+
signal?: AbortSignal;
|
|
19
|
+
}): Promise<Uint8Array>;
|
|
20
|
+
/**
|
|
21
|
+
* Write `source`'s first audio track to `outPath` as 16-bit PCM WAV, at its own
|
|
22
|
+
* rate and channel count unless `sampleRate` or `channels` say otherwise, as
|
|
23
|
+
* `ffmpeg -i in -vn [-ar R] [-ac C] -acodec pcm_s16le out.wav` did. Throws when
|
|
24
|
+
* the source has no audio track.
|
|
25
|
+
*/
|
|
26
|
+
export declare function convertAudioToWav(source: MediaSource, outPath: string, options?: {
|
|
27
|
+
sampleRate?: number;
|
|
28
|
+
channels?: number;
|
|
29
|
+
signal?: AbortSignal;
|
|
30
|
+
}): Promise<void>;
|
|
31
|
+
//# sourceMappingURL=convert.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"convert.d.ts","sourceRoot":"","sources":["../../src/media/convert.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAiBH,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,YAAY,CAAC;AAI9C;;;;GAIG;AACH,wBAAgB,sBAAsB,IAAI,IAAI,CAI7C;AA6BD;;;;GAIG;AACH,wBAAsB,SAAS,CAC7B,MAAM,EAAE,WAAW,EACnB,QAAQ,EAAE,MAAM,EAChB,MAAM,EAAE,MAAM,EACd,OAAO,GAAE;IAAE,MAAM,CAAC,EAAE,WAAW,CAAA;CAAO,GACrC,OAAO,CAAC,UAAU,CAAC,CAwBrB;AAED;;;;;GAKG;AACH,wBAAsB,iBAAiB,CACrC,MAAM,EAAE,WAAW,EACnB,OAAO,EAAE,MAAM,EACf,OAAO,GAAE;IAAE,UAAU,CAAC,EAAE,MAAM,CAAC;IAAC,QAAQ,CAAC,EAAE,MAAM,CAAC;IAAC,MAAM,CAAC,EAAE,WAAW,CAAA;CAAO,GAC7E,OAAO,CAAC,IAAI,CAAC,CA2Bf"}
|