mirror of
https://github.com/arcodange-org/mediabunny.git
synced 2026-09-29 03:43:50 +02:00
Merge branch 'main' into v2
This commit is contained in:
+92
-5
@@ -1,5 +1,6 @@
|
||||
import { expect, test } from 'vitest';
|
||||
import path from 'node:path';
|
||||
import fs from 'node:fs/promises';
|
||||
import { assert, toUint8Array } from '../../src/misc.js';
|
||||
import { Input } from '../../src/input.js';
|
||||
import { BufferSource, FilePathSource } from '../../src/source.js';
|
||||
@@ -22,7 +23,7 @@ test('can loop over all samples', async () => {
|
||||
|
||||
const track = await input.getPrimaryAudioTrack();
|
||||
assert(track);
|
||||
expect(await track.computeDuration()).toEqual(19.71428571428571);
|
||||
expect(await track.computeDuration()).toEqual(19.714285714285715);
|
||||
expect(await track.getDecoderConfig()).toEqual({
|
||||
codec: 'flac',
|
||||
numberOfChannels: 2,
|
||||
@@ -34,7 +35,7 @@ test('can loop over all samples', async () => {
|
||||
]),
|
||||
});
|
||||
expect(await track.getCodecParameterString()).toEqual('flac');
|
||||
expect(track.timeResolution).toEqual(44100);
|
||||
expect(await track.getTimeResolution()).toEqual(44100);
|
||||
expect(await input.getMimeType()).toEqual('audio/flac');
|
||||
|
||||
const cursor = new PacketCursor(track);
|
||||
@@ -183,9 +184,9 @@ test('can re-mux a .flac', async () => {
|
||||
|
||||
const inputTrack = await input.getPrimaryAudioTrack();
|
||||
assert(inputTrack);
|
||||
expect(inputTrack.sampleRate).toBe(outputTrack.sampleRate);
|
||||
expect(inputTrack.numberOfChannels).toBe(outputTrack.numberOfChannels);
|
||||
expect(inputTrack.timeResolution).toBe(outputTrack.timeResolution);
|
||||
expect(await inputTrack.getSampleRate()).toBe(await outputTrack.getSampleRate());
|
||||
expect(await inputTrack.getNumberOfChannels()).toBe(await outputTrack.getNumberOfChannels());
|
||||
expect(await inputTrack.getTimeResolution()).toBe(await outputTrack.getTimeResolution());
|
||||
|
||||
const outputMetadataTags = await outputAsInput.getMetadataTags();
|
||||
|
||||
@@ -260,3 +261,89 @@ test('can re-mux a .flac', async () => {
|
||||
|
||||
expect(otherInputDecoderConfig).toEqual(otherOutputDecoderConfig);
|
||||
});
|
||||
|
||||
test('appendOnly writes correct STREAMINFO header', async () => {
|
||||
const filePath = path.join(__dirname, '..', 'public/sample.flac');
|
||||
using input = new Input({
|
||||
source: new FilePathSource(filePath),
|
||||
formats: ALL_FORMATS,
|
||||
});
|
||||
|
||||
const target = new BufferTarget();
|
||||
const output = new Output({
|
||||
format: new FlacOutputFormat({ appendOnly: true }),
|
||||
target,
|
||||
});
|
||||
|
||||
const conversion = await Conversion.init({ input, output });
|
||||
await conversion.execute();
|
||||
|
||||
assert(target.buffer);
|
||||
const bytes = new Uint8Array(target.buffer);
|
||||
|
||||
// STREAMINFO: min_block=16, max_block=65535, min_frame=0, max_frame=0
|
||||
expect(bytes.slice(8, 18)).toEqual(new Uint8Array([
|
||||
// minimum_block_size=16
|
||||
0x00, 0x10,
|
||||
// maximum_block_size=65535
|
||||
0xFF, 0xFF,
|
||||
// minimum_frame_size=0
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
]));
|
||||
});
|
||||
|
||||
test('can read a FLAC file with leading ID3v2 tags', async () => {
|
||||
const createId3V23TitleTag = (title: string) => {
|
||||
const titleBytes = new TextEncoder().encode(title);
|
||||
const frame = new Uint8Array(11 + titleBytes.length);
|
||||
frame.set([0x54, 0x49, 0x54, 0x32]); // TIT2
|
||||
frame[7] = 1 + titleBytes.length;
|
||||
frame[10] = 0; // ISO-8859-1
|
||||
frame.set(titleBytes, 11);
|
||||
|
||||
const tag = new Uint8Array(10 + frame.length);
|
||||
tag.set([0x49, 0x44, 0x33, 0x03, 0x00, 0x00]); // ID3v2.3
|
||||
tag[9] = frame.length;
|
||||
tag.set(frame, 10);
|
||||
|
||||
return tag;
|
||||
};
|
||||
|
||||
const concatenateBytes = (...chunks: Uint8Array[]) => {
|
||||
const result = new Uint8Array(chunks.reduce((sum, chunk) => sum + chunk.byteLength, 0));
|
||||
let offset = 0;
|
||||
|
||||
for (const chunk of chunks) {
|
||||
result.set(chunk, offset);
|
||||
offset += chunk.byteLength;
|
||||
}
|
||||
|
||||
return result;
|
||||
};
|
||||
|
||||
using input = new Input({
|
||||
source: new BufferSource(concatenateBytes(
|
||||
createId3V23TitleTag('First tag'),
|
||||
createId3V23TitleTag('Second tag'),
|
||||
await fs.readFile(new URL('../public/sample.flac', import.meta.url)),
|
||||
)),
|
||||
formats: ALL_FORMATS,
|
||||
});
|
||||
|
||||
expect(await input.canRead()).toBe(true);
|
||||
expect(await input.getFormat()).toBe(FLAC);
|
||||
|
||||
const track = await input.getPrimaryAudioTrack();
|
||||
assert(track);
|
||||
expect(await track.getDurationFromMetadata()).toEqual(19.714285714285715);
|
||||
|
||||
const firstPacket = await new PacketReader(track).getAt(0);
|
||||
assert(firstPacket);
|
||||
expect(firstPacket.sequenceNumber).toBe(0);
|
||||
expect(firstPacket.timestamp).toBe(0);
|
||||
|
||||
const metadataTags = await input.getMetadataTags();
|
||||
expect(metadataTags.title).toBe('First tag');
|
||||
expect(metadataTags.raw!['TIT2']).toBe('First tag');
|
||||
expect(metadataTags.raw!['TITLE']).toBe('The Happy Meeting');
|
||||
});
|
||||
|
||||
Reference in New Issue
Block a user