mirror of
https://github.com/arcodange-org/mediabunny.git
synced 2026-09-27 19:03:46 +02:00
* add a test * recognize as input format * scaffold flac demuxer * implement getting metadata * Implement mime type * read all metadata + deduplicate stubs * Read first packet * copyright headers * read the first packet * Get entire first packet, work on advancing * iterate over all samples * testable with bun * stub out metadata support * parse descriptive metadata * All in 1 file seems more appropriate to the philosophy * some parameters are not needed anymore all within 1 class * skip over bytes we are sure are not the syncword * run prettier * timestamp is determined based on passed blocks, not maximumBlockSize * no binary search needed! * simplifications * Finish demuxer reading sequentially * more tests + add a file with a seektable * don't throw if (this.audioInfo.minimumBlockSize !== this.audioInfo.maximumBlockSize * Add docs * Update format compatibility table * Simplification * confirm conversion is working * Finish * Resolve TODO comment * Support images (read-only) * Returning description as Uint8Array * Cleanup of demuxer * Misc renames * Object on same line * Resolve first batch of comments * Throw errors on corrupt blocks, correctly use requestSlice() * Fix description field * Explain why last frame is a bit shorter * Add FLAC to README * Put track backings below demuxer * convert to methods * Reorder container checking * getBlockSize() -> readBlockSize() * bitStream -> bitstream * better naming for bytes * use .skip() * Don't return blockSize twice in readFlacFrameHeader * Use enum + switch to distinguish Flac block types * Use else-if * Use else-if * Compressed switch statement * readCodedNumber * Update flac-misc.ts * We don't need the bits variable at all * reorder functions in flac-demuxer * Handle gracefully not being able to load another sample * Update flac-demuxer.ts * blockingbit null * use async instead of promise.resolve * use binary search * Replace recursion with while loop * Add mutex to getPacket() * Load more data not in getPacketAtIndex, but outside * Apply suggestion from @Vanilagy Co-authored-by: David P. <[email protected]> * computeDuration() reads last packet * Update flac-demuxer.ts * share vorbis comment reading logic * reuse vorbis comment writing logic, set vendor always to "Mediabunny" * flush after writign * Use FileSlice.tempFromBytes * assert !== null * fixing nitpicks * apply suggestions * fix ogg * We are now muxing images * apply suggestion * Update src/flac/flac-muxer.ts Co-authored-by: David P. <[email protected]> * apply suggestion * readSampleRate() * seek outside writeHeader() * mention vorbis metadata + add to metadatatags comment * should be able to -> can * Add test in metadata tags * Add test for packets being byte identical after remuxing * compare to null * no casting to uint8array * make test pass * Update flac-muxer.ts * Call validateAudioChunkMetadata() and validateAndNormalizeTimestamp() * `onFrame` option * emit frames using onFrame * Run prettier over files * Fix FLAC PICTURE block logic, small other changes * Update docs * Remove .only modifier * fix remuxing and add test * Don't throw error if parsing fails in header, since hitting a syncword might just be coincidential * Fix remaining type errors --------- Co-authored-by: David P. <[email protected]>
69 lines
2.0 KiB
TypeScript
69 lines
2.0 KiB
TypeScript
import { expect, test } from 'vitest';
|
|
import { Input } from '../../src/input.js';
|
|
import { BufferSource, UrlSource } from '../../src/source.js';
|
|
import { FLAC, WAVE } from '../../src/input-format.js';
|
|
import { AudioSampleSink } from '../../src/media-sink.js';
|
|
import { assert } from '../../src/misc.js';
|
|
import { Output } from '../../src/output.js';
|
|
import { WavOutputFormat } from '../../src/output-format.js';
|
|
import { BufferTarget } from '../../src/target.js';
|
|
import { Conversion } from '../../src/conversion.js';
|
|
|
|
test('can decode samples from a FLAC file', async () => {
|
|
const input = new Input({
|
|
source: new UrlSource('/sample.flac'),
|
|
formats: [FLAC],
|
|
});
|
|
const track = await input.getPrimaryAudioTrack();
|
|
assert(track);
|
|
|
|
const sink = new AudioSampleSink(track);
|
|
|
|
const sample = await sink.getSample(1);
|
|
assert(sample);
|
|
expect(sample.timestamp).toBe(0.9287981859410431);
|
|
});
|
|
|
|
test('can convert a .flac to .wav', async () => {
|
|
const input = new Input({
|
|
source: new UrlSource('/sample.flac'),
|
|
formats: [FLAC],
|
|
});
|
|
const output = new Output({
|
|
format: new WavOutputFormat(),
|
|
target: new BufferTarget(),
|
|
});
|
|
|
|
const conversion = await Conversion.init({ input, output });
|
|
await conversion.execute();
|
|
|
|
const buffer = output.target.buffer;
|
|
assert(buffer);
|
|
|
|
const outputAsInput = new Input({
|
|
source: new BufferSource(buffer),
|
|
formats: [WAVE],
|
|
});
|
|
|
|
const inputTrack = await input.getPrimaryAudioTrack();
|
|
assert(inputTrack);
|
|
|
|
const outputTrack = await outputAsInput.getPrimaryAudioTrack();
|
|
assert(outputTrack);
|
|
|
|
const duration = await outputTrack.computeDuration();
|
|
expect(duration).toBe(19.71428571428571);
|
|
const tags = await outputAsInput.getMetadataTags();
|
|
expect(tags.raw).toEqual({
|
|
IART: 'Samples Files',
|
|
ICRD: '2020-01-01',
|
|
IGNR: 'Ambient',
|
|
INAM: 'The Happy Meeting',
|
|
IPRD: 'Samples files',
|
|
ITRK: '4',
|
|
});
|
|
expect(inputTrack.sampleRate).toBe(outputTrack.sampleRate);
|
|
expect(inputTrack.numberOfChannels).toBe(outputTrack.numberOfChannels);
|
|
expect(inputTrack.timeResolution).toBe(outputTrack.timeResolution);
|
|
});
|