avbridge 2.8.4 → 2.10.0
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/CHANGELOG.md +164 -0
- package/README.md +74 -1
- package/dist/{avi-F6WZJK5T.cjs → avi-2ILLBNPQ.cjs} +8 -2
- package/dist/avi-2ILLBNPQ.cjs.map +1 -0
- package/dist/{avi-W6L3BTWU.cjs → avi-B5CQYB7L.cjs} +8 -2
- package/dist/avi-B5CQYB7L.cjs.map +1 -0
- package/dist/{avi-2JPBSHGA.js → avi-JXU4GQL2.js} +8 -2
- package/dist/avi-JXU4GQL2.js.map +1 -0
- package/dist/{avi-NJXAXUXK.js → avi-RWWPN2PR.js} +8 -2
- package/dist/avi-RWWPN2PR.js.map +1 -0
- package/dist/{chunk-X2K3GIWE.js → chunk-2NSOOMXW.js} +14 -3
- package/dist/chunk-2NSOOMXW.js.map +1 -0
- package/dist/{chunk-KBWQRGHS.js → chunk-3GKM5DFM.js} +119 -8
- package/dist/chunk-3GKM5DFM.js.map +1 -0
- package/dist/{chunk-ZCUXHW55.cjs → chunk-BYGZN4Z5.cjs} +5 -5
- package/dist/{chunk-ZCUXHW55.cjs.map → chunk-BYGZN4Z5.cjs.map} +1 -1
- package/dist/{chunk-SMH6IOP2.js → chunk-CL6UEUQF.js} +4 -4
- package/dist/{chunk-SMH6IOP2.js.map → chunk-CL6UEUQF.js.map} +1 -1
- package/dist/{chunk-SR3MPV4D.js → chunk-GYIJU44C.js} +5 -5
- package/dist/{chunk-SR3MPV4D.js.map → chunk-GYIJU44C.js.map} +1 -1
- package/dist/{chunk-CPZ7PXAM.cjs → chunk-L7A3ECI2.cjs} +14 -2
- package/dist/chunk-L7A3ECI2.cjs.map +1 -0
- package/dist/{chunk-YX4AGLNF.cjs → chunk-NQULEIA3.cjs} +129 -18
- package/dist/chunk-NQULEIA3.cjs.map +1 -0
- package/dist/{chunk-Q2VUO52Z.cjs → chunk-OTFS7DC4.cjs} +12 -12
- package/dist/{chunk-Q2VUO52Z.cjs.map → chunk-OTFS7DC4.cjs.map} +1 -1
- package/dist/element-browser.js +144 -10
- package/dist/element-browser.js.map +1 -1
- package/dist/element.cjs +16 -10
- package/dist/element.cjs.map +1 -1
- package/dist/element.d.cts +11 -6
- package/dist/element.d.ts +11 -6
- package/dist/element.js +15 -9
- package/dist/element.js.map +1 -1
- package/dist/index.cjs +20 -20
- package/dist/index.d.cts +2 -2
- package/dist/index.d.ts +2 -2
- package/dist/index.js +8 -8
- package/dist/libav-demux-3N5Y3VQA.cjs +31 -0
- package/dist/{libav-demux-H2GS46GH.cjs.map → libav-demux-3N5Y3VQA.cjs.map} +1 -1
- package/dist/libav-demux-JXD4OTLM.js +6 -0
- package/dist/{libav-demux-OWZ4T2YW.js.map → libav-demux-JXD4OTLM.js.map} +1 -1
- package/dist/{player-BptSJPfn.d.cts → player-DDdNVFDv.d.cts} +24 -2
- package/dist/{player-BptSJPfn.d.ts → player-DDdNVFDv.d.ts} +24 -2
- package/dist/player.cjs +413 -117
- package/dist/player.cjs.map +1 -1
- package/dist/player.d.cts +44 -11
- package/dist/player.d.ts +44 -11
- package/dist/player.js +413 -117
- package/dist/player.js.map +1 -1
- package/dist/{remux-WBYIZBBX.js → remux-56V7LDAD.js} +5 -5
- package/dist/{remux-WBYIZBBX.js.map → remux-56V7LDAD.js.map} +1 -1
- package/dist/{remux-OBSMIENG.cjs → remux-KUS5GIL6.cjs} +10 -10
- package/dist/{remux-OBSMIENG.cjs.map → remux-KUS5GIL6.cjs.map} +1 -1
- package/package.json +1 -1
- package/src/classify/rules.ts +2 -0
- package/src/element/avbridge-player.ts +172 -86
- package/src/element/avbridge-video.ts +22 -6
- package/src/element/player-styles.ts +149 -34
- package/src/index.ts +1 -0
- package/src/probe/avi.ts +2 -0
- package/src/strategies/fallback/audio-output.ts +29 -4
- package/src/strategies/fallback/decoder.ts +30 -0
- package/src/strategies/fallback/index.ts +42 -0
- package/src/strategies/hybrid/decoder.ts +35 -0
- package/src/strategies/hybrid/index.ts +26 -0
- package/src/strategies/remux/index.ts +8 -0
- package/src/types.ts +31 -0
- package/src/util/libav-demux.ts +26 -0
- package/dist/avi-2JPBSHGA.js.map +0 -1
- package/dist/avi-F6WZJK5T.cjs.map +0 -1
- package/dist/avi-NJXAXUXK.js.map +0 -1
- package/dist/avi-W6L3BTWU.cjs.map +0 -1
- package/dist/chunk-CPZ7PXAM.cjs.map +0 -1
- package/dist/chunk-KBWQRGHS.js.map +0 -1
- package/dist/chunk-X2K3GIWE.js.map +0 -1
- package/dist/chunk-YX4AGLNF.cjs.map +0 -1
- package/dist/libav-demux-H2GS46GH.cjs +0 -27
- package/dist/libav-demux-OWZ4T2YW.js +0 -6
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
'use strict';
|
|
2
2
|
|
|
3
|
-
var
|
|
3
|
+
var chunkBYGZN4Z5_cjs = require('./chunk-BYGZN4Z5.cjs');
|
|
4
4
|
var chunk2IJ66NTD_cjs = require('./chunk-2IJ66NTD.cjs');
|
|
5
|
-
var
|
|
5
|
+
var chunkL7A3ECI2_cjs = require('./chunk-L7A3ECI2.cjs');
|
|
6
6
|
var chunkZ33SBWL5_cjs = require('./chunk-Z33SBWL5.cjs');
|
|
7
7
|
|
|
8
8
|
function isAnnexB(bytes) {
|
|
@@ -72,7 +72,7 @@ var MEDIABUNNY_CONTAINERS = /* @__PURE__ */ new Set([
|
|
|
72
72
|
async function remux(source, options = {}) {
|
|
73
73
|
const outputFormat = options.outputFormat ?? "mp4";
|
|
74
74
|
options.signal?.throwIfAborted();
|
|
75
|
-
const ctx = await
|
|
75
|
+
const ctx = await chunkBYGZN4Z5_cjs.probe(source);
|
|
76
76
|
options.signal?.throwIfAborted();
|
|
77
77
|
validateRemuxEligibility(ctx, options.strict ?? false);
|
|
78
78
|
if (MEDIABUNNY_CONTAINERS.has(ctx.container)) {
|
|
@@ -84,7 +84,7 @@ function validateRemuxEligibility(ctx, strict) {
|
|
|
84
84
|
const video = ctx.videoTracks[0];
|
|
85
85
|
const audio = ctx.audioTracks[0];
|
|
86
86
|
if (video) {
|
|
87
|
-
const mbCodec =
|
|
87
|
+
const mbCodec = chunkBYGZN4Z5_cjs.avbridgeVideoToMediabunny(video.codec);
|
|
88
88
|
if (!mbCodec) {
|
|
89
89
|
throw new Error(
|
|
90
90
|
`Cannot remux: video codec "${video.codec}" is not supported for remuxing. Use transcode() to re-encode to a modern codec.`
|
|
@@ -92,7 +92,7 @@ function validateRemuxEligibility(ctx, strict) {
|
|
|
92
92
|
}
|
|
93
93
|
}
|
|
94
94
|
if (audio) {
|
|
95
|
-
const mbCodec =
|
|
95
|
+
const mbCodec = chunkBYGZN4Z5_cjs.avbridgeAudioToMediabunny(audio.codec);
|
|
96
96
|
if (!mbCodec) {
|
|
97
97
|
throw new Error(
|
|
98
98
|
`Cannot remux: audio codec "${audio.codec}" is not supported for remuxing. Use transcode() to re-encode to a modern codec.`
|
|
@@ -111,7 +111,7 @@ function validateRemuxEligibility(ctx, strict) {
|
|
|
111
111
|
async function remuxViaMediAbunny(ctx, outputFormat, options) {
|
|
112
112
|
const mb = await import('mediabunny');
|
|
113
113
|
const input = new mb.Input({
|
|
114
|
-
source: await
|
|
114
|
+
source: await chunkBYGZN4Z5_cjs.buildMediabunnySourceFromInput(mb, ctx.source),
|
|
115
115
|
formats: mb.ALL_FORMATS
|
|
116
116
|
});
|
|
117
117
|
const target = new mb.BufferTarget();
|
|
@@ -197,8 +197,8 @@ async function doLibavRemux(libav, filename, ctx, outputFormat, options) {
|
|
|
197
197
|
const audioStream = streams.find((s) => s.codec_type === libav.AVMEDIA_TYPE_AUDIO) ?? null;
|
|
198
198
|
const videoTrackInfo = ctx.videoTracks[0];
|
|
199
199
|
const audioTrackInfo = ctx.audioTracks[0];
|
|
200
|
-
const mbVideoCodec = videoTrackInfo ?
|
|
201
|
-
const mbAudioCodec = audioTrackInfo ?
|
|
200
|
+
const mbVideoCodec = videoTrackInfo ? chunkBYGZN4Z5_cjs.avbridgeVideoToMediabunny(videoTrackInfo.codec) : null;
|
|
201
|
+
const mbAudioCodec = audioTrackInfo ? chunkBYGZN4Z5_cjs.avbridgeAudioToMediabunny(audioTrackInfo.codec) : null;
|
|
202
202
|
const target = new mb.BufferTarget();
|
|
203
203
|
const output = new mb.Output({
|
|
204
204
|
format: createOutputFormat(mb, outputFormat),
|
|
@@ -240,7 +240,7 @@ async function doLibavRemux(libav, filename, ctx, outputFormat, options) {
|
|
|
240
240
|
const audioPackets = audioStream ? packets[audioStream.index] ?? [] : [];
|
|
241
241
|
if (videoSource) {
|
|
242
242
|
for (const pkt of videoPackets) {
|
|
243
|
-
|
|
243
|
+
chunkL7A3ECI2_cjs.sanitizePacketTimestamp(pkt, () => {
|
|
244
244
|
const ts = syntheticVideoUs;
|
|
245
245
|
syntheticVideoUs += videoFrameStepUs;
|
|
246
246
|
return ts;
|
|
@@ -258,7 +258,7 @@ async function doLibavRemux(libav, filename, ctx, outputFormat, options) {
|
|
|
258
258
|
}
|
|
259
259
|
if (audioSource) {
|
|
260
260
|
for (const pkt of audioPackets) {
|
|
261
|
-
|
|
261
|
+
chunkL7A3ECI2_cjs.sanitizePacketTimestamp(pkt, () => {
|
|
262
262
|
const ts = syntheticAudioUs;
|
|
263
263
|
const sampleRate = audioTrackInfo?.sampleRate ?? 44100;
|
|
264
264
|
syntheticAudioUs += Math.round(1024 * 1e6 / sampleRate);
|
|
@@ -370,5 +370,5 @@ exports.generateFilename = generateFilename;
|
|
|
370
370
|
exports.mimeForFormat = mimeForFormat;
|
|
371
371
|
exports.remux = remux;
|
|
372
372
|
exports.validateRemuxEligibility = validateRemuxEligibility;
|
|
373
|
-
//# sourceMappingURL=chunk-
|
|
374
|
-
//# sourceMappingURL=chunk-
|
|
373
|
+
//# sourceMappingURL=chunk-OTFS7DC4.cjs.map
|
|
374
|
+
//# sourceMappingURL=chunk-OTFS7DC4.cjs.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/strategies/remux/annexb.ts","../src/convert/remux.ts"],"names":["probe","avbridgeVideoToMediabunny","avbridgeAudioToMediabunny","buildMediabunnySourceFromInput","normalizeSource","prepareLibavInput","sanitizePacketTimestamp"],"mappings":"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","file":"chunk-Q2VUO52Z.cjs","sourcesContent":["/**\n * H.264/HEVC bitstream conversion helpers.\n *\n * Demuxers from MP4-family containers (mediabunny) hand us packets in **AVCC**\n * format: each NAL unit prefixed with a 4-byte big-endian length.\n *\n * Demuxers from elementary-stream/AVI/TS hand us **Annex B**: NAL units\n * separated by `00 00 00 01` (or `00 00 01`) start codes.\n *\n * MSE expects AVCC inside fragmented MP4. So when the source side emits Annex\n * B, we need to convert before muxing. Going the other way (AVCC → Annex B) is\n * useful for feeding `VideoDecoder` configured with `description` omitted.\n */\n\nconst START_CODE_4 = new Uint8Array([0, 0, 0, 1]);\n\n/** True if the bytes look like Annex B (start with `00 00 00 01` or `00 00 01`). */\nexport function isAnnexB(bytes: Uint8Array): boolean {\n if (bytes.length < 3) return false;\n if (bytes[0] === 0 && bytes[1] === 0 && bytes[2] === 1) return true;\n if (bytes.length >= 4 && bytes[0] === 0 && bytes[1] === 0 && bytes[2] === 0 && bytes[3] === 1) return true;\n return false;\n}\n\n/**\n * Walk an Annex B byte stream and yield each NAL unit (without start code).\n * This is the standard byte-by-byte scan; no SIMD tricks because the typical\n * frame is small.\n */\nexport function* iterateAnnexBNalus(bytes: Uint8Array): Generator<Uint8Array> {\n const length = bytes.length;\n let i = 0;\n let nalStart = -1;\n\n while (i < length) {\n // Look for start code at position i\n let scLen = 0;\n if (i + 3 < length && bytes[i] === 0 && bytes[i + 1] === 0 && bytes[i + 2] === 0 && bytes[i + 3] === 1) {\n scLen = 4;\n } else if (i + 2 < length && bytes[i] === 0 && bytes[i + 1] === 0 && bytes[i + 2] === 1) {\n scLen = 3;\n }\n\n if (scLen > 0) {\n if (nalStart >= 0) {\n yield bytes.subarray(nalStart, i);\n }\n nalStart = i + scLen;\n i += scLen;\n } else {\n i += 1;\n }\n }\n\n if (nalStart >= 0 && nalStart < length) {\n yield bytes.subarray(nalStart, length);\n }\n}\n\n/**\n * Convert an Annex B byte stream to AVCC. Each NALU is prefixed with its\n * 4-byte big-endian length.\n */\nexport function annexBToAvcc(annexB: Uint8Array): Uint8Array {\n const nalus: Uint8Array[] = [];\n let total = 0;\n for (const nal of iterateAnnexBNalus(annexB)) {\n nalus.push(nal);\n total += 4 + nal.length;\n }\n const out = new Uint8Array(total);\n let off = 0;\n for (const nal of nalus) {\n const len = nal.length;\n out[off++] = (len >>> 24) & 0xff;\n out[off++] = (len >>> 16) & 0xff;\n out[off++] = (len >>> 8) & 0xff;\n out[off++] = len & 0xff;\n out.set(nal, off);\n off += len;\n }\n return out;\n}\n\n/**\n * Convert AVCC (4-byte length-prefixed) NALUs to Annex B. Each NALU is\n * prefixed with `00 00 00 01`.\n */\nexport function avccToAnnexB(avcc: Uint8Array): Uint8Array {\n const out: Uint8Array[] = [];\n let total = 0;\n let i = 0;\n while (i + 4 <= avcc.length) {\n const len =\n (avcc[i] << 24) | (avcc[i + 1] << 16) | (avcc[i + 2] << 8) | avcc[i + 3];\n i += 4;\n if (i + len > avcc.length) {\n throw new Error(`avccToAnnexB: NAL length ${len} overflows buffer at offset ${i}`);\n }\n out.push(START_CODE_4);\n out.push(avcc.subarray(i, i + len));\n total += 4 + len;\n i += len;\n }\n const merged = new Uint8Array(total);\n let off = 0;\n for (const chunk of out) {\n merged.set(chunk, off);\n off += chunk.length;\n }\n return merged;\n}\n","/**\n * Standalone remux function: repackage media into a modern container without\n * re-encoding. Input can be any format avbridge can probe; output is a\n * finalized downloadable file (MP4, WebM, or MKV).\n *\n * Two internal paths:\n * - **Path A** (mediabunny-readable containers): wraps mediabunny's Conversion\n * class for MP4/MKV/WebM/OGG/MOV/WAV/MP3/FLAC/ADTS sources.\n * - **Path B** (AVI/ASF/FLV): libav.js demux + mediabunny mux via manual\n * packet pump. Lazy-loads libav.js — zero cost if unused.\n */\n\nimport { probe } from \"../probe/index.js\";\nimport { isAnnexB, annexBToAvcc } from \"../strategies/remux/annexb.js\";\nimport {\n avbridgeVideoToMediabunny,\n avbridgeAudioToMediabunny,\n buildMediabunnySourceFromInput,\n} from \"../probe/mediabunny.js\";\nimport { normalizeSource } from \"../util/source.js\";\nimport { sanitizePacketTimestamp } from \"../util/libav-demux.js\";\nimport { prepareLibavInput, type LibavInputHandle } from \"../util/libav-http-reader.js\";\nimport type {\n MediaInput,\n MediaContext,\n ConvertOptions,\n ConvertResult,\n OutputFormat,\n} from \"../types.js\";\n\n/** Containers mediabunny can read (and therefore use Conversion for). */\nconst MEDIABUNNY_CONTAINERS = new Set([\n \"mp4\", \"mov\", \"mkv\", \"webm\", \"ogg\", \"wav\", \"mp3\", \"flac\", \"adts\",\n]);\n\n/**\n * Remux a media source into a modern container format without re-encoding.\n *\n * @throws When the source codecs cannot be remuxed (e.g. WMV3 — use `transcode()` instead).\n * @throws When an AVI/ASF/FLV source is provided but libav.js is not installed.\n */\nexport async function remux(\n source: MediaInput,\n options: ConvertOptions = {},\n): Promise<ConvertResult> {\n const outputFormat = options.outputFormat ?? \"mp4\";\n options.signal?.throwIfAborted();\n\n // Probe the source\n const ctx = await probe(source);\n options.signal?.throwIfAborted();\n\n // Validate remux eligibility: all codecs must map to mediabunny output codecs\n validateRemuxEligibility(ctx, options.strict ?? false);\n\n // Route to the appropriate path\n if (MEDIABUNNY_CONTAINERS.has(ctx.container)) {\n return remuxViaMediAbunny(ctx, outputFormat, options);\n }\n return remuxViaLibav(ctx, outputFormat, options);\n}\n\n// ── Eligibility validation ──────────────────────────────────────────────────\n\n/** @internal Exported for testing. */\nexport function validateRemuxEligibility(ctx: MediaContext, strict: boolean): void {\n const video = ctx.videoTracks[0];\n const audio = ctx.audioTracks[0];\n\n if (video) {\n const mbCodec = avbridgeVideoToMediabunny(video.codec);\n if (!mbCodec) {\n throw new Error(\n `Cannot remux: video codec \"${video.codec}\" is not supported for remuxing. ` +\n `Use transcode() to re-encode to a modern codec.`,\n );\n }\n }\n\n if (audio) {\n const mbCodec = avbridgeAudioToMediabunny(audio.codec);\n if (!mbCodec) {\n throw new Error(\n `Cannot remux: audio codec \"${audio.codec}\" is not supported for remuxing. ` +\n `Use transcode() to re-encode to a modern codec.`,\n );\n }\n }\n\n if (strict && video?.codec === \"h264\" && audio?.codec === \"mp3\") {\n throw new Error(\n `Cannot remux in strict mode: H.264 + MP3 is a best-effort combination ` +\n `that may produce playback issues in some browsers. ` +\n `Set strict: false to allow, or use transcode() to re-encode audio to AAC.`,\n );\n }\n\n if (!video && !audio) {\n throw new Error(\"Cannot remux: source has no video or audio tracks.\");\n }\n}\n\n// ── Path A: mediabunny Conversion ───────────────────────────────────────────\n\nasync function remuxViaMediAbunny(\n ctx: MediaContext,\n outputFormat: OutputFormat,\n options: ConvertOptions,\n): Promise<ConvertResult> {\n const mb = await import(\"mediabunny\");\n\n const input = new mb.Input({\n source: await buildMediabunnySourceFromInput(mb, ctx.source),\n formats: mb.ALL_FORMATS,\n });\n\n const target = new mb.BufferTarget();\n const output = new mb.Output({\n format: createOutputFormat(mb, outputFormat),\n target,\n });\n\n const conversion = await mb.Conversion.init({\n input,\n output,\n showWarnings: false,\n });\n\n if (!conversion.isValid) {\n const reasons = conversion.discardedTracks\n .map((d) => `${d.track.type} track discarded: ${d.reason}`)\n .join(\"; \");\n throw new Error(`Cannot remux: mediabunny rejected the conversion. ${reasons}`);\n }\n\n // Wire progress\n if (options.onProgress) {\n const onProgress = options.onProgress;\n conversion.onProgress = (p) => {\n onProgress({ percent: p * 100, bytesWritten: 0 });\n };\n }\n\n // Wire cancellation\n let abortHandler: (() => void) | undefined;\n if (options.signal) {\n options.signal.throwIfAborted();\n abortHandler = () => void conversion.cancel();\n options.signal.addEventListener(\"abort\", abortHandler, { once: true });\n }\n\n try {\n await conversion.execute();\n } finally {\n if (abortHandler && options.signal) {\n options.signal.removeEventListener(\"abort\", abortHandler);\n }\n }\n\n if (!target.buffer) {\n throw new Error(\"Remux failed: mediabunny produced no output buffer.\");\n }\n\n const mimeType = mimeForFormat(outputFormat);\n const blob = new Blob([target.buffer], { type: mimeType });\n const filename = generateFilename(ctx.name, outputFormat);\n\n options.onProgress?.({ percent: 100, bytesWritten: blob.size });\n\n return {\n blob,\n mimeType,\n container: outputFormat,\n videoCodec: ctx.videoTracks[0]?.codec,\n audioCodec: ctx.audioTracks[0]?.codec,\n duration: ctx.duration,\n filename,\n };\n}\n\n// ── Path B: libav.js demux + mediabunny mux (AVI/ASF/FLV) ──────────────────\n\nasync function remuxViaLibav(\n ctx: MediaContext,\n outputFormat: OutputFormat,\n options: ConvertOptions,\n): Promise<ConvertResult> {\n // Lazy-load libav\n let loadLibav: typeof import(\"../strategies/fallback/libav-loader.js\").loadLibav;\n let pickLibavVariant: typeof import(\"../strategies/fallback/variant-routing.js\").pickLibavVariant;\n try {\n const loader = await import(\"../strategies/fallback/libav-loader.js\");\n const routing = await import(\"../strategies/fallback/variant-routing.js\");\n loadLibav = loader.loadLibav;\n pickLibavVariant = routing.pickLibavVariant;\n } catch {\n throw new Error(\n `Cannot remux ${ctx.container.toUpperCase()} source: libav.js is not available. ` +\n `Install @libav.js/variant-webcodecs and libavjs-webcodecs-bridge, ` +\n `or build the custom avbridge variant with scripts/build-libav.sh.`,\n );\n }\n\n const variant = pickLibavVariant(ctx);\n const libav = await loadLibav(variant) as unknown as LibavRuntime;\n\n // For Blob/File inputs, libav reads from an in-memory readahead file.\n // For URL inputs, libav demuxes via HTTP Range requests through the\n // block reader — no full download.\n const normalized = await normalizeSource(ctx.source);\n const filename = ctx.name ?? `remux-input-${Date.now()}`;\n const handle: LibavInputHandle = await prepareLibavInput(libav as unknown as Parameters<typeof prepareLibavInput>[0], filename, normalized);\n\n try {\n return await doLibavRemux(libav, filename, ctx, outputFormat, options);\n } finally {\n await handle.detach().catch(() => {});\n }\n}\n\nasync function doLibavRemux(\n libav: LibavRuntime,\n filename: string,\n ctx: MediaContext,\n outputFormat: OutputFormat,\n options: ConvertOptions,\n): Promise<ConvertResult> {\n const mb = await import(\"mediabunny\");\n\n const readPkt = await libav.av_packet_alloc();\n const [fmt_ctx, streams] = await libav.ff_init_demuxer_file(filename);\n const videoStream = streams.find((s) => s.codec_type === libav.AVMEDIA_TYPE_VIDEO) ?? null;\n const audioStream = streams.find((s) => s.codec_type === libav.AVMEDIA_TYPE_AUDIO) ?? null;\n\n // Map codecs to mediabunny output\n const videoTrackInfo = ctx.videoTracks[0];\n const audioTrackInfo = ctx.audioTracks[0];\n const mbVideoCodec = videoTrackInfo ? avbridgeVideoToMediabunny(videoTrackInfo.codec) : null;\n const mbAudioCodec = audioTrackInfo ? avbridgeAudioToMediabunny(audioTrackInfo.codec) : null;\n\n // Set up mediabunny output with BufferTarget\n const target = new mb.BufferTarget();\n const output = new mb.Output({\n format: createOutputFormat(mb, outputFormat),\n target,\n });\n\n let videoSource: InstanceType<typeof mb.EncodedVideoPacketSource> | null = null;\n let audioSource: InstanceType<typeof mb.EncodedAudioPacketSource> | null = null;\n\n if (mbVideoCodec && videoStream) {\n videoSource = new mb.EncodedVideoPacketSource(mbVideoCodec);\n output.addVideoTrack(videoSource);\n }\n if (mbAudioCodec && audioStream) {\n type AudioCodecArg = ConstructorParameters<typeof mb.EncodedAudioPacketSource>[0];\n audioSource = new mb.EncodedAudioPacketSource(mbAudioCodec as AudioCodecArg);\n output.addAudioTrack(audioSource);\n }\n\n await output.start();\n\n // Timestamp tracking for synthetic timestamps\n const videoFps = videoTrackInfo?.fps && videoTrackInfo.fps > 0 ? videoTrackInfo.fps : 30;\n const videoFrameStepUs = Math.max(1, Math.round(1_000_000 / videoFps));\n let syntheticVideoUs = 0;\n let syntheticAudioUs = 0;\n\n const videoTimeBase: [number, number] | undefined =\n videoStream?.time_base_num && videoStream?.time_base_den\n ? [videoStream.time_base_num, videoStream.time_base_den]\n : undefined;\n const audioTimeBase: [number, number] | undefined =\n audioStream?.time_base_num && audioStream?.time_base_den\n ? [audioStream.time_base_num, audioStream.time_base_den]\n : undefined;\n\n let totalPackets = 0;\n const durationUs = ctx.duration ? ctx.duration * 1_000_000 : 0;\n let firstVideoMeta = true;\n let firstAudioMeta = true;\n\n // Pump loop: read packets from libav, feed to mediabunny output\n while (true) {\n options.signal?.throwIfAborted();\n\n let readErr: number;\n let packets: Record<number, LibavPacket[]>;\n try {\n [readErr, packets] = await libav.ff_read_frame_multi(fmt_ctx, readPkt, {\n limit: 64 * 1024,\n });\n } catch (err) {\n throw new Error(`libav demux failed: ${(err as Error).message}`);\n }\n\n const videoPackets = videoStream ? packets[videoStream.index] ?? [] : [];\n const audioPackets = audioStream ? packets[audioStream.index] ?? [] : [];\n\n // Feed video packets\n if (videoSource) {\n for (const pkt of videoPackets) {\n sanitizePacketTimestamp(pkt, () => {\n const ts = syntheticVideoUs;\n syntheticVideoUs += videoFrameStepUs;\n return ts;\n }, videoTimeBase);\n\n // libav demuxes AVI/ASF/FLV H.264 as Annex B (start-code framed),\n // but mediabunny's fMP4 muxer expects AVCC (length-prefixed). Convert\n // on the fly. The check is cheap: isAnnexB reads 4 bytes at the head.\n if (videoTrackInfo && (videoTrackInfo.codec === \"h264\" || videoTrackInfo.codec === \"h265\") && isAnnexB(pkt.data)) {\n pkt.data = annexBToAvcc(pkt.data);\n }\n\n const mbPacket = libavPacketToMediAbunny(mb, pkt);\n await videoSource.add(\n mbPacket,\n firstVideoMeta ? { decoderConfig: buildVideoDecoderConfig(videoTrackInfo!) } : undefined,\n );\n firstVideoMeta = false;\n }\n }\n\n // Feed audio packets\n if (audioSource) {\n for (const pkt of audioPackets) {\n sanitizePacketTimestamp(pkt, () => {\n const ts = syntheticAudioUs;\n const sampleRate = audioTrackInfo?.sampleRate ?? 44100;\n syntheticAudioUs += Math.round(1024 * 1_000_000 / sampleRate);\n return ts;\n }, audioTimeBase);\n\n const mbPacket = libavPacketToMediAbunny(mb, pkt);\n await audioSource.add(\n mbPacket,\n firstAudioMeta ? { decoderConfig: buildAudioDecoderConfig(audioTrackInfo!) } : undefined,\n );\n firstAudioMeta = false;\n }\n }\n\n totalPackets += videoPackets.length + audioPackets.length;\n\n // Report progress\n if (options.onProgress && durationUs > 0) {\n const lastVideoTs = videoPackets.length > 0 ? videoPackets[videoPackets.length - 1].pts ?? 0 : 0;\n const lastAudioTs = audioPackets.length > 0 ? audioPackets[audioPackets.length - 1].pts ?? 0 : 0;\n const currentUs = Math.max(lastVideoTs, lastAudioTs);\n const percent = Math.min(99, (currentUs / durationUs) * 100);\n options.onProgress({ percent, bytesWritten: 0 });\n }\n\n if (readErr === libav.AVERROR_EOF) break;\n if (readErr && readErr !== 0 && readErr !== -libav.EAGAIN) {\n console.warn(\"[avbridge] remux: ff_read_frame_multi returned\", readErr);\n break;\n }\n }\n\n await output.finalize();\n\n // Cleanup libav resources\n try { await libav.av_packet_free?.(readPkt); } catch { /* ignore */ }\n try { await libav.avformat_close_input_js(fmt_ctx); } catch { /* ignore */ }\n\n if (!target.buffer) {\n throw new Error(\"Remux failed: mediabunny produced no output buffer.\");\n }\n\n const mimeType = mimeForFormat(outputFormat);\n const blob = new Blob([target.buffer], { type: mimeType });\n const outputFilename = generateFilename(ctx.name, outputFormat);\n\n options.onProgress?.({ percent: 100, bytesWritten: blob.size });\n\n return {\n blob,\n mimeType,\n container: outputFormat,\n videoCodec: videoTrackInfo?.codec,\n audioCodec: audioTrackInfo?.codec,\n duration: ctx.duration,\n filename: outputFilename,\n };\n}\n\n// ── Helpers ─────────────────────────────────────────────────────────────────\n\n/** @internal Exported for use by transcode(). */\nexport function createOutputFormat(\n mb: typeof import(\"mediabunny\"),\n format: OutputFormat,\n) {\n switch (format) {\n case \"mp4\": return new mb.Mp4OutputFormat({ fastStart: \"in-memory\" });\n case \"webm\": return new mb.WebMOutputFormat();\n case \"mkv\": return new mb.MkvOutputFormat();\n default: return new mb.Mp4OutputFormat({ fastStart: \"in-memory\" });\n }\n}\n\n/** @internal Exported for testing. */\nexport function mimeForFormat(format: OutputFormat): string {\n switch (format) {\n case \"mp4\": return \"video/mp4\";\n case \"webm\": return \"video/webm\";\n case \"mkv\": return \"video/x-matroska\";\n default: return \"application/octet-stream\";\n }\n}\n\n/** @internal Exported for testing. */\nexport function generateFilename(originalName: string | undefined, format: OutputFormat): string {\n const ext = format === \"mkv\" ? \"mkv\" : format;\n if (!originalName) return `output.${ext}`;\n const base = originalName.replace(/\\.[^.]+$/, \"\");\n return `${base}.${ext}`;\n}\n\n/** Sequence counter for decode-order numbering in mediabunny packets. */\nlet _seqCounter = 0;\n\n/**\n * Convert a libav packet to a mediabunny EncodedPacket.\n * Timestamps from libav are in microseconds (after sanitization); mediabunny wants seconds.\n */\nfunction libavPacketToMediAbunny(\n mb: typeof import(\"mediabunny\"),\n pkt: LibavPacket,\n): InstanceType<typeof mb.EncodedPacket> {\n const KEY_FRAME_FLAG = 0x0001;\n const timestampSec = (pkt.pts ?? 0) / 1_000_000;\n const durationSec = (pkt.duration ?? 0) / 1_000_000;\n const type = (pkt.flags & KEY_FRAME_FLAG) ? \"key\" as const : \"delta\" as const;\n return new mb.EncodedPacket(pkt.data, type, timestampSec, durationSec, _seqCounter++);\n}\n\nfunction buildVideoDecoderConfig(track: { codec: string; width: number; height: number; codecString?: string }) {\n return {\n codec: track.codecString ?? track.codec,\n codedWidth: track.width,\n codedHeight: track.height,\n };\n}\n\nfunction buildAudioDecoderConfig(track: { codec: string; channels: number; sampleRate: number; codecString?: string }) {\n return {\n codec: track.codecString ?? track.codec,\n numberOfChannels: track.channels,\n sampleRate: track.sampleRate,\n };\n}\n\n// ── Structural types ────────────────────────────────────────────────────────\n\ninterface LibavPacket {\n data: Uint8Array;\n pts: number;\n ptshi?: number;\n duration?: number;\n durationhi?: number;\n flags: number;\n stream_index: number;\n time_base_num?: number;\n time_base_den?: number;\n}\n\ninterface LibavStream {\n index: number;\n codec_type: number;\n codec_id: number;\n codecpar: number;\n time_base_num?: number;\n time_base_den?: number;\n}\n\ninterface LibavRuntime {\n AVMEDIA_TYPE_VIDEO: number;\n AVMEDIA_TYPE_AUDIO: number;\n AVERROR_EOF: number;\n EAGAIN: number;\n\n mkreadaheadfile(name: string, blob: Blob): Promise<void>;\n unlinkreadaheadfile(name: string): Promise<void>;\n ff_init_demuxer_file(name: string): Promise<[number, LibavStream[]]>;\n ff_read_frame_multi(\n fmt_ctx: number,\n pkt: number,\n opts?: { limit?: number },\n ): Promise<[number, Record<number, LibavPacket[]>]>;\n av_packet_alloc(): Promise<number>;\n av_packet_free?(pkt: number): Promise<void>;\n avformat_close_input_js(ctx: number): Promise<void>;\n}\n"]}
|
|
1
|
+
{"version":3,"sources":["../src/strategies/remux/annexb.ts","../src/convert/remux.ts"],"names":["probe","avbridgeVideoToMediabunny","avbridgeAudioToMediabunny","buildMediabunnySourceFromInput","normalizeSource","prepareLibavInput","sanitizePacketTimestamp"],"mappings":"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","file":"chunk-OTFS7DC4.cjs","sourcesContent":["/**\n * H.264/HEVC bitstream conversion helpers.\n *\n * Demuxers from MP4-family containers (mediabunny) hand us packets in **AVCC**\n * format: each NAL unit prefixed with a 4-byte big-endian length.\n *\n * Demuxers from elementary-stream/AVI/TS hand us **Annex B**: NAL units\n * separated by `00 00 00 01` (or `00 00 01`) start codes.\n *\n * MSE expects AVCC inside fragmented MP4. So when the source side emits Annex\n * B, we need to convert before muxing. Going the other way (AVCC → Annex B) is\n * useful for feeding `VideoDecoder` configured with `description` omitted.\n */\n\nconst START_CODE_4 = new Uint8Array([0, 0, 0, 1]);\n\n/** True if the bytes look like Annex B (start with `00 00 00 01` or `00 00 01`). */\nexport function isAnnexB(bytes: Uint8Array): boolean {\n if (bytes.length < 3) return false;\n if (bytes[0] === 0 && bytes[1] === 0 && bytes[2] === 1) return true;\n if (bytes.length >= 4 && bytes[0] === 0 && bytes[1] === 0 && bytes[2] === 0 && bytes[3] === 1) return true;\n return false;\n}\n\n/**\n * Walk an Annex B byte stream and yield each NAL unit (without start code).\n * This is the standard byte-by-byte scan; no SIMD tricks because the typical\n * frame is small.\n */\nexport function* iterateAnnexBNalus(bytes: Uint8Array): Generator<Uint8Array> {\n const length = bytes.length;\n let i = 0;\n let nalStart = -1;\n\n while (i < length) {\n // Look for start code at position i\n let scLen = 0;\n if (i + 3 < length && bytes[i] === 0 && bytes[i + 1] === 0 && bytes[i + 2] === 0 && bytes[i + 3] === 1) {\n scLen = 4;\n } else if (i + 2 < length && bytes[i] === 0 && bytes[i + 1] === 0 && bytes[i + 2] === 1) {\n scLen = 3;\n }\n\n if (scLen > 0) {\n if (nalStart >= 0) {\n yield bytes.subarray(nalStart, i);\n }\n nalStart = i + scLen;\n i += scLen;\n } else {\n i += 1;\n }\n }\n\n if (nalStart >= 0 && nalStart < length) {\n yield bytes.subarray(nalStart, length);\n }\n}\n\n/**\n * Convert an Annex B byte stream to AVCC. Each NALU is prefixed with its\n * 4-byte big-endian length.\n */\nexport function annexBToAvcc(annexB: Uint8Array): Uint8Array {\n const nalus: Uint8Array[] = [];\n let total = 0;\n for (const nal of iterateAnnexBNalus(annexB)) {\n nalus.push(nal);\n total += 4 + nal.length;\n }\n const out = new Uint8Array(total);\n let off = 0;\n for (const nal of nalus) {\n const len = nal.length;\n out[off++] = (len >>> 24) & 0xff;\n out[off++] = (len >>> 16) & 0xff;\n out[off++] = (len >>> 8) & 0xff;\n out[off++] = len & 0xff;\n out.set(nal, off);\n off += len;\n }\n return out;\n}\n\n/**\n * Convert AVCC (4-byte length-prefixed) NALUs to Annex B. Each NALU is\n * prefixed with `00 00 00 01`.\n */\nexport function avccToAnnexB(avcc: Uint8Array): Uint8Array {\n const out: Uint8Array[] = [];\n let total = 0;\n let i = 0;\n while (i + 4 <= avcc.length) {\n const len =\n (avcc[i] << 24) | (avcc[i + 1] << 16) | (avcc[i + 2] << 8) | avcc[i + 3];\n i += 4;\n if (i + len > avcc.length) {\n throw new Error(`avccToAnnexB: NAL length ${len} overflows buffer at offset ${i}`);\n }\n out.push(START_CODE_4);\n out.push(avcc.subarray(i, i + len));\n total += 4 + len;\n i += len;\n }\n const merged = new Uint8Array(total);\n let off = 0;\n for (const chunk of out) {\n merged.set(chunk, off);\n off += chunk.length;\n }\n return merged;\n}\n","/**\n * Standalone remux function: repackage media into a modern container without\n * re-encoding. Input can be any format avbridge can probe; output is a\n * finalized downloadable file (MP4, WebM, or MKV).\n *\n * Two internal paths:\n * - **Path A** (mediabunny-readable containers): wraps mediabunny's Conversion\n * class for MP4/MKV/WebM/OGG/MOV/WAV/MP3/FLAC/ADTS sources.\n * - **Path B** (AVI/ASF/FLV): libav.js demux + mediabunny mux via manual\n * packet pump. Lazy-loads libav.js — zero cost if unused.\n */\n\nimport { probe } from \"../probe/index.js\";\nimport { isAnnexB, annexBToAvcc } from \"../strategies/remux/annexb.js\";\nimport {\n avbridgeVideoToMediabunny,\n avbridgeAudioToMediabunny,\n buildMediabunnySourceFromInput,\n} from \"../probe/mediabunny.js\";\nimport { normalizeSource } from \"../util/source.js\";\nimport { sanitizePacketTimestamp } from \"../util/libav-demux.js\";\nimport { prepareLibavInput, type LibavInputHandle } from \"../util/libav-http-reader.js\";\nimport type {\n MediaInput,\n MediaContext,\n ConvertOptions,\n ConvertResult,\n OutputFormat,\n} from \"../types.js\";\n\n/** Containers mediabunny can read (and therefore use Conversion for). */\nconst MEDIABUNNY_CONTAINERS = new Set([\n \"mp4\", \"mov\", \"mkv\", \"webm\", \"ogg\", \"wav\", \"mp3\", \"flac\", \"adts\",\n]);\n\n/**\n * Remux a media source into a modern container format without re-encoding.\n *\n * @throws When the source codecs cannot be remuxed (e.g. WMV3 — use `transcode()` instead).\n * @throws When an AVI/ASF/FLV source is provided but libav.js is not installed.\n */\nexport async function remux(\n source: MediaInput,\n options: ConvertOptions = {},\n): Promise<ConvertResult> {\n const outputFormat = options.outputFormat ?? \"mp4\";\n options.signal?.throwIfAborted();\n\n // Probe the source\n const ctx = await probe(source);\n options.signal?.throwIfAborted();\n\n // Validate remux eligibility: all codecs must map to mediabunny output codecs\n validateRemuxEligibility(ctx, options.strict ?? false);\n\n // Route to the appropriate path\n if (MEDIABUNNY_CONTAINERS.has(ctx.container)) {\n return remuxViaMediAbunny(ctx, outputFormat, options);\n }\n return remuxViaLibav(ctx, outputFormat, options);\n}\n\n// ── Eligibility validation ──────────────────────────────────────────────────\n\n/** @internal Exported for testing. */\nexport function validateRemuxEligibility(ctx: MediaContext, strict: boolean): void {\n const video = ctx.videoTracks[0];\n const audio = ctx.audioTracks[0];\n\n if (video) {\n const mbCodec = avbridgeVideoToMediabunny(video.codec);\n if (!mbCodec) {\n throw new Error(\n `Cannot remux: video codec \"${video.codec}\" is not supported for remuxing. ` +\n `Use transcode() to re-encode to a modern codec.`,\n );\n }\n }\n\n if (audio) {\n const mbCodec = avbridgeAudioToMediabunny(audio.codec);\n if (!mbCodec) {\n throw new Error(\n `Cannot remux: audio codec \"${audio.codec}\" is not supported for remuxing. ` +\n `Use transcode() to re-encode to a modern codec.`,\n );\n }\n }\n\n if (strict && video?.codec === \"h264\" && audio?.codec === \"mp3\") {\n throw new Error(\n `Cannot remux in strict mode: H.264 + MP3 is a best-effort combination ` +\n `that may produce playback issues in some browsers. ` +\n `Set strict: false to allow, or use transcode() to re-encode audio to AAC.`,\n );\n }\n\n if (!video && !audio) {\n throw new Error(\"Cannot remux: source has no video or audio tracks.\");\n }\n}\n\n// ── Path A: mediabunny Conversion ───────────────────────────────────────────\n\nasync function remuxViaMediAbunny(\n ctx: MediaContext,\n outputFormat: OutputFormat,\n options: ConvertOptions,\n): Promise<ConvertResult> {\n const mb = await import(\"mediabunny\");\n\n const input = new mb.Input({\n source: await buildMediabunnySourceFromInput(mb, ctx.source),\n formats: mb.ALL_FORMATS,\n });\n\n const target = new mb.BufferTarget();\n const output = new mb.Output({\n format: createOutputFormat(mb, outputFormat),\n target,\n });\n\n const conversion = await mb.Conversion.init({\n input,\n output,\n showWarnings: false,\n });\n\n if (!conversion.isValid) {\n const reasons = conversion.discardedTracks\n .map((d) => `${d.track.type} track discarded: ${d.reason}`)\n .join(\"; \");\n throw new Error(`Cannot remux: mediabunny rejected the conversion. ${reasons}`);\n }\n\n // Wire progress\n if (options.onProgress) {\n const onProgress = options.onProgress;\n conversion.onProgress = (p) => {\n onProgress({ percent: p * 100, bytesWritten: 0 });\n };\n }\n\n // Wire cancellation\n let abortHandler: (() => void) | undefined;\n if (options.signal) {\n options.signal.throwIfAborted();\n abortHandler = () => void conversion.cancel();\n options.signal.addEventListener(\"abort\", abortHandler, { once: true });\n }\n\n try {\n await conversion.execute();\n } finally {\n if (abortHandler && options.signal) {\n options.signal.removeEventListener(\"abort\", abortHandler);\n }\n }\n\n if (!target.buffer) {\n throw new Error(\"Remux failed: mediabunny produced no output buffer.\");\n }\n\n const mimeType = mimeForFormat(outputFormat);\n const blob = new Blob([target.buffer], { type: mimeType });\n const filename = generateFilename(ctx.name, outputFormat);\n\n options.onProgress?.({ percent: 100, bytesWritten: blob.size });\n\n return {\n blob,\n mimeType,\n container: outputFormat,\n videoCodec: ctx.videoTracks[0]?.codec,\n audioCodec: ctx.audioTracks[0]?.codec,\n duration: ctx.duration,\n filename,\n };\n}\n\n// ── Path B: libav.js demux + mediabunny mux (AVI/ASF/FLV) ──────────────────\n\nasync function remuxViaLibav(\n ctx: MediaContext,\n outputFormat: OutputFormat,\n options: ConvertOptions,\n): Promise<ConvertResult> {\n // Lazy-load libav\n let loadLibav: typeof import(\"../strategies/fallback/libav-loader.js\").loadLibav;\n let pickLibavVariant: typeof import(\"../strategies/fallback/variant-routing.js\").pickLibavVariant;\n try {\n const loader = await import(\"../strategies/fallback/libav-loader.js\");\n const routing = await import(\"../strategies/fallback/variant-routing.js\");\n loadLibav = loader.loadLibav;\n pickLibavVariant = routing.pickLibavVariant;\n } catch {\n throw new Error(\n `Cannot remux ${ctx.container.toUpperCase()} source: libav.js is not available. ` +\n `Install @libav.js/variant-webcodecs and libavjs-webcodecs-bridge, ` +\n `or build the custom avbridge variant with scripts/build-libav.sh.`,\n );\n }\n\n const variant = pickLibavVariant(ctx);\n const libav = await loadLibav(variant) as unknown as LibavRuntime;\n\n // For Blob/File inputs, libav reads from an in-memory readahead file.\n // For URL inputs, libav demuxes via HTTP Range requests through the\n // block reader — no full download.\n const normalized = await normalizeSource(ctx.source);\n const filename = ctx.name ?? `remux-input-${Date.now()}`;\n const handle: LibavInputHandle = await prepareLibavInput(libav as unknown as Parameters<typeof prepareLibavInput>[0], filename, normalized);\n\n try {\n return await doLibavRemux(libav, filename, ctx, outputFormat, options);\n } finally {\n await handle.detach().catch(() => {});\n }\n}\n\nasync function doLibavRemux(\n libav: LibavRuntime,\n filename: string,\n ctx: MediaContext,\n outputFormat: OutputFormat,\n options: ConvertOptions,\n): Promise<ConvertResult> {\n const mb = await import(\"mediabunny\");\n\n const readPkt = await libav.av_packet_alloc();\n const [fmt_ctx, streams] = await libav.ff_init_demuxer_file(filename);\n const videoStream = streams.find((s) => s.codec_type === libav.AVMEDIA_TYPE_VIDEO) ?? null;\n const audioStream = streams.find((s) => s.codec_type === libav.AVMEDIA_TYPE_AUDIO) ?? null;\n\n // Map codecs to mediabunny output\n const videoTrackInfo = ctx.videoTracks[0];\n const audioTrackInfo = ctx.audioTracks[0];\n const mbVideoCodec = videoTrackInfo ? avbridgeVideoToMediabunny(videoTrackInfo.codec) : null;\n const mbAudioCodec = audioTrackInfo ? avbridgeAudioToMediabunny(audioTrackInfo.codec) : null;\n\n // Set up mediabunny output with BufferTarget\n const target = new mb.BufferTarget();\n const output = new mb.Output({\n format: createOutputFormat(mb, outputFormat),\n target,\n });\n\n let videoSource: InstanceType<typeof mb.EncodedVideoPacketSource> | null = null;\n let audioSource: InstanceType<typeof mb.EncodedAudioPacketSource> | null = null;\n\n if (mbVideoCodec && videoStream) {\n videoSource = new mb.EncodedVideoPacketSource(mbVideoCodec);\n output.addVideoTrack(videoSource);\n }\n if (mbAudioCodec && audioStream) {\n type AudioCodecArg = ConstructorParameters<typeof mb.EncodedAudioPacketSource>[0];\n audioSource = new mb.EncodedAudioPacketSource(mbAudioCodec as AudioCodecArg);\n output.addAudioTrack(audioSource);\n }\n\n await output.start();\n\n // Timestamp tracking for synthetic timestamps\n const videoFps = videoTrackInfo?.fps && videoTrackInfo.fps > 0 ? videoTrackInfo.fps : 30;\n const videoFrameStepUs = Math.max(1, Math.round(1_000_000 / videoFps));\n let syntheticVideoUs = 0;\n let syntheticAudioUs = 0;\n\n const videoTimeBase: [number, number] | undefined =\n videoStream?.time_base_num && videoStream?.time_base_den\n ? [videoStream.time_base_num, videoStream.time_base_den]\n : undefined;\n const audioTimeBase: [number, number] | undefined =\n audioStream?.time_base_num && audioStream?.time_base_den\n ? [audioStream.time_base_num, audioStream.time_base_den]\n : undefined;\n\n let totalPackets = 0;\n const durationUs = ctx.duration ? ctx.duration * 1_000_000 : 0;\n let firstVideoMeta = true;\n let firstAudioMeta = true;\n\n // Pump loop: read packets from libav, feed to mediabunny output\n while (true) {\n options.signal?.throwIfAborted();\n\n let readErr: number;\n let packets: Record<number, LibavPacket[]>;\n try {\n [readErr, packets] = await libav.ff_read_frame_multi(fmt_ctx, readPkt, {\n limit: 64 * 1024,\n });\n } catch (err) {\n throw new Error(`libav demux failed: ${(err as Error).message}`);\n }\n\n const videoPackets = videoStream ? packets[videoStream.index] ?? [] : [];\n const audioPackets = audioStream ? packets[audioStream.index] ?? [] : [];\n\n // Feed video packets\n if (videoSource) {\n for (const pkt of videoPackets) {\n sanitizePacketTimestamp(pkt, () => {\n const ts = syntheticVideoUs;\n syntheticVideoUs += videoFrameStepUs;\n return ts;\n }, videoTimeBase);\n\n // libav demuxes AVI/ASF/FLV H.264 as Annex B (start-code framed),\n // but mediabunny's fMP4 muxer expects AVCC (length-prefixed). Convert\n // on the fly. The check is cheap: isAnnexB reads 4 bytes at the head.\n if (videoTrackInfo && (videoTrackInfo.codec === \"h264\" || videoTrackInfo.codec === \"h265\") && isAnnexB(pkt.data)) {\n pkt.data = annexBToAvcc(pkt.data);\n }\n\n const mbPacket = libavPacketToMediAbunny(mb, pkt);\n await videoSource.add(\n mbPacket,\n firstVideoMeta ? { decoderConfig: buildVideoDecoderConfig(videoTrackInfo!) } : undefined,\n );\n firstVideoMeta = false;\n }\n }\n\n // Feed audio packets\n if (audioSource) {\n for (const pkt of audioPackets) {\n sanitizePacketTimestamp(pkt, () => {\n const ts = syntheticAudioUs;\n const sampleRate = audioTrackInfo?.sampleRate ?? 44100;\n syntheticAudioUs += Math.round(1024 * 1_000_000 / sampleRate);\n return ts;\n }, audioTimeBase);\n\n const mbPacket = libavPacketToMediAbunny(mb, pkt);\n await audioSource.add(\n mbPacket,\n firstAudioMeta ? { decoderConfig: buildAudioDecoderConfig(audioTrackInfo!) } : undefined,\n );\n firstAudioMeta = false;\n }\n }\n\n totalPackets += videoPackets.length + audioPackets.length;\n\n // Report progress\n if (options.onProgress && durationUs > 0) {\n const lastVideoTs = videoPackets.length > 0 ? videoPackets[videoPackets.length - 1].pts ?? 0 : 0;\n const lastAudioTs = audioPackets.length > 0 ? audioPackets[audioPackets.length - 1].pts ?? 0 : 0;\n const currentUs = Math.max(lastVideoTs, lastAudioTs);\n const percent = Math.min(99, (currentUs / durationUs) * 100);\n options.onProgress({ percent, bytesWritten: 0 });\n }\n\n if (readErr === libav.AVERROR_EOF) break;\n if (readErr && readErr !== 0 && readErr !== -libav.EAGAIN) {\n console.warn(\"[avbridge] remux: ff_read_frame_multi returned\", readErr);\n break;\n }\n }\n\n await output.finalize();\n\n // Cleanup libav resources\n try { await libav.av_packet_free?.(readPkt); } catch { /* ignore */ }\n try { await libav.avformat_close_input_js(fmt_ctx); } catch { /* ignore */ }\n\n if (!target.buffer) {\n throw new Error(\"Remux failed: mediabunny produced no output buffer.\");\n }\n\n const mimeType = mimeForFormat(outputFormat);\n const blob = new Blob([target.buffer], { type: mimeType });\n const outputFilename = generateFilename(ctx.name, outputFormat);\n\n options.onProgress?.({ percent: 100, bytesWritten: blob.size });\n\n return {\n blob,\n mimeType,\n container: outputFormat,\n videoCodec: videoTrackInfo?.codec,\n audioCodec: audioTrackInfo?.codec,\n duration: ctx.duration,\n filename: outputFilename,\n };\n}\n\n// ── Helpers ─────────────────────────────────────────────────────────────────\n\n/** @internal Exported for use by transcode(). */\nexport function createOutputFormat(\n mb: typeof import(\"mediabunny\"),\n format: OutputFormat,\n) {\n switch (format) {\n case \"mp4\": return new mb.Mp4OutputFormat({ fastStart: \"in-memory\" });\n case \"webm\": return new mb.WebMOutputFormat();\n case \"mkv\": return new mb.MkvOutputFormat();\n default: return new mb.Mp4OutputFormat({ fastStart: \"in-memory\" });\n }\n}\n\n/** @internal Exported for testing. */\nexport function mimeForFormat(format: OutputFormat): string {\n switch (format) {\n case \"mp4\": return \"video/mp4\";\n case \"webm\": return \"video/webm\";\n case \"mkv\": return \"video/x-matroska\";\n default: return \"application/octet-stream\";\n }\n}\n\n/** @internal Exported for testing. */\nexport function generateFilename(originalName: string | undefined, format: OutputFormat): string {\n const ext = format === \"mkv\" ? \"mkv\" : format;\n if (!originalName) return `output.${ext}`;\n const base = originalName.replace(/\\.[^.]+$/, \"\");\n return `${base}.${ext}`;\n}\n\n/** Sequence counter for decode-order numbering in mediabunny packets. */\nlet _seqCounter = 0;\n\n/**\n * Convert a libav packet to a mediabunny EncodedPacket.\n * Timestamps from libav are in microseconds (after sanitization); mediabunny wants seconds.\n */\nfunction libavPacketToMediAbunny(\n mb: typeof import(\"mediabunny\"),\n pkt: LibavPacket,\n): InstanceType<typeof mb.EncodedPacket> {\n const KEY_FRAME_FLAG = 0x0001;\n const timestampSec = (pkt.pts ?? 0) / 1_000_000;\n const durationSec = (pkt.duration ?? 0) / 1_000_000;\n const type = (pkt.flags & KEY_FRAME_FLAG) ? \"key\" as const : \"delta\" as const;\n return new mb.EncodedPacket(pkt.data, type, timestampSec, durationSec, _seqCounter++);\n}\n\nfunction buildVideoDecoderConfig(track: { codec: string; width: number; height: number; codecString?: string }) {\n return {\n codec: track.codecString ?? track.codec,\n codedWidth: track.width,\n codedHeight: track.height,\n };\n}\n\nfunction buildAudioDecoderConfig(track: { codec: string; channels: number; sampleRate: number; codecString?: string }) {\n return {\n codec: track.codecString ?? track.codec,\n numberOfChannels: track.channels,\n sampleRate: track.sampleRate,\n };\n}\n\n// ── Structural types ────────────────────────────────────────────────────────\n\ninterface LibavPacket {\n data: Uint8Array;\n pts: number;\n ptshi?: number;\n duration?: number;\n durationhi?: number;\n flags: number;\n stream_index: number;\n time_base_num?: number;\n time_base_den?: number;\n}\n\ninterface LibavStream {\n index: number;\n codec_type: number;\n codec_id: number;\n codecpar: number;\n time_base_num?: number;\n time_base_den?: number;\n}\n\ninterface LibavRuntime {\n AVMEDIA_TYPE_VIDEO: number;\n AVMEDIA_TYPE_AUDIO: number;\n AVERROR_EOF: number;\n EAGAIN: number;\n\n mkreadaheadfile(name: string, blob: Blob): Promise<void>;\n unlinkreadaheadfile(name: string): Promise<void>;\n ff_init_demuxer_file(name: string): Promise<[number, LibavStream[]]>;\n ff_read_frame_multi(\n fmt_ctx: number,\n pkt: number,\n opts?: { limit?: number },\n ): Promise<[number, Record<number, LibavPacket[]>]>;\n av_packet_alloc(): Promise<number>;\n av_packet_free?(pkt: number): Promise<void>;\n avformat_close_input_js(ctx: number): Promise<void>;\n}\n"]}
|
package/dist/element-browser.js
CHANGED
|
@@ -30030,6 +30030,12 @@ function ffmpegToAvbridgeVideo(name) {
|
|
|
30030
30030
|
return "rv30";
|
|
30031
30031
|
case "rv40":
|
|
30032
30032
|
return "rv40";
|
|
30033
|
+
case "dvvideo":
|
|
30034
|
+
return "dv";
|
|
30035
|
+
// DV / DVCPRO (camcorder, MiniDV)
|
|
30036
|
+
case "hq_hqa":
|
|
30037
|
+
return "hq_hqa";
|
|
30038
|
+
// Canopus HQ / HQA (Grass Valley)
|
|
30033
30039
|
default:
|
|
30034
30040
|
return name;
|
|
30035
30041
|
}
|
|
@@ -31564,7 +31570,13 @@ var FALLBACK_VIDEO_CODECS = /* @__PURE__ */ new Set([
|
|
|
31564
31570
|
"rv40",
|
|
31565
31571
|
"mpeg2",
|
|
31566
31572
|
"mpeg1",
|
|
31567
|
-
"theora"
|
|
31573
|
+
"theora",
|
|
31574
|
+
"dv",
|
|
31575
|
+
"hq_hqa",
|
|
31576
|
+
"rawvideo",
|
|
31577
|
+
"qtrle",
|
|
31578
|
+
"png",
|
|
31579
|
+
"vp6f"
|
|
31568
31580
|
]);
|
|
31569
31581
|
var FALLBACK_AUDIO_CODECS = /* @__PURE__ */ new Set([
|
|
31570
31582
|
"wmav2",
|
|
@@ -32401,6 +32413,12 @@ async function createRemuxSession(context, video) {
|
|
|
32401
32413
|
}
|
|
32402
32414
|
const wasPlaying = !video.paused;
|
|
32403
32415
|
await pipeline.seek(time, wasPlaying || wantPlay);
|
|
32416
|
+
queueMicrotask(() => {
|
|
32417
|
+
try {
|
|
32418
|
+
video.dispatchEvent(new Event("seeked"));
|
|
32419
|
+
} catch {
|
|
32420
|
+
}
|
|
32421
|
+
});
|
|
32404
32422
|
},
|
|
32405
32423
|
async setAudioTrack(id) {
|
|
32406
32424
|
if (!context.audioTracks.some((t) => t.id === id)) {
|
|
@@ -32790,6 +32808,10 @@ var AudioOutput = class {
|
|
|
32790
32808
|
_volume = 1;
|
|
32791
32809
|
/** User-set muted flag. When true, gain is forced to 0. */
|
|
32792
32810
|
_muted = false;
|
|
32811
|
+
/** Playback rate. Scales the media clock and each AudioBufferSourceNode's
|
|
32812
|
+
* playbackRate so audio pitches up/down accordingly (same as native
|
|
32813
|
+
* <video>.playbackRate). Default 1. */
|
|
32814
|
+
_rate = 1;
|
|
32793
32815
|
constructor() {
|
|
32794
32816
|
this.ctx = new AudioContext();
|
|
32795
32817
|
this.gain = this.ctx.createGain();
|
|
@@ -32811,6 +32833,20 @@ var AudioOutput = class {
|
|
|
32811
32833
|
getMuted() {
|
|
32812
32834
|
return this._muted;
|
|
32813
32835
|
}
|
|
32836
|
+
/** Set playback rate. Scales the media clock and pitches audio output
|
|
32837
|
+
* (same as native <video>.playbackRate — speed without pitch correction).
|
|
32838
|
+
* Rebases the anchor so the clock transition is seamless. */
|
|
32839
|
+
setPlaybackRate(rate) {
|
|
32840
|
+
if (rate === this._rate) return;
|
|
32841
|
+
const t = this.now();
|
|
32842
|
+
this.mediaTimeOfAnchor = t;
|
|
32843
|
+
this.ctxTimeAtAnchor = this.ctx.currentTime;
|
|
32844
|
+
this.wallAnchorMs = performance.now();
|
|
32845
|
+
this._rate = rate;
|
|
32846
|
+
}
|
|
32847
|
+
getPlaybackRate() {
|
|
32848
|
+
return this._rate;
|
|
32849
|
+
}
|
|
32814
32850
|
applyGain() {
|
|
32815
32851
|
const target = this._muted ? 0 : this._volume;
|
|
32816
32852
|
try {
|
|
@@ -32831,12 +32867,12 @@ var AudioOutput = class {
|
|
|
32831
32867
|
now() {
|
|
32832
32868
|
if (this.noAudio) {
|
|
32833
32869
|
if (this.state === "playing") {
|
|
32834
|
-
return this.mediaTimeOfAnchor + (performance.now() - this.wallAnchorMs) / 1e3;
|
|
32870
|
+
return this.mediaTimeOfAnchor + (performance.now() - this.wallAnchorMs) / 1e3 * this._rate;
|
|
32835
32871
|
}
|
|
32836
32872
|
return this.mediaTimeOfAnchor;
|
|
32837
32873
|
}
|
|
32838
32874
|
if (this.state === "playing") {
|
|
32839
|
-
return this.mediaTimeOfAnchor + (this.ctx.currentTime - this.ctxTimeAtAnchor);
|
|
32875
|
+
return this.mediaTimeOfAnchor + (this.ctx.currentTime - this.ctxTimeAtAnchor) * this._rate;
|
|
32840
32876
|
}
|
|
32841
32877
|
return this.mediaTimeOfAnchor;
|
|
32842
32878
|
}
|
|
@@ -32888,7 +32924,8 @@ var AudioOutput = class {
|
|
|
32888
32924
|
const node3 = this.ctx.createBufferSource();
|
|
32889
32925
|
node3.buffer = buffer;
|
|
32890
32926
|
node3.connect(this.gain);
|
|
32891
|
-
|
|
32927
|
+
if (this._rate !== 1) node3.playbackRate.value = this._rate;
|
|
32928
|
+
let ctxStart = this.ctxTimeAtAnchor + (this.mediaTimeOfNext - this.mediaTimeOfAnchor) / this._rate;
|
|
32892
32929
|
if (ctxStart < this.ctx.currentTime) {
|
|
32893
32930
|
this.ctxTimeAtAnchor = this.ctx.currentTime;
|
|
32894
32931
|
this.mediaTimeOfAnchor = this.mediaTimeOfNext;
|
|
@@ -33042,6 +33079,17 @@ function sanitizePacketTimestamp(pkt, nextUs, fallbackTimeBase) {
|
|
|
33042
33079
|
pkt.time_base_num = 1;
|
|
33043
33080
|
pkt.time_base_den = 1e6;
|
|
33044
33081
|
}
|
|
33082
|
+
function packetPtsSec(pkt, timeBase) {
|
|
33083
|
+
const lo = pkt.pts ?? 0;
|
|
33084
|
+
const hi = pkt.ptshi ?? 0;
|
|
33085
|
+
const isInvalid = hi === -2147483648 && lo === 0 || !Number.isFinite(lo);
|
|
33086
|
+
if (isInvalid) return null;
|
|
33087
|
+
const tb = timeBase ?? [1, 1e6];
|
|
33088
|
+
if (!tb[0] || !tb[1]) return null;
|
|
33089
|
+
const pts64 = hi * 4294967296 + lo;
|
|
33090
|
+
const sec = pts64 * tb[0] / tb[1];
|
|
33091
|
+
return Number.isFinite(sec) ? sec : null;
|
|
33092
|
+
}
|
|
33045
33093
|
var AV_SAMPLE_FMT_U8 = 0;
|
|
33046
33094
|
var AV_SAMPLE_FMT_S16 = 1;
|
|
33047
33095
|
var AV_SAMPLE_FMT_S32 = 2;
|
|
@@ -33302,6 +33350,7 @@ async function startHybridDecoder(opts) {
|
|
|
33302
33350
|
let videoFramesDecoded = 0;
|
|
33303
33351
|
let audioFramesDecoded = 0;
|
|
33304
33352
|
let videoChunksFed = 0;
|
|
33353
|
+
let bufferedUntilSec = 0;
|
|
33305
33354
|
let syntheticVideoUs = 0;
|
|
33306
33355
|
let syntheticAudioUs = 0;
|
|
33307
33356
|
const videoTrackInfo = opts.context.videoTracks.find((t) => t.id === videoStream?.index);
|
|
@@ -33322,6 +33371,18 @@ async function startHybridDecoder(opts) {
|
|
|
33322
33371
|
if (myToken !== pumpToken || destroyed) return;
|
|
33323
33372
|
const videoPackets = videoStream ? packets[videoStream.index] : void 0;
|
|
33324
33373
|
const audioPackets = audioStream ? packets[audioStream.index] : void 0;
|
|
33374
|
+
if (videoPackets && videoTimeBase) {
|
|
33375
|
+
for (const pkt of videoPackets) {
|
|
33376
|
+
const sec = packetPtsSec(pkt, videoTimeBase);
|
|
33377
|
+
if (sec != null && sec > bufferedUntilSec) bufferedUntilSec = sec;
|
|
33378
|
+
}
|
|
33379
|
+
}
|
|
33380
|
+
if (audioPackets && audioTimeBase) {
|
|
33381
|
+
for (const pkt of audioPackets) {
|
|
33382
|
+
const sec = packetPtsSec(pkt, audioTimeBase);
|
|
33383
|
+
if (sec != null && sec > bufferedUntilSec) bufferedUntilSec = sec;
|
|
33384
|
+
}
|
|
33385
|
+
}
|
|
33325
33386
|
if (audioDec && audioPackets && audioPackets.length > 0) {
|
|
33326
33387
|
await decodeAudioBatch(audioPackets, myToken);
|
|
33327
33388
|
}
|
|
@@ -33578,6 +33639,9 @@ async function startHybridDecoder(opts) {
|
|
|
33578
33639
|
(err) => console.error("[avbridge] hybrid pump failed (post-seek):", err)
|
|
33579
33640
|
);
|
|
33580
33641
|
},
|
|
33642
|
+
bufferedUntilSec() {
|
|
33643
|
+
return bufferedUntilSec;
|
|
33644
|
+
},
|
|
33581
33645
|
stats() {
|
|
33582
33646
|
return {
|
|
33583
33647
|
decoderType: "webcodecs-hybrid",
|
|
@@ -33693,6 +33757,14 @@ async function createHybridSession(ctx, target, transport) {
|
|
|
33693
33757
|
get: () => ctx.duration ?? NaN
|
|
33694
33758
|
});
|
|
33695
33759
|
}
|
|
33760
|
+
Object.defineProperty(target, "playbackRate", {
|
|
33761
|
+
configurable: true,
|
|
33762
|
+
get: () => audio.getPlaybackRate(),
|
|
33763
|
+
set: (v) => {
|
|
33764
|
+
audio.setPlaybackRate(v);
|
|
33765
|
+
target.dispatchEvent(new Event("ratechange"));
|
|
33766
|
+
}
|
|
33767
|
+
});
|
|
33696
33768
|
Object.defineProperty(target, "readyState", {
|
|
33697
33769
|
configurable: true,
|
|
33698
33770
|
get: () => {
|
|
@@ -33705,6 +33777,13 @@ async function createHybridSession(ctx, target, transport) {
|
|
|
33705
33777
|
configurable: true,
|
|
33706
33778
|
get: () => makeTimeRanges(ctx.duration && Number.isFinite(ctx.duration) && ctx.duration > 0 ? [[0, ctx.duration]] : [])
|
|
33707
33779
|
});
|
|
33780
|
+
Object.defineProperty(target, "buffered", {
|
|
33781
|
+
configurable: true,
|
|
33782
|
+
get: () => {
|
|
33783
|
+
const end = handles.bufferedUntilSec();
|
|
33784
|
+
return makeTimeRanges(end > 0 ? [[0, end]] : []);
|
|
33785
|
+
}
|
|
33786
|
+
});
|
|
33708
33787
|
async function waitForBuffer() {
|
|
33709
33788
|
const start = performance.now();
|
|
33710
33789
|
while (true) {
|
|
@@ -33718,6 +33797,7 @@ async function createHybridSession(ctx, target, transport) {
|
|
|
33718
33797
|
}
|
|
33719
33798
|
async function doSeek(timeSec) {
|
|
33720
33799
|
const wasPlaying = audio.isPlaying();
|
|
33800
|
+
target.dispatchEvent(new Event("seeking"));
|
|
33721
33801
|
await audio.pause().catch(() => {
|
|
33722
33802
|
});
|
|
33723
33803
|
await handles.seek(timeSec).catch(
|
|
@@ -33729,7 +33809,14 @@ async function createHybridSession(ctx, target, transport) {
|
|
|
33729
33809
|
await waitForBuffer();
|
|
33730
33810
|
await audio.start();
|
|
33731
33811
|
}
|
|
33812
|
+
target.dispatchEvent(new Event("seeked"));
|
|
33732
33813
|
}
|
|
33814
|
+
queueMicrotask(() => {
|
|
33815
|
+
try {
|
|
33816
|
+
target.dispatchEvent(new Event("loadedmetadata"));
|
|
33817
|
+
} catch {
|
|
33818
|
+
}
|
|
33819
|
+
});
|
|
33733
33820
|
let fatalErrorHandler = null;
|
|
33734
33821
|
handles.onFatalError((reason) => fatalErrorHandler?.(reason));
|
|
33735
33822
|
return {
|
|
@@ -33788,6 +33875,7 @@ async function createHybridSession(ctx, target, transport) {
|
|
|
33788
33875
|
delete target.muted;
|
|
33789
33876
|
delete target.readyState;
|
|
33790
33877
|
delete target.seekable;
|
|
33878
|
+
delete target.playbackRate;
|
|
33791
33879
|
} catch {
|
|
33792
33880
|
}
|
|
33793
33881
|
},
|
|
@@ -33916,6 +34004,7 @@ async function startDecoder(opts) {
|
|
|
33916
34004
|
let pumpRunning = null;
|
|
33917
34005
|
let packetsRead = 0;
|
|
33918
34006
|
let videoFramesDecoded = 0;
|
|
34007
|
+
let bufferedUntilSec = 0;
|
|
33919
34008
|
let audioFramesDecoded = 0;
|
|
33920
34009
|
let watchdogFirstFrameMs = 0;
|
|
33921
34010
|
let watchdogSlowSinceMs = 0;
|
|
@@ -33941,6 +34030,18 @@ async function startDecoder(opts) {
|
|
|
33941
34030
|
if (myToken !== pumpToken || destroyed) return;
|
|
33942
34031
|
const videoPackets = videoStream ? packets[videoStream.index] : void 0;
|
|
33943
34032
|
const audioPackets = audioStream ? packets[audioStream.index] : void 0;
|
|
34033
|
+
if (videoPackets && videoTimeBase) {
|
|
34034
|
+
for (const pkt of videoPackets) {
|
|
34035
|
+
const sec = packetPtsSec(pkt, videoTimeBase);
|
|
34036
|
+
if (sec != null && sec > bufferedUntilSec) bufferedUntilSec = sec;
|
|
34037
|
+
}
|
|
34038
|
+
}
|
|
34039
|
+
if (audioPackets && audioTimeBase) {
|
|
34040
|
+
for (const pkt of audioPackets) {
|
|
34041
|
+
const sec = packetPtsSec(pkt, audioTimeBase);
|
|
34042
|
+
if (sec != null && sec > bufferedUntilSec) bufferedUntilSec = sec;
|
|
34043
|
+
}
|
|
34044
|
+
}
|
|
33944
34045
|
if (audioDec && audioPackets && audioPackets.length > 0) {
|
|
33945
34046
|
await decodeAudioBatch(audioPackets, myToken);
|
|
33946
34047
|
}
|
|
@@ -34222,6 +34323,9 @@ async function startDecoder(opts) {
|
|
|
34222
34323
|
(err) => console.error("[avbridge] decoder pump failed (post-seek):", err)
|
|
34223
34324
|
);
|
|
34224
34325
|
},
|
|
34326
|
+
bufferedUntilSec() {
|
|
34327
|
+
return bufferedUntilSec;
|
|
34328
|
+
},
|
|
34225
34329
|
stats() {
|
|
34226
34330
|
return {
|
|
34227
34331
|
decoderType: "libav-wasm",
|
|
@@ -34310,6 +34414,14 @@ async function createFallbackSession(ctx, target, transport) {
|
|
|
34310
34414
|
get: () => ctx.duration ?? NaN
|
|
34311
34415
|
});
|
|
34312
34416
|
}
|
|
34417
|
+
Object.defineProperty(target, "playbackRate", {
|
|
34418
|
+
configurable: true,
|
|
34419
|
+
get: () => audio.getPlaybackRate(),
|
|
34420
|
+
set: (v) => {
|
|
34421
|
+
audio.setPlaybackRate(v);
|
|
34422
|
+
target.dispatchEvent(new Event("ratechange"));
|
|
34423
|
+
}
|
|
34424
|
+
});
|
|
34313
34425
|
Object.defineProperty(target, "readyState", {
|
|
34314
34426
|
configurable: true,
|
|
34315
34427
|
get: () => {
|
|
@@ -34322,6 +34434,13 @@ async function createFallbackSession(ctx, target, transport) {
|
|
|
34322
34434
|
configurable: true,
|
|
34323
34435
|
get: () => makeTimeRanges(ctx.duration && Number.isFinite(ctx.duration) && ctx.duration > 0 ? [[0, ctx.duration]] : [])
|
|
34324
34436
|
});
|
|
34437
|
+
Object.defineProperty(target, "buffered", {
|
|
34438
|
+
configurable: true,
|
|
34439
|
+
get: () => {
|
|
34440
|
+
const end = handles.bufferedUntilSec();
|
|
34441
|
+
return makeTimeRanges(end > 0 ? [[0, end]] : []);
|
|
34442
|
+
}
|
|
34443
|
+
});
|
|
34325
34444
|
async function waitForBuffer() {
|
|
34326
34445
|
const start = performance.now();
|
|
34327
34446
|
let firstFrameAtMs = 0;
|
|
@@ -34361,6 +34480,7 @@ async function createFallbackSession(ctx, target, transport) {
|
|
|
34361
34480
|
}
|
|
34362
34481
|
async function doSeek(timeSec) {
|
|
34363
34482
|
const wasPlaying = audio.isPlaying();
|
|
34483
|
+
target.dispatchEvent(new Event("seeking"));
|
|
34364
34484
|
await audio.pause().catch(() => {
|
|
34365
34485
|
});
|
|
34366
34486
|
await handles.seek(timeSec).catch(
|
|
@@ -34372,7 +34492,14 @@ async function createFallbackSession(ctx, target, transport) {
|
|
|
34372
34492
|
await waitForBuffer();
|
|
34373
34493
|
await audio.start();
|
|
34374
34494
|
}
|
|
34495
|
+
target.dispatchEvent(new Event("seeked"));
|
|
34375
34496
|
}
|
|
34497
|
+
queueMicrotask(() => {
|
|
34498
|
+
try {
|
|
34499
|
+
target.dispatchEvent(new Event("loadedmetadata"));
|
|
34500
|
+
} catch {
|
|
34501
|
+
}
|
|
34502
|
+
});
|
|
34376
34503
|
return {
|
|
34377
34504
|
strategy: "fallback",
|
|
34378
34505
|
async play() {
|
|
@@ -34426,6 +34553,7 @@ async function createFallbackSession(ctx, target, transport) {
|
|
|
34426
34553
|
delete target.muted;
|
|
34427
34554
|
delete target.readyState;
|
|
34428
34555
|
delete target.seekable;
|
|
34556
|
+
delete target.playbackRate;
|
|
34429
34557
|
} catch {
|
|
34430
34558
|
}
|
|
34431
34559
|
},
|
|
@@ -35455,9 +35583,10 @@ var AvbridgeVideoElement = class extends HTMLElementCtor {
|
|
|
35455
35583
|
else this.removeAttribute("autoplay");
|
|
35456
35584
|
}
|
|
35457
35585
|
get muted() {
|
|
35458
|
-
return this.
|
|
35586
|
+
return this._videoEl.muted;
|
|
35459
35587
|
}
|
|
35460
35588
|
set muted(value) {
|
|
35589
|
+
this._videoEl.muted = value;
|
|
35461
35590
|
if (value) this.setAttribute("muted", "");
|
|
35462
35591
|
else this.removeAttribute("muted");
|
|
35463
35592
|
}
|
|
@@ -35522,11 +35651,16 @@ var AvbridgeVideoElement = class extends HTMLElementCtor {
|
|
|
35522
35651
|
}
|
|
35523
35652
|
/**
|
|
35524
35653
|
* Buffered time ranges for the active source. Mirrors the standard
|
|
35525
|
-
* `<video>.buffered` `TimeRanges` API.
|
|
35526
|
-
*
|
|
35527
|
-
*
|
|
35528
|
-
*
|
|
35529
|
-
*
|
|
35654
|
+
* `<video>.buffered` `TimeRanges` API.
|
|
35655
|
+
*
|
|
35656
|
+
* - **Native / remux:** pass-through to the real `<video>.buffered`
|
|
35657
|
+
* (reflects the browser's SourceBuffer / progressive-download state).
|
|
35658
|
+
* - **Hybrid / fallback:** a single `[0, frontier]` range synthesized
|
|
35659
|
+
* from the demuxer's read progress — "how far libav has ever pumped
|
|
35660
|
+
* packets through." Monotonic; does not shrink on seek. This is an
|
|
35661
|
+
* approximation, not MSE-fidelity: decoded frames on canvas strategies
|
|
35662
|
+
* are consumed in flight, so we can't report per-range availability
|
|
35663
|
+
* the way MSE does. Enough for a seek-bar buffered indicator.
|
|
35530
35664
|
*/
|
|
35531
35665
|
get buffered() {
|
|
35532
35666
|
return this._videoEl.buffered;
|