mirror of
https://github.com/arcodange-org/mediabunny.git
synced 2026-09-27 02:43:48 +02:00
131 lines
3.5 KiB
TypeScript
131 lines
3.5 KiB
TypeScript
import { expect, test } from 'vitest';
|
|
import { Input } from '../../src/input.js';
|
|
import { BufferSource, UrlSource } from '../../src/source.js';
|
|
import { ALL_FORMATS } from '../../src/input-format.js';
|
|
import { EncodedPacketSink } from '../../src/media-sink.js';
|
|
import { EncodedAudioPacketSource } from '../../src/media-source.js';
|
|
import { Output } from '../../src/output.js';
|
|
import { StreamTarget, type StreamTargetChunk } from '../../src/target.js';
|
|
import { AdtsOutputFormat } from '../../src/output-format.js';
|
|
import { assert } from '../../src/misc.js';
|
|
|
|
const createBufferingStreamTarget = () => {
|
|
const written = new Map<number, Uint8Array>();
|
|
|
|
const stream = new WritableStream<StreamTargetChunk>({
|
|
async write(chunk: StreamTargetChunk) {
|
|
written.set(chunk.position, chunk.data.slice());
|
|
},
|
|
});
|
|
|
|
const toBuffer = () => {
|
|
let maxEnd = 0;
|
|
for (const [offset, data] of written) {
|
|
maxEnd = Math.max(maxEnd, offset + data.byteLength);
|
|
}
|
|
const buffer = new Uint8Array(maxEnd);
|
|
for (const [offset, data] of written) {
|
|
buffer.set(data, offset);
|
|
}
|
|
return buffer;
|
|
};
|
|
|
|
return { stream, toBuffer };
|
|
};
|
|
|
|
test('ADTS with metadata over StreamTarget', async () => {
|
|
const target = createBufferingStreamTarget();
|
|
|
|
const output = new Output({
|
|
format: new AdtsOutputFormat(),
|
|
target: new StreamTarget(target.stream),
|
|
});
|
|
|
|
output.setMetadataTags({ comment: 'Remotion' });
|
|
|
|
const audioSource = new EncodedAudioPacketSource('aac');
|
|
output.addAudioTrack(audioSource);
|
|
|
|
await output.start();
|
|
|
|
using input = new Input({
|
|
source: new UrlSource('/sample3.aac'),
|
|
formats: ALL_FORMATS,
|
|
});
|
|
|
|
const audioTrack = await input.getPrimaryAudioTrack();
|
|
assert(audioTrack);
|
|
|
|
const sink = new EncodedPacketSink(audioTrack);
|
|
|
|
let isFirst = true;
|
|
for await (const packet of sink.packets()) {
|
|
await audioSource.add(packet, {
|
|
decoderConfig: isFirst ? (await audioTrack.getDecoderConfig())! : undefined,
|
|
});
|
|
isFirst = false;
|
|
}
|
|
|
|
await output.finalize();
|
|
|
|
const buffer = target.toBuffer();
|
|
using outputAsInput = new Input({
|
|
source: new BufferSource(buffer.buffer),
|
|
formats: ALL_FORMATS,
|
|
});
|
|
|
|
const readTags = await outputAsInput.getMetadataTags();
|
|
expect(readTags.comment).toBe('Remotion');
|
|
|
|
const outputAudioTrack = await outputAsInput.getPrimaryAudioTrack();
|
|
assert(outputAudioTrack);
|
|
expect(await outputAudioTrack.getCodec()).toBe('aac');
|
|
});
|
|
|
|
// Previously, write handler rejections were silently swallowed and surfaced as
|
|
// "Cannot write to a closing writable stream" instead of the actual error.
|
|
test('StreamTarget write errors surface directly', async () => {
|
|
let writeCount = 0;
|
|
const stream = new WritableStream<StreamTargetChunk>({
|
|
async write() {
|
|
writeCount++;
|
|
if (writeCount === 2) {
|
|
throw new Error('OPFS write failed');
|
|
}
|
|
},
|
|
});
|
|
|
|
const output = new Output({
|
|
format: new AdtsOutputFormat(),
|
|
target: new StreamTarget(stream),
|
|
});
|
|
|
|
const audioSource = new EncodedAudioPacketSource('aac');
|
|
output.addAudioTrack(audioSource);
|
|
|
|
await output.start();
|
|
|
|
using input = new Input({
|
|
source: new UrlSource('/sample3.aac'),
|
|
formats: ALL_FORMATS,
|
|
});
|
|
|
|
const audioTrack = await input.getPrimaryAudioTrack();
|
|
assert(audioTrack);
|
|
|
|
const sink = new EncodedPacketSink(audioTrack);
|
|
|
|
const run = async () => {
|
|
let isFirst = true;
|
|
for await (const packet of sink.packets()) {
|
|
await audioSource.add(packet, {
|
|
decoderConfig: isFirst ? (await audioTrack.getDecoderConfig())! : undefined,
|
|
});
|
|
isFirst = false;
|
|
}
|
|
await output.finalize();
|
|
};
|
|
|
|
await expect(run()).rejects.toThrow('OPFS write failed');
|
|
});
|