@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
|
@@ -0,0 +1,112 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Video frames as PNG files, the in-process form of `ffmpeg -i in -vf <filter>
|
|
3
|
+
* frame_%d.png`, `-ss T -i in -frames:v 1 frame.png` and `-sseof`.
|
|
4
|
+
*/
|
|
5
|
+
import { Encoder } from "node-av";
|
|
6
|
+
import { abortError, findEncoder, quietLibav } from "./av.js";
|
|
7
|
+
import { openFilterGraph } from "./filter-graph.js";
|
|
8
|
+
/**
|
|
9
|
+
* One frame as a PNG file. One encoder per frame: a PNG is a whole file, and
|
|
10
|
+
* the encoder's options (size, format) are fixed when it opens.
|
|
11
|
+
*/
|
|
12
|
+
async function encodePng(frame, signal) {
|
|
13
|
+
const codec = findEncoder("png");
|
|
14
|
+
if (!codec)
|
|
15
|
+
throw new Error("This libav build has no PNG encoder");
|
|
16
|
+
const encoder = await Encoder.create(codec, { signal });
|
|
17
|
+
try {
|
|
18
|
+
const packets = [...(await encoder.encodeAll(frame)), ...(await encoder.encodeAll(null))];
|
|
19
|
+
const parts = [];
|
|
20
|
+
for (const packet of packets) {
|
|
21
|
+
if (packet.data)
|
|
22
|
+
parts.push(new Uint8Array(packet.data));
|
|
23
|
+
packet.free();
|
|
24
|
+
}
|
|
25
|
+
if (parts.length !== 1)
|
|
26
|
+
throw new Error("The PNG encoder wrote no picture");
|
|
27
|
+
return parts[0];
|
|
28
|
+
}
|
|
29
|
+
finally {
|
|
30
|
+
encoder.close();
|
|
31
|
+
}
|
|
32
|
+
}
|
|
33
|
+
/**
|
|
34
|
+
* PNG bytes of every frame `filter` passes, in order. Frames are RGB, or RGBA
|
|
35
|
+
* with `alpha`, as the CLI's PNG encoder chose from the source. `seekSec`
|
|
36
|
+
* starts at the frame shown at that time; `limit` stops after that many.
|
|
37
|
+
* Yields nothing when the file has no video stream.
|
|
38
|
+
*/
|
|
39
|
+
export async function* pngFrames(opts) {
|
|
40
|
+
const { signal } = opts;
|
|
41
|
+
quietLibav();
|
|
42
|
+
const seekSec = opts.seekSec && opts.seekSec > 0 ? opts.seekSec : 0;
|
|
43
|
+
const run = await openFilterGraph({
|
|
44
|
+
filePath: opts.filePath,
|
|
45
|
+
kind: "video",
|
|
46
|
+
filter: [
|
|
47
|
+
seekSec > 0 ? "trim=start=0" : null,
|
|
48
|
+
opts.filter,
|
|
49
|
+
`format=${opts.alpha ? "rgba" : "rgb24"}`
|
|
50
|
+
]
|
|
51
|
+
.filter((step) => step)
|
|
52
|
+
.join(","),
|
|
53
|
+
seekSec,
|
|
54
|
+
signal
|
|
55
|
+
});
|
|
56
|
+
if (!run)
|
|
57
|
+
return;
|
|
58
|
+
const limit = opts.limit ?? Number.POSITIVE_INFINITY;
|
|
59
|
+
let count = 0;
|
|
60
|
+
try {
|
|
61
|
+
for await (const frame of run.frames()) {
|
|
62
|
+
try {
|
|
63
|
+
if (signal?.aborted)
|
|
64
|
+
throw abortError(signal);
|
|
65
|
+
if (count >= limit)
|
|
66
|
+
break;
|
|
67
|
+
yield await encodePng(frame, signal);
|
|
68
|
+
count += 1;
|
|
69
|
+
}
|
|
70
|
+
finally {
|
|
71
|
+
frame.free();
|
|
72
|
+
}
|
|
73
|
+
}
|
|
74
|
+
}
|
|
75
|
+
finally {
|
|
76
|
+
await run.close();
|
|
77
|
+
}
|
|
78
|
+
}
|
|
79
|
+
/**
|
|
80
|
+
* The last frame of `filePath` as PNG, or null when it has no picture: the
|
|
81
|
+
* in-process form of `ffmpeg -sseof -1 -i in -update 1 -frames:v 1 out.png`.
|
|
82
|
+
* Decodes only the last `tailSec` seconds.
|
|
83
|
+
*/
|
|
84
|
+
export async function lastFramePng(opts) {
|
|
85
|
+
const { signal } = opts;
|
|
86
|
+
quietLibav();
|
|
87
|
+
const seekSec = Math.max(0, (opts.durationSec ?? 0) - (opts.tailSec ?? 1));
|
|
88
|
+
const run = await openFilterGraph({
|
|
89
|
+
filePath: opts.filePath,
|
|
90
|
+
kind: "video",
|
|
91
|
+
filter: [seekSec > 0 ? "trim=start=0" : null, `format=${opts.alpha ? "rgba" : "rgb24"}`]
|
|
92
|
+
.filter((step) => step)
|
|
93
|
+
.join(","),
|
|
94
|
+
seekSec,
|
|
95
|
+
signal
|
|
96
|
+
});
|
|
97
|
+
if (!run)
|
|
98
|
+
return null;
|
|
99
|
+
let last = null;
|
|
100
|
+
try {
|
|
101
|
+
for await (const frame of run.frames()) {
|
|
102
|
+
last?.free();
|
|
103
|
+
last = frame;
|
|
104
|
+
}
|
|
105
|
+
return last ? await encodePng(last, signal) : null;
|
|
106
|
+
}
|
|
107
|
+
finally {
|
|
108
|
+
last?.free();
|
|
109
|
+
await run.close();
|
|
110
|
+
}
|
|
111
|
+
}
|
|
112
|
+
//# sourceMappingURL=frames.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"frames.js","sourceRoot":"","sources":["../../src/media/frames.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* In-process media: probes, decode, filter graphs and encode without the
|
|
3
|
+
* `ffmpeg` and `ffprobe` binaries.
|
|
4
|
+
*
|
|
5
|
+
* Mediabunny handles probes, timestamp decode, trims and whole-file
|
|
6
|
+
* conversions. node-av, the same libav Mediabunny's server adapter runs on,
|
|
7
|
+
* handles filter graphs, the audio mix, and raw RGBA decode and encode, so the
|
|
8
|
+
* CLI's filter strings and swscale flags carry over unchanged.
|
|
9
|
+
*
|
|
10
|
+
* Node only: every function here loads a native addon.
|
|
11
|
+
*/
|
|
12
|
+
export { hasEncoder, hasFilter } from "./codecs.js";
|
|
13
|
+
export { packetTimes, probeDurationSec, probeHasAudio, probeMedia, probeVideoStream, type AudioStreamInfo, type MediaProbe, type MediaSource, type ProbeOptions, type VideoStreamInfo } from "./probe.js";
|
|
14
|
+
export { decodeAudioChunks, decodeAudioToPcm, type PcmAudio, type PcmOptions } from "./audio.js";
|
|
15
|
+
export { openFilterComplex, openFilterGraph, type FilterComplexInput, type FilterRun } from "./filter-graph.js";
|
|
16
|
+
export { openDecodedStream, type DecodedStream, type MediaKind } from "./decode.js";
|
|
17
|
+
export { openRgbaFrameReader, openVideoFrameEncoder, type RgbaFrame, type RgbaFrameReader, type VideoEncoderSpec, type VideoFrameEncoder } from "./rgba.js";
|
|
18
|
+
export { copyContainerFor, muxAudioWithVideoCopy, muxStreamCopy, streamCodecs, type CopyContainer } from "./mux.js";
|
|
19
|
+
export { convertAudioToWav, ensureMediabunnyServer, trimVideo } from "./convert.js";
|
|
20
|
+
export { transcodeVideo } from "./transcode.js";
|
|
21
|
+
export { AudioEncoder } from "./audio-encoder.js";
|
|
22
|
+
export { concatCopy, concatSegments, type ConcatSegment } from "./concat.js";
|
|
23
|
+
export { lastFramePng, pngFrames } from "./frames.js";
|
|
24
|
+
export { verifyDecodes } from "./verify.js";
|
|
25
|
+
export { DEFAULT_VIDEO_ENCODER, transformMedia, type StreamPlan, type TransformInput } from "./transform.js";
|
|
26
|
+
//# sourceMappingURL=index.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/media/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;GAUG;AAEH,OAAO,EAAE,UAAU,EAAE,SAAS,EAAE,MAAM,aAAa,CAAC;AACpD,OAAO,EACL,WAAW,EACX,gBAAgB,EAChB,aAAa,EACb,UAAU,EACV,gBAAgB,EAChB,KAAK,eAAe,EACpB,KAAK,UAAU,EACf,KAAK,WAAW,EAChB,KAAK,YAAY,EACjB,KAAK,eAAe,EACrB,MAAM,YAAY,CAAC;AACpB,OAAO,EACL,iBAAiB,EACjB,gBAAgB,EAChB,KAAK,QAAQ,EACb,KAAK,UAAU,EAChB,MAAM,YAAY,CAAC;AACpB,OAAO,EACL,iBAAiB,EACjB,eAAe,EACf,KAAK,kBAAkB,EACvB,KAAK,SAAS,EACf,MAAM,mBAAmB,CAAC;AAC3B,OAAO,EAAE,iBAAiB,EAAE,KAAK,aAAa,EAAE,KAAK,SAAS,EAAE,MAAM,aAAa,CAAC;AACpF,OAAO,EACL,mBAAmB,EACnB,qBAAqB,EACrB,KAAK,SAAS,EACd,KAAK,eAAe,EACpB,KAAK,gBAAgB,EACrB,KAAK,iBAAiB,EACvB,MAAM,WAAW,CAAC;AACnB,OAAO,EACL,gBAAgB,EAChB,qBAAqB,EACrB,aAAa,EACb,YAAY,EACZ,KAAK,aAAa,EACnB,MAAM,UAAU,CAAC;AAClB,OAAO,EAAE,iBAAiB,EAAE,sBAAsB,EAAE,SAAS,EAAE,MAAM,cAAc,CAAC;AACpF,OAAO,EAAE,cAAc,EAAE,MAAM,gBAAgB,CAAC;AAChD,OAAO,EAAE,YAAY,EAAE,MAAM,oBAAoB,CAAC;AAClD,OAAO,EAAE,UAAU,EAAE,cAAc,EAAE,KAAK,aAAa,EAAE,MAAM,aAAa,CAAC;AAC7E,OAAO,EAAE,YAAY,EAAE,SAAS,EAAE,MAAM,aAAa,CAAC;AACtD,OAAO,EAAE,aAAa,EAAE,MAAM,aAAa,CAAC;AAC5C,OAAO,EACL,qBAAqB,EACrB,cAAc,EACd,KAAK,UAAU,EACf,KAAK,cAAc,EACpB,MAAM,gBAAgB,CAAC"}
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* In-process media: probes, decode, filter graphs and encode without the
|
|
3
|
+
* `ffmpeg` and `ffprobe` binaries.
|
|
4
|
+
*
|
|
5
|
+
* Mediabunny handles probes, timestamp decode, trims and whole-file
|
|
6
|
+
* conversions. node-av, the same libav Mediabunny's server adapter runs on,
|
|
7
|
+
* handles filter graphs, the audio mix, and raw RGBA decode and encode, so the
|
|
8
|
+
* CLI's filter strings and swscale flags carry over unchanged.
|
|
9
|
+
*
|
|
10
|
+
* Node only: every function here loads a native addon.
|
|
11
|
+
*/
|
|
12
|
+
export { hasEncoder, hasFilter } from "./codecs.js";
|
|
13
|
+
export { packetTimes, probeDurationSec, probeHasAudio, probeMedia, probeVideoStream } from "./probe.js";
|
|
14
|
+
export { decodeAudioChunks, decodeAudioToPcm } from "./audio.js";
|
|
15
|
+
export { openFilterComplex, openFilterGraph } from "./filter-graph.js";
|
|
16
|
+
export { openDecodedStream } from "./decode.js";
|
|
17
|
+
export { openRgbaFrameReader, openVideoFrameEncoder } from "./rgba.js";
|
|
18
|
+
export { copyContainerFor, muxAudioWithVideoCopy, muxStreamCopy, streamCodecs } from "./mux.js";
|
|
19
|
+
export { convertAudioToWav, ensureMediabunnyServer, trimVideo } from "./convert.js";
|
|
20
|
+
export { transcodeVideo } from "./transcode.js";
|
|
21
|
+
export { AudioEncoder } from "./audio-encoder.js";
|
|
22
|
+
export { concatCopy, concatSegments } from "./concat.js";
|
|
23
|
+
export { lastFramePng, pngFrames } from "./frames.js";
|
|
24
|
+
export { verifyDecodes } from "./verify.js";
|
|
25
|
+
export { DEFAULT_VIDEO_ENCODER, transformMedia } from "./transform.js";
|
|
26
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/media/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;GAUG;AAEH,OAAO,EAAE,UAAU,EAAE,SAAS,EAAE,MAAM,aAAa,CAAC;AACpD,OAAO,EACL,WAAW,EACX,gBAAgB,EAChB,aAAa,EACb,UAAU,EACV,gBAAgB,EAMjB,MAAM,YAAY,CAAC;AACpB,OAAO,EACL,iBAAiB,EACjB,gBAAgB,EAGjB,MAAM,YAAY,CAAC;AACpB,OAAO,EACL,iBAAiB,EACjB,eAAe,EAGhB,MAAM,mBAAmB,CAAC;AAC3B,OAAO,EAAE,iBAAiB,EAAsC,MAAM,aAAa,CAAC;AACpF,OAAO,EACL,mBAAmB,EACnB,qBAAqB,EAKtB,MAAM,WAAW,CAAC;AACnB,OAAO,EACL,gBAAgB,EAChB,qBAAqB,EACrB,aAAa,EACb,YAAY,EAEb,MAAM,UAAU,CAAC;AAClB,OAAO,EAAE,iBAAiB,EAAE,sBAAsB,EAAE,SAAS,EAAE,MAAM,cAAc,CAAC;AACpF,OAAO,EAAE,cAAc,EAAE,MAAM,gBAAgB,CAAC;AAChD,OAAO,EAAE,YAAY,EAAE,MAAM,oBAAoB,CAAC;AAClD,OAAO,EAAE,UAAU,EAAE,cAAc,EAAsB,MAAM,aAAa,CAAC;AAC7E,OAAO,EAAE,YAAY,EAAE,SAAS,EAAE,MAAM,aAAa,CAAC;AACtD,OAAO,EAAE,aAAa,EAAE,MAAM,aAAa,CAAC;AAC5C,OAAO,EACL,qBAAqB,EACrB,cAAc,EAGf,MAAM,gBAAgB,CAAC"}
|
|
@@ -0,0 +1,58 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Encode filtered audio onto an existing video without re-encoding the
|
|
3
|
+
* picture: the in-process form of `ffmpeg -i base ... -map 0:v -map [aout]
|
|
4
|
+
* -c:v copy -c:a <codec> -shortest out`.
|
|
5
|
+
*/
|
|
6
|
+
import { type Frame } from "node-av";
|
|
7
|
+
/**
|
|
8
|
+
* Copy `videoPath`'s video stream into `outPath` and encode `audio` beside it
|
|
9
|
+
* as `codec` at `sampleRate`, stereo. The audio is cut at the end of the
|
|
10
|
+
* picture, as `-shortest` cut it, so a padded mix never outlasts the video.
|
|
11
|
+
* `audio`'s frames are consumed and freed.
|
|
12
|
+
*/
|
|
13
|
+
export declare function muxAudioWithVideoCopy(opts: {
|
|
14
|
+
videoPath: string;
|
|
15
|
+
audio: AsyncIterable<Frame>;
|
|
16
|
+
outPath: string;
|
|
17
|
+
codec: string;
|
|
18
|
+
sampleRate: number;
|
|
19
|
+
signal?: AbortSignal;
|
|
20
|
+
}): Promise<void>;
|
|
21
|
+
/** The video and audio codec of a file, in libav's names; `null` for none. */
|
|
22
|
+
export declare function streamCodecs(filePath: string, signal?: AbortSignal): Promise<{
|
|
23
|
+
video: string | null;
|
|
24
|
+
audio: string | null;
|
|
25
|
+
}>;
|
|
26
|
+
/** A container `muxStreamCopy` writes. */
|
|
27
|
+
export type CopyContainer = "mp4" | "mov" | "webm" | "mkv";
|
|
28
|
+
/**
|
|
29
|
+
* The container a stream copy of `video` and `audio` goes into, as yt-dlp
|
|
30
|
+
* picked one when it merged: WebM when both are WebM codecs, else MP4 when
|
|
31
|
+
* MP4 holds both, else Matroska, which holds anything.
|
|
32
|
+
*/
|
|
33
|
+
export declare function copyContainerFor(video: string | null, audio: string | null): CopyContainer;
|
|
34
|
+
/**
|
|
35
|
+
* Copy the video stream of `videoPath` and the audio stream of `audioPath`
|
|
36
|
+
* into one file, packets unchanged: the in-process form of
|
|
37
|
+
* `ffmpeg -i v -i a -map 0:v -map 1:a -c copy out`, which is what yt-dlp ran
|
|
38
|
+
* to merge formats.
|
|
39
|
+
*
|
|
40
|
+
* `container` is `auto` (see {@link copyContainerFor}) or a
|
|
41
|
+
* {@link CopyContainer}; the output is `<outStem>.<container>`. A container
|
|
42
|
+
* that cannot hold the codecs without re-encoding throws an error naming
|
|
43
|
+
* both codecs and the container, before any file is written. When the two
|
|
44
|
+
* paths are the same file, its audio stream is optional.
|
|
45
|
+
*/
|
|
46
|
+
export declare function muxStreamCopy(opts: {
|
|
47
|
+
videoPath: string;
|
|
48
|
+
audioPath: string;
|
|
49
|
+
outStem: string;
|
|
50
|
+
container: string;
|
|
51
|
+
signal?: AbortSignal;
|
|
52
|
+
}): Promise<{
|
|
53
|
+
outPath: string;
|
|
54
|
+
container: CopyContainer;
|
|
55
|
+
video: string;
|
|
56
|
+
audio: string | null;
|
|
57
|
+
}>;
|
|
58
|
+
//# sourceMappingURL=mux.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"mux.d.ts","sourceRoot":"","sources":["../../src/media/mux.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAEH,OAAO,EAA2B,KAAK,KAAK,EAAe,MAAM,SAAS,CAAC;AA2C3E;;;;;GAKG;AACH,wBAAsB,qBAAqB,CAAC,IAAI,EAAE;IAChD,SAAS,EAAE,MAAM,CAAC;IAClB,KAAK,EAAE,aAAa,CAAC,KAAK,CAAC,CAAC;IAC5B,OAAO,EAAE,MAAM,CAAC;IAChB,KAAK,EAAE,MAAM,CAAC;IACd,UAAU,EAAE,MAAM,CAAC;IACnB,MAAM,CAAC,EAAE,WAAW,CAAC;CACtB,GAAG,OAAO,CAAC,IAAI,CAAC,CAuFhB;AAED,8EAA8E;AAC9E,wBAAsB,YAAY,CAChC,QAAQ,EAAE,MAAM,EAChB,MAAM,CAAC,EAAE,WAAW,GACnB,OAAO,CAAC;IAAE,KAAK,EAAE,MAAM,GAAG,IAAI,CAAC;IAAC,KAAK,EAAE,MAAM,GAAG,IAAI,CAAA;CAAE,CAAC,CAUzD;AAED,0CAA0C;AAC1C,MAAM,MAAM,aAAa,GAAG,KAAK,GAAG,KAAK,GAAG,MAAM,GAAG,KAAK,CAAC;AA8B3D;;;;GAIG;AACH,wBAAgB,gBAAgB,CAAC,KAAK,EAAE,MAAM,GAAG,IAAI,EAAE,KAAK,EAAE,MAAM,GAAG,IAAI,GAAG,aAAa,CAI1F;AAED;;;;;;;;;;;GAWG;AACH,wBAAsB,aAAa,CAAC,IAAI,EAAE;IACxC,SAAS,EAAE,MAAM,CAAC;IAClB,SAAS,EAAE,MAAM,CAAC;IAClB,OAAO,EAAE,MAAM,CAAC;IAChB,SAAS,EAAE,MAAM,CAAC;IAClB,MAAM,CAAC,EAAE,WAAW,CAAC;CACtB,GAAG,OAAO,CAAC;IAAE,OAAO,EAAE,MAAM,CAAC;IAAC,SAAS,EAAE,aAAa,CAAC;IAAC,KAAK,EAAE,MAAM,CAAC;IAAC,KAAK,EAAE,MAAM,GAAG,IAAI,CAAA;CAAE,CAAC,CAuC9F"}
|
|
@@ -0,0 +1,234 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Encode filtered audio onto an existing video without re-encoding the
|
|
3
|
+
* picture: the in-process form of `ffmpeg -i base ... -map 0:v -map [aout]
|
|
4
|
+
* -c:v copy -c:a <codec> -shortest out`.
|
|
5
|
+
*/
|
|
6
|
+
import { avGetCodecName, Demuxer } from "node-av";
|
|
7
|
+
import { AudioEncoder } from "./audio-encoder.js";
|
|
8
|
+
import { abortError, openFileMuxer, quietLibav, startTimeSeconds, throwIfAborted } from "./av.js";
|
|
9
|
+
import { transformMedia } from "./transform.js";
|
|
10
|
+
function seconds(ts, timeBase) {
|
|
11
|
+
return (Number(ts) * timeBase.num) / timeBase.den;
|
|
12
|
+
}
|
|
13
|
+
/** The end of the video stream in seconds: last packet's pts plus its duration. */
|
|
14
|
+
async function videoEndSec(filePath, signal) {
|
|
15
|
+
const demuxer = await Demuxer.open(filePath, { signal });
|
|
16
|
+
try {
|
|
17
|
+
const stream = demuxer.video();
|
|
18
|
+
if (!stream)
|
|
19
|
+
throw new Error(`${filePath} has no video stream`);
|
|
20
|
+
const formatStart = startTimeSeconds(demuxer.getFormatContext().startTime, {
|
|
21
|
+
num: 1,
|
|
22
|
+
den: 1_000_000
|
|
23
|
+
});
|
|
24
|
+
let end = 0;
|
|
25
|
+
for await (const packet of demuxer.packets(stream.index)) {
|
|
26
|
+
if (!packet)
|
|
27
|
+
continue;
|
|
28
|
+
throwIfAborted(signal);
|
|
29
|
+
end = Math.max(end, seconds(packet.pts + packet.duration, stream.timeBase) - formatStart);
|
|
30
|
+
packet.free();
|
|
31
|
+
}
|
|
32
|
+
return end;
|
|
33
|
+
}
|
|
34
|
+
finally {
|
|
35
|
+
await demuxer.close();
|
|
36
|
+
}
|
|
37
|
+
}
|
|
38
|
+
/**
|
|
39
|
+
* Copy `videoPath`'s video stream into `outPath` and encode `audio` beside it
|
|
40
|
+
* as `codec` at `sampleRate`, stereo. The audio is cut at the end of the
|
|
41
|
+
* picture, as `-shortest` cut it, so a padded mix never outlasts the video.
|
|
42
|
+
* `audio`'s frames are consumed and freed.
|
|
43
|
+
*/
|
|
44
|
+
export async function muxAudioWithVideoCopy(opts) {
|
|
45
|
+
const { signal } = opts;
|
|
46
|
+
quietLibav();
|
|
47
|
+
throwIfAborted(signal);
|
|
48
|
+
const endSec = await videoEndSec(opts.videoPath, signal);
|
|
49
|
+
const demuxer = await Demuxer.open(opts.videoPath, { signal });
|
|
50
|
+
let output = null;
|
|
51
|
+
let audioEncoder = null;
|
|
52
|
+
try {
|
|
53
|
+
const videoStream = demuxer.video();
|
|
54
|
+
if (!videoStream)
|
|
55
|
+
throw new Error(`${opts.videoPath} has no video stream`);
|
|
56
|
+
output = await openFileMuxer(opts.outPath, { signal });
|
|
57
|
+
const videoIndex = output.muxer.addStream(videoStream);
|
|
58
|
+
// The CLI converted at the output: `-ar` and `-ac 2` after the graph.
|
|
59
|
+
audioEncoder = await AudioEncoder.create(opts.codec, {
|
|
60
|
+
sampleRate: opts.sampleRate,
|
|
61
|
+
channels: 2,
|
|
62
|
+
signal
|
|
63
|
+
});
|
|
64
|
+
const audioIndex = output.muxer.addStream(audioEncoder.encoder);
|
|
65
|
+
const activeEncoder = audioEncoder;
|
|
66
|
+
const activeOutput = output;
|
|
67
|
+
const formatStart = startTimeSeconds(demuxer.getFormatContext().startTime, {
|
|
68
|
+
num: 1,
|
|
69
|
+
den: 1_000_000
|
|
70
|
+
});
|
|
71
|
+
const videoPackets = demuxer.packets(videoStream.index);
|
|
72
|
+
let pendingVideo = null;
|
|
73
|
+
let videoDone = false;
|
|
74
|
+
const nextVideo = async () => {
|
|
75
|
+
while (!pendingVideo && !videoDone) {
|
|
76
|
+
const { value, done } = await videoPackets.next();
|
|
77
|
+
if (done)
|
|
78
|
+
videoDone = true;
|
|
79
|
+
else if (value)
|
|
80
|
+
pendingVideo = value;
|
|
81
|
+
}
|
|
82
|
+
};
|
|
83
|
+
const pendingVideoSec = () => pendingVideo
|
|
84
|
+
? seconds(pendingVideo.dts ?? pendingVideo.pts, videoStream.timeBase) - formatStart
|
|
85
|
+
: Number.POSITIVE_INFINITY;
|
|
86
|
+
/** Write every video packet that sorts before `untilSec`. */
|
|
87
|
+
const drainVideo = async (untilSec) => {
|
|
88
|
+
await nextVideo();
|
|
89
|
+
while (pendingVideo && pendingVideoSec() <= untilSec) {
|
|
90
|
+
const packet = pendingVideo;
|
|
91
|
+
pendingVideo = null;
|
|
92
|
+
await activeOutput.muxer.writePacket(packet, videoIndex);
|
|
93
|
+
packet.free();
|
|
94
|
+
await nextVideo();
|
|
95
|
+
}
|
|
96
|
+
};
|
|
97
|
+
const writePackets = async (packets) => {
|
|
98
|
+
for (const packet of packets) {
|
|
99
|
+
await drainVideo(seconds(packet.pts, packet.timeBase));
|
|
100
|
+
await activeOutput.muxer.writePacket(packet, audioIndex);
|
|
101
|
+
packet.free();
|
|
102
|
+
}
|
|
103
|
+
};
|
|
104
|
+
for await (const mixed of opts.audio) {
|
|
105
|
+
try {
|
|
106
|
+
if (signal?.aborted)
|
|
107
|
+
throw abortError(signal);
|
|
108
|
+
const startSec = seconds(mixed.pts, mixed.timeBase);
|
|
109
|
+
if (startSec >= endSec)
|
|
110
|
+
break;
|
|
111
|
+
const samples = mixed.nbSamples;
|
|
112
|
+
const keep = Math.min(samples, Math.ceil((endSec - startSec) * mixed.sampleRate));
|
|
113
|
+
if (keep < samples) {
|
|
114
|
+
// The frame crosses the end of the picture: keep only what lies before it.
|
|
115
|
+
mixed.nbSamples = keep;
|
|
116
|
+
}
|
|
117
|
+
await writePackets(await activeEncoder.encode(mixed));
|
|
118
|
+
if (keep < samples)
|
|
119
|
+
break;
|
|
120
|
+
}
|
|
121
|
+
finally {
|
|
122
|
+
mixed.free();
|
|
123
|
+
}
|
|
124
|
+
}
|
|
125
|
+
await writePackets(await activeEncoder.flush());
|
|
126
|
+
await drainVideo(Number.POSITIVE_INFINITY);
|
|
127
|
+
await output.close();
|
|
128
|
+
}
|
|
129
|
+
finally {
|
|
130
|
+
audioEncoder?.close();
|
|
131
|
+
await output?.close();
|
|
132
|
+
await demuxer.close();
|
|
133
|
+
}
|
|
134
|
+
}
|
|
135
|
+
/** The video and audio codec of a file, in libav's names; `null` for none. */
|
|
136
|
+
export async function streamCodecs(filePath, signal) {
|
|
137
|
+
quietLibav();
|
|
138
|
+
const demuxer = await Demuxer.open(filePath, { signal });
|
|
139
|
+
try {
|
|
140
|
+
const name = (stream) => stream ? (avGetCodecName(stream.codecpar.codecId) ?? "unknown") : null;
|
|
141
|
+
return { video: name(demuxer.video()), audio: name(demuxer.audio()) };
|
|
142
|
+
}
|
|
143
|
+
finally {
|
|
144
|
+
await demuxer.close();
|
|
145
|
+
}
|
|
146
|
+
}
|
|
147
|
+
/** The codecs each container takes without re-encoding; `null` takes any. */
|
|
148
|
+
const COPY_CODECS = {
|
|
149
|
+
mp4: {
|
|
150
|
+
video: new Set(["h264", "hevc", "av1", "vp9", "mpeg4"]),
|
|
151
|
+
audio: new Set(["aac", "mp3", "opus", "flac", "alac", "ac3", "eac3"])
|
|
152
|
+
},
|
|
153
|
+
mov: {
|
|
154
|
+
video: new Set(["h264", "hevc", "av1", "vp9", "mpeg4", "prores"]),
|
|
155
|
+
audio: new Set(["aac", "mp3", "opus", "flac", "alac", "ac3", "eac3", "pcm_s16le"])
|
|
156
|
+
},
|
|
157
|
+
webm: {
|
|
158
|
+
video: new Set(["vp8", "vp9", "av1"]),
|
|
159
|
+
audio: new Set(["opus", "vorbis"])
|
|
160
|
+
},
|
|
161
|
+
mkv: null
|
|
162
|
+
};
|
|
163
|
+
function isCopyContainer(name) {
|
|
164
|
+
return Object.hasOwn(COPY_CODECS, name);
|
|
165
|
+
}
|
|
166
|
+
/** Whether `container` holds `video` and `audio` (either may be absent) as they are. */
|
|
167
|
+
function holds(container, video, audio) {
|
|
168
|
+
const codecs = COPY_CODECS[container];
|
|
169
|
+
if (!codecs)
|
|
170
|
+
return true;
|
|
171
|
+
return (!video || codecs.video.has(video)) && (!audio || codecs.audio.has(audio));
|
|
172
|
+
}
|
|
173
|
+
/**
|
|
174
|
+
* The container a stream copy of `video` and `audio` goes into, as yt-dlp
|
|
175
|
+
* picked one when it merged: WebM when both are WebM codecs, else MP4 when
|
|
176
|
+
* MP4 holds both, else Matroska, which holds anything.
|
|
177
|
+
*/
|
|
178
|
+
export function copyContainerFor(video, audio) {
|
|
179
|
+
if (holds("webm", video, audio))
|
|
180
|
+
return "webm";
|
|
181
|
+
if (holds("mp4", video, audio))
|
|
182
|
+
return "mp4";
|
|
183
|
+
return "mkv";
|
|
184
|
+
}
|
|
185
|
+
/**
|
|
186
|
+
* Copy the video stream of `videoPath` and the audio stream of `audioPath`
|
|
187
|
+
* into one file, packets unchanged: the in-process form of
|
|
188
|
+
* `ffmpeg -i v -i a -map 0:v -map 1:a -c copy out`, which is what yt-dlp ran
|
|
189
|
+
* to merge formats.
|
|
190
|
+
*
|
|
191
|
+
* `container` is `auto` (see {@link copyContainerFor}) or a
|
|
192
|
+
* {@link CopyContainer}; the output is `<outStem>.<container>`. A container
|
|
193
|
+
* that cannot hold the codecs without re-encoding throws an error naming
|
|
194
|
+
* both codecs and the container, before any file is written. When the two
|
|
195
|
+
* paths are the same file, its audio stream is optional.
|
|
196
|
+
*/
|
|
197
|
+
export async function muxStreamCopy(opts) {
|
|
198
|
+
const { signal } = opts;
|
|
199
|
+
const sameFile = opts.videoPath === opts.audioPath;
|
|
200
|
+
const video = (await streamCodecs(opts.videoPath, signal)).video;
|
|
201
|
+
if (!video)
|
|
202
|
+
throw new Error(`${opts.videoPath} has no video stream`);
|
|
203
|
+
const audio = (await streamCodecs(opts.audioPath, signal)).audio;
|
|
204
|
+
if (!audio && !sameFile)
|
|
205
|
+
throw new Error(`${opts.audioPath} has no audio stream`);
|
|
206
|
+
const requested = opts.container.trim().toLowerCase().replace(/^\./, "");
|
|
207
|
+
const container = requested === "" || requested === "auto" ? copyContainerFor(video, audio) : requested;
|
|
208
|
+
if (!isCopyContainer(container)) {
|
|
209
|
+
throw new Error(`Cannot write container "${opts.container}": use auto, mp4, mov, webm or mkv`);
|
|
210
|
+
}
|
|
211
|
+
const pair = audio ? `${video} video with ${audio} audio` : `${video} video`;
|
|
212
|
+
if (!holds(container, video, audio)) {
|
|
213
|
+
throw new Error(`Cannot stream-copy ${pair} into ${container} without re-encoding. ` +
|
|
214
|
+
`Use container auto or mkv.`);
|
|
215
|
+
}
|
|
216
|
+
const outPath = `${opts.outStem}.${container}`;
|
|
217
|
+
try {
|
|
218
|
+
await transformMedia({
|
|
219
|
+
inputs: [{ filePath: opts.videoPath }, { filePath: opts.audioPath }],
|
|
220
|
+
outPath,
|
|
221
|
+
video: { copy: 0 },
|
|
222
|
+
audio: { copy: 1, optional: sameFile },
|
|
223
|
+
signal
|
|
224
|
+
});
|
|
225
|
+
}
|
|
226
|
+
catch (error) {
|
|
227
|
+
if (signal?.aborted)
|
|
228
|
+
throw error;
|
|
229
|
+
throw new Error(`Could not stream-copy ${pair} into ${container}: ` +
|
|
230
|
+
`${error instanceof Error ? error.message : String(error)}`);
|
|
231
|
+
}
|
|
232
|
+
return { outPath, container, video, audio };
|
|
233
|
+
}
|
|
234
|
+
//# sourceMappingURL=mux.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"mux.js","sourceRoot":"","sources":["../../src/media/mux.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,84 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Container probes on Mediabunny: duration, picture size, frame rates,
|
|
3
|
+
* streams and packet timestamps, read without decoding anything.
|
|
4
|
+
*/
|
|
5
|
+
/** A file path or the file's bytes. */
|
|
6
|
+
export type MediaSource = string | Uint8Array;
|
|
7
|
+
export interface VideoStreamInfo {
|
|
8
|
+
codec: string | null;
|
|
9
|
+
/** Coded size before rotation, as ffprobe's `stream=width,height` reports it. */
|
|
10
|
+
width: number;
|
|
11
|
+
height: number;
|
|
12
|
+
/** Size after rotation metadata is applied. */
|
|
13
|
+
displayWidth: number;
|
|
14
|
+
displayHeight: number;
|
|
15
|
+
rotation: number;
|
|
16
|
+
/**
|
|
17
|
+
* The rate of the timestamp lattice the frames sit on, or `null` when the
|
|
18
|
+
* frames sit on none (a truly variable-rate source). Frames may be missing
|
|
19
|
+
* from the lattice: a 60 fps grid with two frames of every five kept still
|
|
20
|
+
* reports 60. This is what ffprobe calls `r_frame_rate` for files whose
|
|
21
|
+
* header carries a real rate.
|
|
22
|
+
*/
|
|
23
|
+
nominalFps: number | null;
|
|
24
|
+
/** Frames per second over the probed packets, as ffprobe's `avg_frame_rate`. */
|
|
25
|
+
averageFps: number;
|
|
26
|
+
/** True only when every lattice slot holds a frame. */
|
|
27
|
+
constantFrameRate: boolean;
|
|
28
|
+
/** Whether the frames may carry alpha (a `yuva*` or RGBA stream). */
|
|
29
|
+
alpha: boolean;
|
|
30
|
+
/** Ticks per second of the track's timestamps. */
|
|
31
|
+
timeResolution: number;
|
|
32
|
+
}
|
|
33
|
+
export interface AudioStreamInfo {
|
|
34
|
+
codec: string | null;
|
|
35
|
+
sampleRate: number;
|
|
36
|
+
channels: number;
|
|
37
|
+
}
|
|
38
|
+
export interface MediaProbe {
|
|
39
|
+
/** Container name, e.g. `MP4`, `Matroska`, `WAVE`. */
|
|
40
|
+
format: string;
|
|
41
|
+
/** End of the last packet in seconds, or `null` when it cannot be known. */
|
|
42
|
+
durationSec: number | null;
|
|
43
|
+
video: VideoStreamInfo | null;
|
|
44
|
+
audio: AudioStreamInfo | null;
|
|
45
|
+
}
|
|
46
|
+
export interface ProbeOptions {
|
|
47
|
+
signal?: AbortSignal;
|
|
48
|
+
/**
|
|
49
|
+
* How many video packets the frame-rate measurement reads. Mediabunny needs
|
|
50
|
+
* about 256 for a reliable answer. `Infinity` reads the whole track.
|
|
51
|
+
*/
|
|
52
|
+
frameRatePackets?: number;
|
|
53
|
+
}
|
|
54
|
+
/**
|
|
55
|
+
* Read `source`'s streams and timing. Throws when the bytes are not a
|
|
56
|
+
* container Mediabunny recognizes; callers that treat unreadable media as
|
|
57
|
+
* "no audio" or "no duration" catch that.
|
|
58
|
+
*/
|
|
59
|
+
export declare function probeMedia(source: MediaSource, options?: ProbeOptions): Promise<MediaProbe>;
|
|
60
|
+
/**
|
|
61
|
+
* `source`'s duration in seconds, or `null` when it is not media Mediabunny
|
|
62
|
+
* reads or names no duration. An abort still throws.
|
|
63
|
+
*/
|
|
64
|
+
export declare function probeDurationSec(source: MediaSource, options?: ProbeOptions): Promise<number | null>;
|
|
65
|
+
/**
|
|
66
|
+
* Whether `source` has an audio stream. Media Mediabunny cannot read has
|
|
67
|
+
* none. An abort still throws.
|
|
68
|
+
*/
|
|
69
|
+
export declare function probeHasAudio(source: MediaSource, options?: ProbeOptions): Promise<boolean>;
|
|
70
|
+
/**
|
|
71
|
+
* `source`'s primary video stream, or `null` when it has none or is not media
|
|
72
|
+
* Mediabunny reads. An abort still throws.
|
|
73
|
+
*/
|
|
74
|
+
export declare function probeVideoStream(source: MediaSource, options?: ProbeOptions): Promise<VideoStreamInfo | null>;
|
|
75
|
+
/**
|
|
76
|
+
* Presentation timestamps of the primary video track's packets in seconds, in
|
|
77
|
+
* file (decode) order, as ffprobe's `packet=pts_time` lists them. `null` when
|
|
78
|
+
* there is no video track or the track has more than `maxPackets` packets.
|
|
79
|
+
*/
|
|
80
|
+
export declare function packetTimes(source: MediaSource, options?: {
|
|
81
|
+
signal?: AbortSignal;
|
|
82
|
+
maxPackets?: number;
|
|
83
|
+
}): Promise<number[] | null>;
|
|
84
|
+
//# sourceMappingURL=probe.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"probe.d.ts","sourceRoot":"","sources":["../../src/media/probe.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAYH,uCAAuC;AACvC,MAAM,MAAM,WAAW,GAAG,MAAM,GAAG,UAAU,CAAC;AAE9C,MAAM,WAAW,eAAe;IAC9B,KAAK,EAAE,MAAM,GAAG,IAAI,CAAC;IACrB,iFAAiF;IACjF,KAAK,EAAE,MAAM,CAAC;IACd,MAAM,EAAE,MAAM,CAAC;IACf,+CAA+C;IAC/C,YAAY,EAAE,MAAM,CAAC;IACrB,aAAa,EAAE,MAAM,CAAC;IACtB,QAAQ,EAAE,MAAM,CAAC;IACjB;;;;;;OAMG;IACH,UAAU,EAAE,MAAM,GAAG,IAAI,CAAC;IAC1B,gFAAgF;IAChF,UAAU,EAAE,MAAM,CAAC;IACnB,uDAAuD;IACvD,iBAAiB,EAAE,OAAO,CAAC;IAC3B,qEAAqE;IACrE,KAAK,EAAE,OAAO,CAAC;IACf,kDAAkD;IAClD,cAAc,EAAE,MAAM,CAAC;CACxB;AAED,MAAM,WAAW,eAAe;IAC9B,KAAK,EAAE,MAAM,GAAG,IAAI,CAAC;IACrB,UAAU,EAAE,MAAM,CAAC;IACnB,QAAQ,EAAE,MAAM,CAAC;CAClB;AAED,MAAM,WAAW,UAAU;IACzB,sDAAsD;IACtD,MAAM,EAAE,MAAM,CAAC;IACf,4EAA4E;IAC5E,WAAW,EAAE,MAAM,GAAG,IAAI,CAAC;IAC3B,KAAK,EAAE,eAAe,GAAG,IAAI,CAAC;IAC9B,KAAK,EAAE,eAAe,GAAG,IAAI,CAAC;CAC/B;AAED,MAAM,WAAW,YAAY;IAC3B,MAAM,CAAC,EAAE,WAAW,CAAC;IACrB;;;OAGG;IACH,gBAAgB,CAAC,EAAE,MAAM,CAAC;CAC3B;AAUD;;;;GAIG;AACH,wBAAsB,UAAU,CAC9B,MAAM,EAAE,WAAW,EACnB,OAAO,GAAE,YAAiB,GACzB,OAAO,CAAC,UAAU,CAAC,CAmDrB;AAkBD;;;GAGG;AACH,wBAAsB,gBAAgB,CACpC,MAAM,EAAE,WAAW,EACnB,OAAO,GAAE,YAAiB,GACzB,OAAO,CAAC,MAAM,GAAG,IAAI,CAAC,CAExB;AAED;;;GAGG;AACH,wBAAsB,aAAa,CACjC,MAAM,EAAE,WAAW,EACnB,OAAO,GAAE,YAAiB,GACzB,OAAO,CAAC,OAAO,CAAC,CAGlB;AAED;;;GAGG;AACH,wBAAsB,gBAAgB,CACpC,MAAM,EAAE,WAAW,EACnB,OAAO,GAAE,YAAiB,GACzB,OAAO,CAAC,eAAe,GAAG,IAAI,CAAC,CAEjC;AAED;;;;GAIG;AACH,wBAAsB,WAAW,CAC/B,MAAM,EAAE,WAAW,EACnB,OAAO,GAAE;IAAE,MAAM,CAAC,EAAE,WAAW,CAAC;IAAC,UAAU,CAAC,EAAE,MAAM,CAAA;CAAO,GAC1D,OAAO,CAAC,MAAM,EAAE,GAAG,IAAI,CAAC,CAmB1B"}
|