Files
mediabunny/docs/guide/input-formats.md
T
d426d36386 FLAC container support (#95)
* 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]>
2025-09-18 21:05:09 +02:00

100 lines
3.4 KiB
Markdown

# Input formats
Mediabunny supports a wide variety of commonly used container formats for reading input files. These *input formats* are used in two ways:
- When creating an `Input`, they are used to specify the list of supported container formats. See [Creating a new input](./reading-media-files#creating-a-new-input) for more.
- Given an existing `Input`, its `getFormat` method returns the *actual* format of the file as an `InputFormat`.
## Input format properties
Retrieve the full written name of the format like this:
```ts
inputFormat.name; // => 'MP4'
```
You can also retrieve the format's base MIME type:
```ts
inputFormat.mimeType; // => 'video/mp4'
```
If you want a file's full MIME type, which depends on track codecs, use [`getMimeType`](./reading-media-files#reading-file-metadata) on `Input` instead.
## Input format singletons
Since input formats don't require any additional configuration, each input format is directly available as an exported singleton instance:
```ts
import {
MP4, // MP4 input format singleton
QTFF, // QuickTime File Format input format singleton
MATROSKA, // Matroska input format singleton
WEBM, // WebM input format singleton
MP3, // MP3 input format singleton
WAVE, // WAVE input format singleton
OGG, // Ogg input format singleton
ADTS, // ADTS input format singleton
FLAC, // FLAC input format singleton
} from 'mediabunny';
```
You can use these singletons when creating an input:
```ts
import { Input, MP3, WAVE, OGG } from 'mediabunny';
const input = new Input({
formats: [MP3, WAVE, OGG],
// ...
});
```
You can also use them for checking the actual format of an `Input`:
```ts
import { MP3 } from 'mediabunny';
const isMp3 = (await input.getFormat()) === MP3;
```
There is a special `ALL_FORMATS` constant exported by Mediabunny which contains every input format singleton. Use this constant if you want to support as many formats as possible:
```ts
import { Input, ALL_FORMATS } from 'mediabunny';
const input = new Input({
formats: ALL_FORMATS,
// ...
});
```
::: info
Using `ALL_FORMATS` means [demuxers](https://en.wikipedia.org/wiki/Demultiplexer_(media_file)) for all formats must be included in the bundle, which can increase the bundle size significantly. Use it only if you need to support all formats.
:::
## Input format class hierarchy
In addition to singletons, input format classes are structured hierarchically:
- `InputFormat` (abstract)
- `IsobmffInputFormat` (abstract)
- `Mp4InputFormat`
- `QuickTimeInputFormat`
- `MatroskaInputFormat`
- `WebMInputFormat`
- `Mp3InputFormat`
- `WaveInputFormat`
- `OggInputFormat`
- `AdtsInputFormat`
- `FlacInputFormat`
This means you can also perform input format checks using `instanceof` instead of `===` comparisons. For example:
```ts
import { Mp3InputFormat } from 'mediabunny';
// Check if the file is MP3:
(await input.getFormat()) instanceof Mp3InputFormat;
// Check if the file is Matroska (MKV + WebM):
(await input.getFormat()) instanceof MatroskaInputFormat;
// Check if the file is MP4 or QuickTime:
(await input.getFormat()) instanceof IsobmffInputFormat;
```
::: info
Well, actually 🤓☝️, the QuickTime File Format is technically not an instance of the ISO Base Media File Format (ISOBMFF) - instead, ISOBMFF is a standard originally inspired by QTFF. However, as the two are extremely similar and are used in the same way, we consider QTFF an instance of `IsobmffInputFormat` for convenience.
:::