mirror of
https://github.com/arcodange-org/mediabunny.git
synced 2026-09-27 02:43:48 +02:00
Mediakit -> Mediabunny
This commit is contained in:
|
Before Width: | Height: | Size: 1.4 KiB After Width: | Height: | Size: 1.4 KiB |
@@ -3,7 +3,7 @@ import footnote from 'markdown-it-footnote';
|
|||||||
|
|
||||||
// https://vitepress.dev/reference/site-config
|
// https://vitepress.dev/reference/site-config
|
||||||
export default withMermaid({
|
export default withMermaid({
|
||||||
title: 'Mediakit',
|
title: 'Mediabunny',
|
||||||
description: 'A VitePress Site',
|
description: 'A VitePress Site',
|
||||||
cleanUrls: true,
|
cleanUrls: true,
|
||||||
themeConfig: {
|
themeConfig: {
|
||||||
|
|||||||
+2
-2
@@ -4,7 +4,7 @@ title: Examples
|
|||||||
|
|
||||||
hero:
|
hero:
|
||||||
text: Examples
|
text: Examples
|
||||||
tagline: Demos showcasing various features of Mediakit
|
tagline: Demos showcasing various features of Mediabunny
|
||||||
|
|
||||||
features:
|
features:
|
||||||
- title: Metadata extraction
|
- title: Metadata extraction
|
||||||
@@ -16,7 +16,7 @@ features:
|
|||||||
link: /examples/thumbnail-generation
|
link: /examples/thumbnail-generation
|
||||||
target: _self
|
target: _self
|
||||||
- title: Media player (advanced)
|
- title: Media player (advanced)
|
||||||
details: "A full video & audio media player, implemented from scratch with Mediakit, with microsecond playback accuracy."
|
details: "A full video & audio media player, implemented from scratch with Mediabunny, with microsecond playback accuracy."
|
||||||
link: /examples/media-player
|
link: /examples/media-player
|
||||||
target: _self
|
target: _self
|
||||||
- title: File compression
|
- title: File compression
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
# Converting media files
|
# Converting media files
|
||||||
|
|
||||||
The [reading](./reading-media-files) and [writing](./writing-media-files) primitives in Mediakit provide everything you need to convert media files. However, since this is such a common operation and the details can be tricky, Mediakit ships with a built-in file conversion abstraction.
|
The [reading](./reading-media-files) and [writing](./writing-media-files) primitives in Mediabunny provide everything you need to convert media files. However, since this is such a common operation and the details can be tricky, Mediabunny ships with a built-in file conversion abstraction.
|
||||||
|
|
||||||
It has the following features:
|
It has the following features:
|
||||||
|
|
||||||
@@ -30,7 +30,7 @@ import {
|
|||||||
WebMOutputFormat,
|
WebMOutputFormat,
|
||||||
BufferTarget,
|
BufferTarget,
|
||||||
Conversion,
|
Conversion,
|
||||||
} from 'mediakit';
|
} from 'mediabunny';
|
||||||
|
|
||||||
const input = new Input({ ... });
|
const input = new Input({ ... });
|
||||||
const output = new Output({
|
const output = new Output({
|
||||||
@@ -189,9 +189,9 @@ If you want to get rid of the audio track, use `discard: true`.
|
|||||||
|
|
||||||
### Resampling audio
|
### Resampling audio
|
||||||
|
|
||||||
The `numberOfChannels` property controls the channel count of the output audio (e.g., 1 for mono, 2 for stereo). If this value differs from the number of channels in the input track, Mediakit will perform up/downmixing of the channel data using [the same algorithm as the Web Audio API](https://developer.mozilla.org/en-US/docs/Web/API/Web_Audio_API/Basic_concepts_behind_Web_Audio_API#audio_channels).
|
The `numberOfChannels` property controls the channel count of the output audio (e.g., 1 for mono, 2 for stereo). If this value differs from the number of channels in the input track, Mediabunny will perform up/downmixing of the channel data using [the same algorithm as the Web Audio API](https://developer.mozilla.org/en-US/docs/Web/API/Web_Audio_API/Basic_concepts_behind_Web_Audio_API#audio_channels).
|
||||||
|
|
||||||
The `sampleRate` property controls the sample rate in Hz (e.g., 44100, 48000). If this value differs from the input track's sample rate, Mediakit will resample the audio.
|
The `sampleRate` property controls the sample rate in Hz (e.g., 44100, 48000). If this value differs from the input track's sample rate, Mediabunny will resample the audio.
|
||||||
|
|
||||||
### Transcoding audio
|
### Transcoding audio
|
||||||
|
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
# Input formats
|
# Input formats
|
||||||
|
|
||||||
Mediakit supports a wide variety of commonly used container formats for reading input files. These *input formats* are used in two ways:
|
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.
|
- 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`.
|
- Given an existing `Input`, its `getFormat` method returns the *actual* format of the file as an `InputFormat`.
|
||||||
|
|
||||||
@@ -30,12 +30,12 @@ import {
|
|||||||
MP3, // MP3 input format singleton
|
MP3, // MP3 input format singleton
|
||||||
WAVE, // WAVE input format singleton
|
WAVE, // WAVE input format singleton
|
||||||
OGG, // Ogg input format singleton
|
OGG, // Ogg input format singleton
|
||||||
} from 'mediakit';
|
} from 'mediabunny';
|
||||||
```
|
```
|
||||||
|
|
||||||
You can use these singletons when creating an input:
|
You can use these singletons when creating an input:
|
||||||
```ts
|
```ts
|
||||||
import { Input, MP3, WAVE, OGG } from 'mediakit';
|
import { Input, MP3, WAVE, OGG } from 'mediabunny';
|
||||||
|
|
||||||
const input = new Input({
|
const input = new Input({
|
||||||
formats: [MP3, WAVE, OGG],
|
formats: [MP3, WAVE, OGG],
|
||||||
@@ -45,14 +45,14 @@ const input = new Input({
|
|||||||
|
|
||||||
You can also use them for checking the actual format of an `Input`:
|
You can also use them for checking the actual format of an `Input`:
|
||||||
```ts
|
```ts
|
||||||
import { MP3 } from 'mediakit';
|
import { MP3 } from 'mediabunny';
|
||||||
|
|
||||||
const isMp3 = input.getFormat() === MP3;
|
const isMp3 = input.getFormat() === MP3;
|
||||||
```
|
```
|
||||||
|
|
||||||
There is a special `ALL_FORMATS` constant exported by Mediakit which contains every input format singleton. Use this constant if you want to support as many formats as possible:
|
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
|
```ts
|
||||||
import { Input, ALL_FORMATS } from 'mediakit';
|
import { Input, ALL_FORMATS } from 'mediabunny';
|
||||||
|
|
||||||
const input = new Input({
|
const input = new Input({
|
||||||
formats: ALL_FORMATS,
|
formats: ALL_FORMATS,
|
||||||
@@ -79,7 +79,7 @@ In addition to singletons, input format classes are structured hierarchically:
|
|||||||
|
|
||||||
This means you can also perform input format checks using `instanceof` instead of `===` comparisons. For example:
|
This means you can also perform input format checks using `instanceof` instead of `===` comparisons. For example:
|
||||||
```ts
|
```ts
|
||||||
import { Mp3InputFormat } from 'mediakit';
|
import { Mp3InputFormat } from 'mediabunny';
|
||||||
|
|
||||||
// Check if the file is MP3:
|
// Check if the file is MP3:
|
||||||
input.getFormat() instanceof Mp3InputFormat;
|
input.getFormat() instanceof Mp3InputFormat;
|
||||||
|
|||||||
@@ -1,31 +1,31 @@
|
|||||||
# Introduction
|
# Introduction
|
||||||
|
|
||||||
Install Mediakit using your favorite package manager:
|
Install Mediabunny using your favorite package manager:
|
||||||
|
|
||||||
::: code-group
|
::: code-group
|
||||||
```bash [npm]
|
```bash [npm]
|
||||||
npm install mediakit
|
npm install mediabunny
|
||||||
```
|
```
|
||||||
```bash [yarn]
|
```bash [yarn]
|
||||||
yarn add mediakit
|
yarn add mediabunny
|
||||||
```
|
```
|
||||||
```bash [pnpm]
|
```bash [pnpm]
|
||||||
pnpm add mediakit
|
pnpm add mediabunny
|
||||||
```
|
```
|
||||||
```bash [bun]
|
```bash [bun]
|
||||||
bun add mediakit
|
bun add mediabunny
|
||||||
```
|
```
|
||||||
:::
|
:::
|
||||||
|
|
||||||
Both ESM and CommonJS are supported:
|
Both ESM and CommonJS are supported:
|
||||||
```ts
|
```ts
|
||||||
import * as Mediakit from 'mediakit';
|
import * as Mediabunny from 'mediabunny';
|
||||||
const Mediakit = require('mediakit');
|
const Mediabunny = require('mediabunny');
|
||||||
```
|
```
|
||||||
|
|
||||||
Alternativly, you can simply include the library using a script tag in your HTML:
|
Alternativly, you can simply include the library using a script tag in your HTML:
|
||||||
```html
|
```html
|
||||||
<script src="path/to/mediakit.js"></script>
|
<script src="path/to/mediabunny.js"></script>
|
||||||
```
|
```
|
||||||
|
|
||||||
You can download the built distribution file from the [releases page](https://github.com/Vanilagy/mp4-muxer/releases).
|
You can download the built distribution file from the [releases page](https://github.com/Vanilagy/mp4-muxer/releases).
|
||||||
@@ -82,7 +82,7 @@ This sink can be used to extract raw, [encoded packets](./packets-and-samples#en
|
|||||||
|
|
||||||
Start by constructing the sink from any `InputTrack`:
|
Start by constructing the sink from any `InputTrack`:
|
||||||
```ts
|
```ts
|
||||||
import { EncodedPacketSink } from 'mediakit';
|
import { EncodedPacketSink } from 'mediabunny';
|
||||||
|
|
||||||
const sink = new EncodedPacketSink(track);
|
const sink = new EncodedPacketSink(track);
|
||||||
```
|
```
|
||||||
@@ -169,7 +169,7 @@ All operations of this sink use [presentation order](#decode-vs-presentation-ord
|
|||||||
|
|
||||||
Create the sink like so:
|
Create the sink like so:
|
||||||
```ts
|
```ts
|
||||||
import { VideoSampleSink } from 'mediakit';
|
import { VideoSampleSink } from 'mediabunny';
|
||||||
|
|
||||||
const sink = new VideoSampleSink(videoTrack);
|
const sink = new VideoSampleSink(videoTrack);
|
||||||
```
|
```
|
||||||
@@ -296,7 +296,7 @@ This sink yields `HTMLCanvasElement` whenever possible, and falls back to `Offsc
|
|||||||
|
|
||||||
Create the sink like so:
|
Create the sink like so:
|
||||||
```ts
|
```ts
|
||||||
import { CanvasSink } from 'mediakit';
|
import { CanvasSink } from 'mediabunny';
|
||||||
|
|
||||||
const sink = new CanvasSink(videoTrack, options);
|
const sink = new CanvasSink(videoTrack, options);
|
||||||
```
|
```
|
||||||
@@ -414,7 +414,7 @@ Use this sink to extract decoded [audio samples](./packets-and-samples#audiosamp
|
|||||||
|
|
||||||
Create the sink like so:
|
Create the sink like so:
|
||||||
```ts
|
```ts
|
||||||
import { AudioSampleSink } from 'mediakit';
|
import { AudioSampleSink } from 'mediabunny';
|
||||||
|
|
||||||
const sink = new AudioSampleSink(audioTrack);
|
const sink = new AudioSampleSink(audioTrack);
|
||||||
```
|
```
|
||||||
@@ -457,7 +457,7 @@ While `AudioSampleSink` extracts raw decoded audio samples, you can use `AudioBu
|
|||||||
|
|
||||||
Create the sink like so:
|
Create the sink like so:
|
||||||
```ts
|
```ts
|
||||||
import { AudioBufferSink } from 'mediakit';
|
import { AudioBufferSink } from 'mediabunny';
|
||||||
|
|
||||||
const sink = new AudioBufferSink(audioTrack);
|
const sink = new AudioBufferSink(audioTrack);
|
||||||
```
|
```
|
||||||
|
|||||||
+13
-13
@@ -98,7 +98,7 @@ type AudioEncodingConfig = {
|
|||||||
|
|
||||||
### Subjective qualities
|
### Subjective qualities
|
||||||
|
|
||||||
Mediakit provides five subjective quality options as an alternative to manually providing a bitrate. From a subjective quality, a bitrate will be calculated internally based on the codec and track information (width, height, sample rate, ...).
|
Mediabunny provides five subjective quality options as an alternative to manually providing a bitrate. From a subjective quality, a bitrate will be calculated internally based on the codec and track information (width, height, sample rate, ...).
|
||||||
|
|
||||||
```ts
|
```ts
|
||||||
import {
|
import {
|
||||||
@@ -107,7 +107,7 @@ import {
|
|||||||
QUALITY_MEDIUM,
|
QUALITY_MEDIUM,
|
||||||
QUALITY_HIGH,
|
QUALITY_HIGH,
|
||||||
QUALITY_VERY_HIGH,
|
QUALITY_VERY_HIGH,
|
||||||
} from 'mediakit';
|
} from 'mediabunny';
|
||||||
```
|
```
|
||||||
|
|
||||||
## Video sources
|
## Video sources
|
||||||
@@ -119,7 +119,7 @@ Video sources feed data to video tracks on an `Output`. They all extend the abst
|
|||||||
This source takes [video samples](./packets-and-samples#videosample), encodes them, and passes the encoded data to the output.
|
This source takes [video samples](./packets-and-samples#videosample), encodes them, and passes the encoded data to the output.
|
||||||
|
|
||||||
```ts
|
```ts
|
||||||
import { VideoSampleSource } from 'mediakit';
|
import { VideoSampleSource } from 'mediabunny';
|
||||||
|
|
||||||
const sampleSource = new VideoSampleSource({
|
const sampleSource = new VideoSampleSource({
|
||||||
codec: 'avc',
|
codec: 'avc',
|
||||||
@@ -137,7 +137,7 @@ await sampleSource.add(videoSample, { keyFrame: true });
|
|||||||
This source simplifies a common pattern: A single canvas is repeatedly updated in a render loop and each frame is added to the output file.
|
This source simplifies a common pattern: A single canvas is repeatedly updated in a render loop and each frame is added to the output file.
|
||||||
|
|
||||||
```ts
|
```ts
|
||||||
import { CanvasSource, QUALITY_MEDIUM } from 'mediakit';
|
import { CanvasSource, QUALITY_MEDIUM } from 'mediabunny';
|
||||||
|
|
||||||
const canvasSource = new CanvasSource(canvasElement, {
|
const canvasSource = new CanvasSource(canvasElement, {
|
||||||
codec: 'av1',
|
codec: 'av1',
|
||||||
@@ -157,7 +157,7 @@ await canvasSource.add(0.3, 0.1, { keyFrame: true });
|
|||||||
This is a source for use with the [Media Capture and Streams API](https://developer.mozilla.org/en-US/docs/Web/API/Media_Capture_and_Streams_API). Use this source if you want to pipe a real-time video source (such as a webcam or screen recording) to an output file.
|
This is a source for use with the [Media Capture and Streams API](https://developer.mozilla.org/en-US/docs/Web/API/Media_Capture_and_Streams_API). Use this source if you want to pipe a real-time video source (such as a webcam or screen recording) to an output file.
|
||||||
|
|
||||||
```ts
|
```ts
|
||||||
import { MediaStreamVideoTrackSource } from 'mediakit';
|
import { MediaStreamVideoTrackSource } from 'mediabunny';
|
||||||
|
|
||||||
// Get the user's screen
|
// Get the user's screen
|
||||||
const stream = await navigator.mediaDevices.getDisplayMedia({ video: true });
|
const stream = await navigator.mediaDevices.getDisplayMedia({ video: true });
|
||||||
@@ -180,7 +180,7 @@ If this source is the only MediaStreamTrack source in the `Output`, then the fir
|
|||||||
The most barebones of all video sources, this source can be used to directly pipe [encoded packets](./packets-and-samples#encodedpacket) of video data to the output. This source requires that you take care of the encoding process yourself, which enables you to use the WebCodecs API manually or to plug in your own encoding stack. Alternatively, you may retrieve the encoded packets directly by reading them from another media file, allowing you to skip decoding and reencoding video data.
|
The most barebones of all video sources, this source can be used to directly pipe [encoded packets](./packets-and-samples#encodedpacket) of video data to the output. This source requires that you take care of the encoding process yourself, which enables you to use the WebCodecs API manually or to plug in your own encoding stack. Alternatively, you may retrieve the encoded packets directly by reading them from another media file, allowing you to skip decoding and reencoding video data.
|
||||||
|
|
||||||
```ts
|
```ts
|
||||||
import { EncodedVideoPacketSource } from 'mediakit';
|
import { EncodedVideoPacketSource } from 'mediabunny';
|
||||||
|
|
||||||
// You must specify the codec name:
|
// You must specify the codec name:
|
||||||
const packetSource = new EncodedVideoPacketSource('vp9');
|
const packetSource = new EncodedVideoPacketSource('vp9');
|
||||||
@@ -224,7 +224,7 @@ The decode order for these frames will be:
|
|||||||
```md
|
```md
|
||||||
Frame 1 -> Frame 3 -> Frame 2
|
Frame 1 -> Frame 3 -> Frame 2
|
||||||
```
|
```
|
||||||
Some file formats have an explicit notion of both a "decode timestamp" and a "presentation timestamp" to model B-frames or out-of-order decoding. However, Mediakit packets only specify their *presentation timestamp*. Decode order is determined by the order in which you add the packets, so in our example, you must add the packets like this:
|
Some file formats have an explicit notion of both a "decode timestamp" and a "presentation timestamp" to model B-frames or out-of-order decoding. However, Mediabunny packets only specify their *presentation timestamp*. Decode order is determined by the order in which you add the packets, so in our example, you must add the packets like this:
|
||||||
```ts
|
```ts
|
||||||
await packetSource.add(packetForFrame1); // 0.0s
|
await packetSource.add(packetForFrame1); // 0.0s
|
||||||
await packetSource.add(packetForFrame3); // 0.2s
|
await packetSource.add(packetForFrame3); // 0.2s
|
||||||
@@ -274,7 +274,7 @@ Audio sources feed data to audio tracks on an `Output`. They all extend the abst
|
|||||||
This source takes [audio samples](./packets-and-samples#audiosample), encodes them, and passes the encoded data to the output.
|
This source takes [audio samples](./packets-and-samples#audiosample), encodes them, and passes the encoded data to the output.
|
||||||
|
|
||||||
```ts
|
```ts
|
||||||
import { AudioSampleSource } from 'mediakit';
|
import { AudioSampleSource } from 'mediabunny';
|
||||||
|
|
||||||
const sampleSource = new AudioSampleSource({
|
const sampleSource = new AudioSampleSource({
|
||||||
codec: 'aac',
|
codec: 'aac',
|
||||||
@@ -289,7 +289,7 @@ await sampleSource.add(audioSample);
|
|||||||
This source directly accepts instances of `AudioBuffer` as data, simplifying usage with the Web Audio API. The first AudioBuffer will be played at timestamp 0, and any subsequent AudioBuffer will be appended after all previous AudioBuffers.
|
This source directly accepts instances of `AudioBuffer` as data, simplifying usage with the Web Audio API. The first AudioBuffer will be played at timestamp 0, and any subsequent AudioBuffer will be appended after all previous AudioBuffers.
|
||||||
|
|
||||||
```ts
|
```ts
|
||||||
import { AudioBufferSource, QUALITY_MEDIUM } from 'mediakit';
|
import { AudioBufferSource, QUALITY_MEDIUM } from 'mediabunny';
|
||||||
|
|
||||||
const bufferSource = new AudioBufferSource({
|
const bufferSource = new AudioBufferSource({
|
||||||
codec: 'opus',
|
codec: 'opus',
|
||||||
@@ -306,7 +306,7 @@ await bufferSource.add(audioBuffer3);
|
|||||||
This is a source for use with the [Media Capture and Streams API](https://developer.mozilla.org/en-US/docs/Web/API/Media_Capture_and_Streams_API). Use this source if you want to pipe a real-time audio source (such as a microphone or audio from the user's computer) to an output file.
|
This is a source for use with the [Media Capture and Streams API](https://developer.mozilla.org/en-US/docs/Web/API/Media_Capture_and_Streams_API). Use this source if you want to pipe a real-time audio source (such as a microphone or audio from the user's computer) to an output file.
|
||||||
|
|
||||||
```ts
|
```ts
|
||||||
import { MediaStreamAudioTrackSource } from 'mediakit';
|
import { MediaStreamAudioTrackSource } from 'mediabunny';
|
||||||
|
|
||||||
// Get the user's microphone
|
// Get the user's microphone
|
||||||
const stream = await navigator.mediaDevices.getUserMedia({ audio: true });
|
const stream = await navigator.mediaDevices.getUserMedia({ audio: true });
|
||||||
@@ -329,7 +329,7 @@ If this source is the only MediaStreamTrack source in the `Output`, then the fir
|
|||||||
The most barebones of all audio sources, this source can be used to directly pipe [encoded packets](./packets-and-samples#encodedpacket) of audio data to the output. This source requires that you take care of the encoding process yourself, which enables you to use the WebCodecs API manually or to plug in your own encoding stack. Alternatively, you may retrieve the encoded packets directly by reading them from another media file, allowing you to skip decoding and reencoding audio data.
|
The most barebones of all audio sources, this source can be used to directly pipe [encoded packets](./packets-and-samples#encodedpacket) of audio data to the output. This source requires that you take care of the encoding process yourself, which enables you to use the WebCodecs API manually or to plug in your own encoding stack. Alternatively, you may retrieve the encoded packets directly by reading them from another media file, allowing you to skip decoding and reencoding audio data.
|
||||||
|
|
||||||
```ts
|
```ts
|
||||||
import { EncodedAudioPacketSource } from 'mediakit';
|
import { EncodedAudioPacketSource } from 'mediabunny';
|
||||||
|
|
||||||
// You must specify the codec name:
|
// You must specify the codec name:
|
||||||
const packetSource = new EncodedAudioPacketSource('aac');
|
const packetSource = new EncodedAudioPacketSource('aac');
|
||||||
@@ -360,7 +360,7 @@ Subtitle sources feed data to subtitle tracks on an `Output`. They all extend th
|
|||||||
This source feeds subtitle cues to the output from a text file in which the subtitles are defined.
|
This source feeds subtitle cues to the output from a text file in which the subtitles are defined.
|
||||||
|
|
||||||
```ts
|
```ts
|
||||||
import { TextSubtitleSource } from 'mediakit';
|
import { TextSubtitleSource } from 'mediabunny';
|
||||||
|
|
||||||
const textSource = new TextSubtitleSource('webvtt');
|
const textSource = new TextSubtitleSource('webvtt');
|
||||||
|
|
||||||
@@ -396,7 +396,7 @@ textSource.close();
|
|||||||
|
|
||||||
You can also add cues individually in small chunks:
|
You can also add cues individually in small chunks:
|
||||||
```ts
|
```ts
|
||||||
import { TextSubtitleSource } from 'mediakit';
|
import { TextSubtitleSource } from 'mediabunny';
|
||||||
|
|
||||||
const textSource = new TextSubtitleSource('webvtt');
|
const textSource = new TextSubtitleSource('webvtt');
|
||||||
|
|
||||||
|
|||||||
@@ -2,7 +2,7 @@
|
|||||||
|
|
||||||
## Introduction
|
## Introduction
|
||||||
|
|
||||||
An _output format_ specifies the container format of the data written by an `Output`. Mediakit supports many commonly used container formats, each having format-specific options.
|
An _output format_ specifies the container format of the data written by an `Output`. Mediabunny supports many commonly used container formats, each having format-specific options.
|
||||||
|
|
||||||
Many formats also offer *data callbacks*, which are special callbacks that fire for specific data regions in the output file.
|
Many formats also offer *data callbacks*, which are special callbacks that fire for specific data regions in the output file.
|
||||||
|
|
||||||
@@ -45,7 +45,7 @@ type TrackCountLimits = {
|
|||||||
|
|
||||||
This output format creates MP4 files.
|
This output format creates MP4 files.
|
||||||
```ts
|
```ts
|
||||||
import { Output, Mp4OutputFormat } from 'mediakit';
|
import { Output, Mp4OutputFormat } from 'mediabunny';
|
||||||
|
|
||||||
const output = new Output({
|
const output = new Output({
|
||||||
format: new Mp4OutputFormat(options),
|
format: new Mp4OutputFormat(options),
|
||||||
@@ -99,7 +99,7 @@ type IsobmffOutputFormatOptions = {
|
|||||||
|
|
||||||
This output format creates QuickTime files (.mov).
|
This output format creates QuickTime files (.mov).
|
||||||
```ts
|
```ts
|
||||||
import { Output, MovOutputFormat } from 'mediakit';
|
import { Output, MovOutputFormat } from 'mediabunny';
|
||||||
|
|
||||||
const output = new Output({
|
const output = new Output({
|
||||||
format: new MovOutputFormat(options),
|
format: new MovOutputFormat(options),
|
||||||
@@ -113,7 +113,7 @@ The available options are the same `IsobmffOutputFormatOptions` used by [MP4](#m
|
|||||||
|
|
||||||
This output format creates WebM files.
|
This output format creates WebM files.
|
||||||
```ts
|
```ts
|
||||||
import { Output, WebmOutputFormat } from 'mediakit';
|
import { Output, WebmOutputFormat } from 'mediabunny';
|
||||||
|
|
||||||
const output = new Output({
|
const output = new Output({
|
||||||
format: new WebmOutputFormat(options),
|
format: new WebmOutputFormat(options),
|
||||||
@@ -150,7 +150,7 @@ type MkvOutputFormatOptions = {
|
|||||||
|
|
||||||
This output format creates Matroska files (.mkv).
|
This output format creates Matroska files (.mkv).
|
||||||
```ts
|
```ts
|
||||||
import { Output, MkvOutputFormat } from 'mediakit';
|
import { Output, MkvOutputFormat } from 'mediabunny';
|
||||||
|
|
||||||
const output = new Output({
|
const output = new Output({
|
||||||
format: new MkvOutputFormat(options),
|
format: new MkvOutputFormat(options),
|
||||||
@@ -164,7 +164,7 @@ The available options are the same `MkvOutputFormatOptions` used by [WebM](#webm
|
|||||||
|
|
||||||
This output format creates Ogg files.
|
This output format creates Ogg files.
|
||||||
```ts
|
```ts
|
||||||
import { Output, OggOutputFormat } from 'mediakit';
|
import { Output, OggOutputFormat } from 'mediabunny';
|
||||||
|
|
||||||
const output = new Output({
|
const output = new Output({
|
||||||
format: new OggOutputFormat(options),
|
format: new OggOutputFormat(options),
|
||||||
@@ -189,7 +189,7 @@ type OggOutputFormatOptions = {
|
|||||||
|
|
||||||
This output format creates MP3 files.
|
This output format creates MP3 files.
|
||||||
```ts
|
```ts
|
||||||
import { Output, Mp3OutputFormat } from 'mediakit';
|
import { Output, Mp3OutputFormat } from 'mediabunny';
|
||||||
|
|
||||||
const output = new Output({
|
const output = new Output({
|
||||||
format: new Mp3OutputFormat(options),
|
format: new Mp3OutputFormat(options),
|
||||||
@@ -210,7 +210,7 @@ type Mp3OutputFormatOptions = {
|
|||||||
|
|
||||||
This output format creates WAVE (.wav) files.
|
This output format creates WAVE (.wav) files.
|
||||||
```ts
|
```ts
|
||||||
import { Output, WavOutputFormat } from 'mediakit';
|
import { Output, WavOutputFormat } from 'mediabunny';
|
||||||
|
|
||||||
const output = new Output({
|
const output = new Output({
|
||||||
format: new WavOutputFormat(options),
|
format: new WavOutputFormat(options),
|
||||||
|
|||||||
@@ -2,7 +2,7 @@
|
|||||||
|
|
||||||
## Introduction
|
## Introduction
|
||||||
|
|
||||||
Media data in Mediakit is present in two different forms:
|
Media data in Mediabunny is present in two different forms:
|
||||||
|
|
||||||
- **Packet:** Encoded media data, the result of an encoding process
|
- **Packet:** Encoded media data, the result of an encoding process
|
||||||
- **Sample:** Raw, uncompressed, presentable media data
|
- **Sample:** Raw, uncompressed, presentable media data
|
||||||
@@ -30,7 +30,7 @@ flowchart LR
|
|||||||
|
|
||||||
### Connection to WebCodecs
|
### Connection to WebCodecs
|
||||||
|
|
||||||
Packets and samples in Mediakit correspond directly with concepts of the [WebCodecs API](https://w3c.github.io/webcodecs/):
|
Packets and samples in Mediabunny correspond directly with concepts of the [WebCodecs API](https://w3c.github.io/webcodecs/):
|
||||||
- `EncodedPacket`\
|
- `EncodedPacket`\
|
||||||
-> `EncodedVideoChunk` for video packets\
|
-> `EncodedVideoChunk` for video packets\
|
||||||
-> `EncodedAudioChunk` for audio packets
|
-> `EncodedAudioChunk` for audio packets
|
||||||
@@ -39,14 +39,14 @@ Packets and samples in Mediakit correspond directly with concepts of the [WebCod
|
|||||||
- `AudioSample`
|
- `AudioSample`
|
||||||
-> `AudioData`
|
-> `AudioData`
|
||||||
|
|
||||||
Since Mediakit makes heavy use of WebCodecs API, its own classes are typically used as wrappers around the WebCodecs classes. However, this wrapping comes with a few benefits:
|
Since Mediabunny makes heavy use of WebCodecs API, its own classes are typically used as wrappers around the WebCodecs classes. However, this wrapping comes with a few benefits:
|
||||||
1. **Independence:** This library remains functional even if the WebCodecs API isn't available. Encoders and decoders can be polyfilled using [custom coders](./supported-formats-and-codecs#custom-coders), and the library can run in non-browser contexts such as Node.js.
|
1. **Independence:** This library remains functional even if the WebCodecs API isn't available. Encoders and decoders can be polyfilled using [custom coders](./supported-formats-and-codecs#custom-coders), and the library can run in non-browser contexts such as Node.js.
|
||||||
1. **Extensibility:** The wrappers serve as a namespace for additional operations, such as `toAudioBuffer()` on `AudioSample`, or `draw()` on `VideoSample`.
|
1. **Extensibility:** The wrappers serve as a namespace for additional operations, such as `toAudioBuffer()` on `AudioSample`, or `draw()` on `VideoSample`.
|
||||||
1. **Consistency:** While WebCodecs uses integer microsecond timestamps, Mediakit uses floating-point second timestamps everywhere. With these wrappers, all timing information is always in seconds and the user doesn't need to think about unit conversions.
|
1. **Consistency:** While WebCodecs uses integer microsecond timestamps, Mediabunny uses floating-point second timestamps everywhere. With these wrappers, all timing information is always in seconds and the user doesn't need to think about unit conversions.
|
||||||
|
|
||||||
Conversion is easy:
|
Conversion is easy:
|
||||||
```ts
|
```ts
|
||||||
import { EncodedPacket, VideoSample, AudioSample } from 'mediakit';
|
import { EncodedPacket, VideoSample, AudioSample } from 'mediabunny';
|
||||||
|
|
||||||
// EncodedPacket to WebCodecs chunks:
|
// EncodedPacket to WebCodecs chunks:
|
||||||
encodedPacket.toEncodedVideoChunk(); // => EncodedVideoChunk
|
encodedPacket.toEncodedVideoChunk(); // => EncodedVideoChunk
|
||||||
@@ -100,7 +100,7 @@ You probably won't ever need to set `sequenceNumber` or `byteLength` in the cons
|
|||||||
|
|
||||||
For example, here we're creating a packet from some encoded video data:
|
For example, here we're creating a packet from some encoded video data:
|
||||||
```ts
|
```ts
|
||||||
import { EncodedPacket } from 'mediakit';
|
import { EncodedPacket } from 'mediabunny';
|
||||||
|
|
||||||
const encodedVideoData = new Uint8Array([...]);
|
const encodedVideoData = new Uint8Array([...]);
|
||||||
const encodedPacket = new EncodedPacket(encodedVideoData, 'key', 5, 1/24);
|
const encodedPacket = new EncodedPacket(encodedVideoData, 'key', 5, 1/24);
|
||||||
@@ -108,7 +108,7 @@ const encodedPacket = new EncodedPacket(encodedVideoData, 'key', 5, 1/24);
|
|||||||
|
|
||||||
Alternatively, if you're coming from WebCodecs encoded chunks, you can create an `EncodedPacket` from them:
|
Alternatively, if you're coming from WebCodecs encoded chunks, you can create an `EncodedPacket` from them:
|
||||||
```ts
|
```ts
|
||||||
import { EncodedPacket } from 'mediakit';
|
import { EncodedPacket } from 'mediabunny';
|
||||||
|
|
||||||
// From EncodedVideoChunk:
|
// From EncodedVideoChunk:
|
||||||
const encodedPacket = EncodedPacket.fromEncodedChunk(encodedVideoChunk);
|
const encodedPacket = EncodedPacket.fromEncodedChunk(encodedVideoChunk);
|
||||||
@@ -214,7 +214,7 @@ The constructor of `VideoSample` is very similar to [`VideoFrame`'s constructor]
|
|||||||
This constructor creates a `VideoSample` from a `CanvasImageSource`:
|
This constructor creates a `VideoSample` from a `CanvasImageSource`:
|
||||||
|
|
||||||
```ts
|
```ts
|
||||||
import { VideoSample } from 'mediakit';
|
import { VideoSample } from 'mediabunny';
|
||||||
|
|
||||||
// Creates a sample from a canvas element
|
// Creates a sample from a canvas element
|
||||||
const sample = new VideoSample(canvas, {
|
const sample = new VideoSample(canvas, {
|
||||||
@@ -237,7 +237,7 @@ const sample = new VideoSample(videoFrame);
|
|||||||
This constructor creates a `VideoSample` from raw pixel data given in an `ArrayBuffer`:
|
This constructor creates a `VideoSample` from raw pixel data given in an `ArrayBuffer`:
|
||||||
|
|
||||||
```ts
|
```ts
|
||||||
import { VideoSample } from 'mediakit';
|
import { VideoSample } from 'mediabunny';
|
||||||
|
|
||||||
// Creates a sample from pixel data in the RGBX format
|
// Creates a sample from pixel data in the RGBX format
|
||||||
const sample = new VideoSample(buffer, {
|
const sample = new VideoSample(buffer, {
|
||||||
@@ -382,7 +382,7 @@ An audio sample represents a section of audio data. It can be created directly f
|
|||||||
Audio samples can be constructed either from an `AudioData` instance or an initialization object:
|
Audio samples can be constructed either from an `AudioData` instance or an initialization object:
|
||||||
|
|
||||||
```ts
|
```ts
|
||||||
import { AudioSample } from 'mediakit';
|
import { AudioSample } from 'mediabunny';
|
||||||
|
|
||||||
// From AudioData:
|
// From AudioData:
|
||||||
const sample = new AudioSample(audioData);
|
const sample = new AudioSample(audioData);
|
||||||
@@ -502,7 +502,7 @@ for (let i = 0; i < audioSample.numberOfChannels; i++) {
|
|||||||
```
|
```
|
||||||
|
|
||||||
::: info
|
::: info
|
||||||
The behavior of `allocationSize` and `copyTo` exactly mirrors that of the WebCodecs API. However, the WebCodecs API specification only mandates support for converting to `f32-planar`, while Mediakit's implementation supports conversion into all formats. Therefore, Mediakit's methods are more powerful.
|
The behavior of `allocationSize` and `copyTo` exactly mirrors that of the WebCodecs API. However, the WebCodecs API specification only mandates support for converting to `f32-planar`, while Mediabunny's implementation supports conversion into all formats. Therefore, Mediabunny's methods are more powerful.
|
||||||
:::
|
:::
|
||||||
|
|
||||||
### Closing audio samples
|
### Closing audio samples
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
# Reading media files
|
# Reading media files
|
||||||
|
|
||||||
Mediakit allows you to read media files with great control and efficiency. You can use it to extract metadata (such as duration or resolution), as well as to read actual media data from video and audio tracks with frame-accurate timing. Many commonly used [input file formats](./input-formats) are supported. Using [input sources](#input-sources), data can be read from multiple sources, such as directly from memory, from the user's disk, or even over the network.
|
Mediabunny allows you to read media files with great control and efficiency. You can use it to extract metadata (such as duration or resolution), as well as to read actual media data from video and audio tracks with frame-accurate timing. Many commonly used [input file formats](./input-formats) are supported. Using [input sources](#input-sources), data can be read from multiple sources, such as directly from memory, from the user's disk, or even over the network.
|
||||||
|
|
||||||
Files are always read partially ("lazily"), meaning only the bytes required to extract the requested information will be read, keeping performance high and memory usage low. Therefore, most methods for reading data are asynchronous and return promises.
|
Files are always read partially ("lazily"), meaning only the bytes required to extract the requested information will be read, keeping performance high and memory usage low. Therefore, most methods for reading data are asynchronous and return promises.
|
||||||
|
|
||||||
@@ -10,11 +10,11 @@ Not all data is extracted equally. Methods that are prefixed with `compute` inst
|
|||||||
|
|
||||||
## Creating a new input
|
## Creating a new input
|
||||||
|
|
||||||
Reading media files in Mediakit revolves around a central class, `Input`, from which all reading operations begin. One instance of `Input` represents one media file that we want to read.
|
Reading media files in Mediabunny revolves around a central class, `Input`, from which all reading operations begin. One instance of `Input` represents one media file that we want to read.
|
||||||
|
|
||||||
Start by creating a new instance of `Input`. Here, we're creating it with a [File](https://developer.mozilla.org/en-US/docs/Web/API/File) instance, meaning we'll be reading data directly from the user's disk:
|
Start by creating a new instance of `Input`. Here, we're creating it with a [File](https://developer.mozilla.org/en-US/docs/Web/API/File) instance, meaning we'll be reading data directly from the user's disk:
|
||||||
```ts
|
```ts
|
||||||
import { Input, ALL_FORMATS, BlobSource } from 'mediakit';
|
import { Input, ALL_FORMATS, BlobSource } from 'mediabunny';
|
||||||
|
|
||||||
const input = new Input({
|
const input = new Input({
|
||||||
formats: ALL_FORMATS,
|
formats: ALL_FORMATS,
|
||||||
@@ -24,9 +24,9 @@ const input = new Input({
|
|||||||
|
|
||||||
`source` specifies where the `Input` reads data from. See [Input sources](#input-sources) for a full list of available input sources.
|
`source` specifies where the `Input` reads data from. See [Input sources](#input-sources) for a full list of available input sources.
|
||||||
|
|
||||||
`formats` specifies the list of formats that the `Input` should support. This field is mainly used for tree shaking optimizations: Using `ALL_FORMATS` means we can load files of [any format that Mediakit supports](./supported-formats-and-codecs#container-formats), but requires that we include the parsers for each of these formats. If we know we'll only be reading MP3 or WAVE files, then something like this will reduce the overall bundle size drastically:
|
`formats` specifies the list of formats that the `Input` should support. This field is mainly used for tree shaking optimizations: Using `ALL_FORMATS` means we can load files of [any format that Mediabunny supports](./supported-formats-and-codecs#container-formats), but requires that we include the parsers for each of these formats. If we know we'll only be reading MP3 or WAVE files, then something like this will reduce the overall bundle size drastically:
|
||||||
```ts
|
```ts
|
||||||
import { Input, MP3, WAVE } from 'mediakit';
|
import { Input, MP3, WAVE } from 'mediabunny';
|
||||||
|
|
||||||
const input = new Input({
|
const input = new Input({
|
||||||
formats: [MP3, WAVE],
|
formats: [MP3, WAVE],
|
||||||
@@ -105,7 +105,7 @@ You can query metadata related to the track's codec:
|
|||||||
```ts
|
```ts
|
||||||
track.codec; // => MediaCodec | null
|
track.codec; // => MediaCodec | null
|
||||||
```
|
```
|
||||||
This field is `null` when the track's codec couldn't be recognized or is not supported by Mediakit. See [Codecs](./supported-formats-and-codecs#codecs) for the full list of supported codecs.
|
This field is `null` when the track's codec couldn't be recognized or is not supported by Mediabunny. See [Codecs](./supported-formats-and-codecs#codecs) for the full list of supported codecs.
|
||||||
|
|
||||||
You can also extract the full codec parameter string from the track, as specified in the [WebCodecs Codec Registry](https://www.w3.org/TR/webcodecs-codec-registry/):
|
You can also extract the full codec parameter string from the track, as specified in the [WebCodecs Codec Registry](https://www.w3.org/TR/webcodecs-codec-registry/):
|
||||||
```ts
|
```ts
|
||||||
@@ -272,7 +272,7 @@ For example, here's the decoder configuration for an AAC audio track:
|
|||||||
|
|
||||||
## Reading media data
|
## Reading media data
|
||||||
|
|
||||||
Mediakit has the concept of *media sinks*, which are the way to read media data from an `InputTrack`. Media sinks differ in their API and in their level of abstraction, meaning you can pick whichever sink best fits your use case.
|
Mediabunny has the concept of *media sinks*, which are the way to read media data from an `InputTrack`. Media sinks differ in their API and in their level of abstraction, meaning you can pick whichever sink best fits your use case.
|
||||||
|
|
||||||
See [Media sinks](./media-sinks) for a full list of sinks.
|
See [Media sinks](./media-sinks) for a full list of sinks.
|
||||||
|
|
||||||
@@ -280,7 +280,7 @@ See [Media sinks](./media-sinks) for a full list of sinks.
|
|||||||
|
|
||||||
Here we iterate over all samples (frames) of a video track:
|
Here we iterate over all samples (frames) of a video track:
|
||||||
```ts
|
```ts
|
||||||
import { VideoSampleSink } from 'mediakit';
|
import { VideoSampleSink } from 'mediabunny';
|
||||||
|
|
||||||
const videoTrack = await input.getPrimaryVideoTrack();
|
const videoTrack = await input.getPrimaryVideoTrack();
|
||||||
const sink = new VideoSampleSink(videoTrack);
|
const sink = new VideoSampleSink(videoTrack);
|
||||||
@@ -304,7 +304,7 @@ await sink.getSample(42);
|
|||||||
|
|
||||||
We may want to extract downscaled thumbnails from a video track:
|
We may want to extract downscaled thumbnails from a video track:
|
||||||
```ts
|
```ts
|
||||||
import { CanvasSink } from 'mediakit';
|
import { CanvasSink } from 'mediabunny';
|
||||||
|
|
||||||
const videoTrack = await input.getPrimaryVideoTrack();
|
const videoTrack = await input.getPrimaryVideoTrack();
|
||||||
const sink = new CanvasSink(videoTrack, {
|
const sink = new CanvasSink(videoTrack, {
|
||||||
@@ -327,7 +327,7 @@ for await (const result of sink.canvasesAtTimestamps(thumbnailTimestamps)) {
|
|||||||
|
|
||||||
We may loop over a section of an audio track and play it using the Web Audio API:
|
We may loop over a section of an audio track and play it using the Web Audio API:
|
||||||
```ts
|
```ts
|
||||||
import { AudioBufferSink } from 'mediakit';
|
import { AudioBufferSink } from 'mediabunny';
|
||||||
|
|
||||||
const audioTrack = await input.getPrimaryAudioTrack();
|
const audioTrack = await input.getPrimaryAudioTrack();
|
||||||
const sink = new AudioBufferSink(audioTrack);
|
const sink = new AudioBufferSink(audioTrack);
|
||||||
@@ -342,7 +342,7 @@ for await (const { buffer, timestamp } of sink.buffers(5, 10)) {
|
|||||||
|
|
||||||
Or we may take the decoding process into our own hands:
|
Or we may take the decoding process into our own hands:
|
||||||
```ts
|
```ts
|
||||||
import { EncodedPacketSink } from 'mediakit';
|
import { EncodedPacketSink } from 'mediabunny';
|
||||||
|
|
||||||
const videoTrack = await input.getPrimaryVideoTrack();
|
const videoTrack = await input.getPrimaryVideoTrack();
|
||||||
const sink = new EncodedPacketSink(videoTrack);
|
const sink = new EncodedPacketSink(videoTrack);
|
||||||
@@ -384,7 +384,7 @@ This library offers a couple of sources:
|
|||||||
|
|
||||||
This source uses an in-memory `ArrayBuffer` as the underlying source of data.
|
This source uses an in-memory `ArrayBuffer` as the underlying source of data.
|
||||||
```ts
|
```ts
|
||||||
import { BufferSource } from 'mediakit';
|
import { BufferSource } from 'mediabunny';
|
||||||
|
|
||||||
// You can construct a BufferSource directly from ArrayBuffer:
|
// You can construct a BufferSource directly from ArrayBuffer:
|
||||||
const source = new BufferSource(arrayBuffer);
|
const source = new BufferSource(arrayBuffer);
|
||||||
@@ -399,7 +399,7 @@ This source is the fastest but requires the entire input file to be held in memo
|
|||||||
|
|
||||||
This source is backed by an underlying [`Blob`](https://developer.mozilla.org/en-US/docs/Web/API/Blob) object. Since [`File`](https://developer.mozilla.org/en-US/docs/Web/API/File) extends `Blob`, this source is perfect for reading data directly from disk.
|
This source is backed by an underlying [`Blob`](https://developer.mozilla.org/en-US/docs/Web/API/Blob) object. Since [`File`](https://developer.mozilla.org/en-US/docs/Web/API/File) extends `Blob`, this source is perfect for reading data directly from disk.
|
||||||
```ts
|
```ts
|
||||||
import { BlobSource } from 'mediakit';
|
import { BlobSource } from 'mediabunny';
|
||||||
|
|
||||||
fileInput.addEventListener('change', (event) => {
|
fileInput.addEventListener('change', (event) => {
|
||||||
const file = event.target.files[0];
|
const file = event.target.files[0];
|
||||||
@@ -417,7 +417,7 @@ It still works, but keep in mind it's going to be much higher-latency than readi
|
|||||||
|
|
||||||
This source fetches data from a URL. This is useful for reading files over the network.
|
This source fetches data from a URL. This is useful for reading files over the network.
|
||||||
```ts
|
```ts
|
||||||
import { UrlSource } from 'mediakit';
|
import { UrlSource } from 'mediabunny';
|
||||||
|
|
||||||
const source = new UrlSource('https://example.com/bigbuckbunny.mp4');
|
const source = new UrlSource('https://example.com/bigbuckbunny.mp4');
|
||||||
```
|
```
|
||||||
@@ -461,7 +461,7 @@ This is a general-purpose input source you can use to read data from anywhere. A
|
|||||||
|
|
||||||
For example, here we're reading a file from disk using the Node.js file system:
|
For example, here we're reading a file from disk using the Node.js file system:
|
||||||
```ts
|
```ts
|
||||||
import { StreamSource } from 'mediakit';
|
import { StreamSource } from 'mediabunny';
|
||||||
import { open } from 'node:fs/promises';
|
import { open } from 'node:fs/promises';
|
||||||
|
|
||||||
const fileHandle = await open('bigbuckbunny.mp4', 'r');
|
const fileHandle = await open('bigbuckbunny.mp4', 'r');
|
||||||
|
|||||||
@@ -2,7 +2,7 @@
|
|||||||
|
|
||||||
## Container formats
|
## Container formats
|
||||||
|
|
||||||
Mediakit supports many commonly used media container formats, all of which are supported bidirectionally (reading & writing):
|
Mediabunny supports many commonly used media container formats, all of which are supported bidirectionally (reading & writing):
|
||||||
|
|
||||||
- ISOBMFF-based formats (.mp4, .m4v, .m4a, ...)
|
- ISOBMFF-based formats (.mp4, .m4v, .m4a, ...)
|
||||||
- QuickTime File Format (.mov)
|
- QuickTime File Format (.mov)
|
||||||
@@ -14,12 +14,12 @@ Mediakit supports many commonly used media container formats, all of which are s
|
|||||||
|
|
||||||
## Codecs
|
## Codecs
|
||||||
|
|
||||||
Mediakit supports a wide range of video, audio, and subtitle codecs. More specifically, it supports all codecs specified by the WebCodecs API and a few additional PCM codecs out of the box.
|
Mediabunny supports a wide range of video, audio, and subtitle codecs. More specifically, it supports all codecs specified by the WebCodecs API and a few additional PCM codecs out of the box.
|
||||||
|
|
||||||
The availability of the codecs provided by the WebCodecs API depends on the browser and thus cannot be guaranteed by this library. Mediakit provides [special utility functions](#querying-codec-encodability) to check which codecs are able to be encoded. You can also specify [custom coders](#custom-coders) to provide your own encoder/decoder implementation if the browser doesn't support the codec natively.
|
The availability of the codecs provided by the WebCodecs API depends on the browser and thus cannot be guaranteed by this library. Mediabunny provides [special utility functions](#querying-codec-encodability) to check which codecs are able to be encoded. You can also specify [custom coders](#custom-coders) to provide your own encoder/decoder implementation if the browser doesn't support the codec natively.
|
||||||
|
|
||||||
::: info
|
::: info
|
||||||
Mediakit ships with built-in decoders and encoders for all audio PCM codecs, meaning they are always supported.
|
Mediabunny ships with built-in decoders and encoders for all audio PCM codecs, meaning they are always supported.
|
||||||
:::
|
:::
|
||||||
|
|
||||||
### Video codecs
|
### Video codecs
|
||||||
@@ -94,12 +94,12 @@ Not all codecs can be used with all containers. The following table specifies th
|
|||||||
|
|
||||||
## Querying codec encodability
|
## Querying codec encodability
|
||||||
|
|
||||||
Mediakit provides utility functions that you can use to check if the browser can encode a given codec. Additionally, you
|
Mediabunny provides utility functions that you can use to check if the browser can encode a given codec. Additionally, you
|
||||||
can check if a codec is encodable with a specific _configuration_.
|
can check if a codec is encodable with a specific _configuration_.
|
||||||
|
|
||||||
`canEncode` tests whether a codec can be encoded using typical settings:
|
`canEncode` tests whether a codec can be encoded using typical settings:
|
||||||
```ts
|
```ts
|
||||||
import { canEncode } from 'mediakit';
|
import { canEncode } from 'mediabunny';
|
||||||
|
|
||||||
canEncode('avc'); // => Promise<boolean>
|
canEncode('avc'); // => Promise<boolean>
|
||||||
canEncode('opus'); // => Promise<boolean>
|
canEncode('opus'); // => Promise<boolean>
|
||||||
@@ -108,7 +108,7 @@ Video codecs are checked using 1280x720 @1Mbps, while audio codecs are checked u
|
|||||||
|
|
||||||
You can also check encodability using specific configurations:
|
You can also check encodability using specific configurations:
|
||||||
```ts
|
```ts
|
||||||
import { canEncodeVideo, canEncodeAudio } from 'mediakit';
|
import { canEncodeVideo, canEncodeAudio } from 'mediabunny';
|
||||||
|
|
||||||
canEncodeVideo('hevc', {
|
canEncodeVideo('hevc', {
|
||||||
width: 1920, height: 1080, bitrate: 1e7
|
width: 1920, height: 1080, bitrate: 1e7
|
||||||
@@ -128,7 +128,7 @@ import {
|
|||||||
getEncodableVideoCodecs,
|
getEncodableVideoCodecs,
|
||||||
getEncodableAudioCodecs,
|
getEncodableAudioCodecs,
|
||||||
getEncodableSubtitleCodecs,
|
getEncodableSubtitleCodecs,
|
||||||
} from 'mediakit';
|
} from 'mediabunny';
|
||||||
|
|
||||||
getEncodableCodecs(); // => Promise<MediaCodec[]>
|
getEncodableCodecs(); // => Promise<MediaCodec[]>
|
||||||
getEncodableVideoCodecs(); // => Promise<VideoCodec[]>
|
getEncodableVideoCodecs(); // => Promise<VideoCodec[]>
|
||||||
@@ -151,7 +151,7 @@ import {
|
|||||||
getFirstEncodableVideoCodec,
|
getFirstEncodableVideoCodec,
|
||||||
getFirstEncodableAudioCodec,
|
getFirstEncodableAudioCodec,
|
||||||
getFirstEncodableSubtitleCodec,
|
getFirstEncodableSubtitleCodec,
|
||||||
} from 'mediakit';
|
} from 'mediabunny';
|
||||||
|
|
||||||
getFirstEncodableVideoCodec(['avc', 'vp9', 'av1']); // => Promise<VideoCodec | null>
|
getFirstEncodableVideoCodec(['avc', 'vp9', 'av1']); // => Promise<VideoCodec | null>
|
||||||
getFirstEncodableAudioCodec(['opus', 'aac']); // => Promise<AudioCodec | null>
|
getFirstEncodableAudioCodec(['opus', 'aac']); // => Promise<AudioCodec | null>
|
||||||
@@ -169,7 +169,7 @@ These functions are especially useful in conjunction with an [output format](./o
|
|||||||
import {
|
import {
|
||||||
Mp4OutputFormat,
|
Mp4OutputFormat,
|
||||||
getFirstEncodableVideoCodec,
|
getFirstEncodableVideoCodec,
|
||||||
} from 'mediakit';
|
} from 'mediabunny';
|
||||||
|
|
||||||
const outputFormat = new Mp4OutputFormat();
|
const outputFormat = new Mp4OutputFormat();
|
||||||
const containableVideoCodecs = outputFormat.getSupportedVideoCodecs();
|
const containableVideoCodecs = outputFormat.getSupportedVideoCodecs();
|
||||||
@@ -186,19 +186,19 @@ Whether a codec can be decoded depends on the specific codec configuration of an
|
|||||||
|
|
||||||
## Custom coders
|
## Custom coders
|
||||||
|
|
||||||
Mediakit allows you to register your own custom encoders and decoders - useful if you want to polyfill a codec that's not supported in all browsers, or want to use Mediakit outside of an environment with WebCodecs (such as Node.js).
|
Mediabunny allows you to register your own custom encoders and decoders - useful if you want to polyfill a codec that's not supported in all browsers, or want to use Mediabunny outside of an environment with WebCodecs (such as Node.js).
|
||||||
|
|
||||||
Encoders and decoders can be registered for [all video and audio codecs](#codecs) supported by the library. It is not possible to add new codecs.
|
Encoders and decoders can be registered for [all video and audio codecs](#codecs) supported by the library. It is not possible to add new codecs.
|
||||||
|
|
||||||
::: warning
|
::: warning
|
||||||
Mediakit requires customs encoders and decoders to follow very specific implementation rules. Pay special attention to the parts labeled with "**must**" to ensure compatibility.
|
Mediabunny requires customs encoders and decoders to follow very specific implementation rules. Pay special attention to the parts labeled with "**must**" to ensure compatibility.
|
||||||
:::
|
:::
|
||||||
|
|
||||||
### Custom encoders
|
### Custom encoders
|
||||||
|
|
||||||
To create a custom video or audio encoder, you'll need to create a class which extends `CustomVideoEncoder` or `CustomAudioEncoder`. Then, you **must** register this class using `registerEncoder`:
|
To create a custom video or audio encoder, you'll need to create a class which extends `CustomVideoEncoder` or `CustomAudioEncoder`. Then, you **must** register this class using `registerEncoder`:
|
||||||
```ts
|
```ts
|
||||||
import { CustomAudioEncoder, registerEncoder } from 'mediakit';
|
import { CustomAudioEncoder, registerEncoder } from 'mediabunny';
|
||||||
|
|
||||||
class MyAwesomeMp3Encoder extends CustomAudioEncoder {
|
class MyAwesomeMp3Encoder extends CustomAudioEncoder {
|
||||||
// ...
|
// ...
|
||||||
@@ -261,7 +261,7 @@ The packets passed to `onPacket` **must** be in [decode order](./media-sinks.md#
|
|||||||
|
|
||||||
To create a custom video or audio decoder, you'll need to create a class which extends `CustomVideoDecoder` or `CustomAudioDecoder`. Then, you **must** register this class using `registerDecoder`:
|
To create a custom video or audio decoder, you'll need to create a class which extends `CustomVideoDecoder` or `CustomAudioDecoder`. Then, you **must** register this class using `registerDecoder`:
|
||||||
```ts
|
```ts
|
||||||
import { CustomAudioDecoder, registerDecoder } from 'mediakit';
|
import { CustomAudioDecoder, registerDecoder } from 'mediabunny';
|
||||||
|
|
||||||
class MyAwesomeMp3Decoder extends CustomAudioDecoder {
|
class MyAwesomeMp3Decoder extends CustomAudioDecoder {
|
||||||
// ...
|
// ...
|
||||||
|
|||||||
@@ -1,16 +1,16 @@
|
|||||||
# Writing media files
|
# Writing media files
|
||||||
|
|
||||||
Mediakit enables you to create media files with very fine levels of control. You can add an arbitrary number of video, audio and subtitle tracks to a media file, and precisely control the timing of media data. This library supports [many output file formats](./output-formats). Using [output targets](#output-targets), you can decide if you want to build up the entire file in memory or stream it out in chunks as it's being created - allowing you to create very large files.
|
Mediabunny enables you to create media files with very fine levels of control. You can add an arbitrary number of video, audio and subtitle tracks to a media file, and precisely control the timing of media data. This library supports [many output file formats](./output-formats). Using [output targets](#output-targets), you can decide if you want to build up the entire file in memory or stream it out in chunks as it's being created - allowing you to create very large files.
|
||||||
|
|
||||||
Mediakit provides many ways to supply media data for output tracks, nicely integrating with the WebCodecs API, but also allowing you to use your own encoding stack if you wish. These [media sources](./media-sources) come in multiple levels of abstraction, enabling easy use for common use cases while still giving you fine-grained control if you need it.
|
Mediabunny provides many ways to supply media data for output tracks, nicely integrating with the WebCodecs API, but also allowing you to use your own encoding stack if you wish. These [media sources](./media-sources) come in multiple levels of abstraction, enabling easy use for common use cases while still giving you fine-grained control if you need it.
|
||||||
|
|
||||||
## Creating an output
|
## Creating an output
|
||||||
|
|
||||||
Media file creation in Mediakit revolves around a central class, `Output`. One instance of `Output` represents one media file you want to create.
|
Media file creation in Mediabunny revolves around a central class, `Output`. One instance of `Output` represents one media file you want to create.
|
||||||
|
|
||||||
Start by creating a new instance of `Output` using the desired configuration of the file you want to create:
|
Start by creating a new instance of `Output` using the desired configuration of the file you want to create:
|
||||||
```ts
|
```ts
|
||||||
import { Output, Mp4OutputFormat, BufferTarget } from 'mediakit';
|
import { Output, Mp4OutputFormat, BufferTarget } from 'mediabunny';
|
||||||
|
|
||||||
// In this example, we'll be creating an MP4 file in memory:
|
// In this example, we'll be creating an MP4 file in memory:
|
||||||
const output = new Output({
|
const output = new Output({
|
||||||
@@ -82,7 +82,7 @@ As an example, let's add two tracks to our output:
|
|||||||
- An audio track driven by the user's microphone input, encoded using AAC
|
- An audio track driven by the user's microphone input, encoded using AAC
|
||||||
|
|
||||||
```ts
|
```ts
|
||||||
import { CanvasSource, MediaStreamAudioTrackSource } from 'mediakit';
|
import { CanvasSource, MediaStreamAudioTrackSource } from 'mediabunny';
|
||||||
|
|
||||||
// Assuming `canvasElement` exists
|
// Assuming `canvasElement` exists
|
||||||
const videoSource = new CanvasSource(canvasElement, {
|
const videoSource = new CanvasSource(canvasElement, {
|
||||||
@@ -202,7 +202,7 @@ The _output target_ determines where the data created by the `Output` will be wr
|
|||||||
|
|
||||||
This target writes all data to a single, contiguous, in-memory `ArrayBuffer`. This buffer will automatically grow as the file becomes larger. Usage is straightforward:
|
This target writes all data to a single, contiguous, in-memory `ArrayBuffer`. This buffer will automatically grow as the file becomes larger. Usage is straightforward:
|
||||||
```ts
|
```ts
|
||||||
import { Output, BufferTarget } from 'mediakit';
|
import { Output, BufferTarget } from 'mediabunny';
|
||||||
|
|
||||||
const output = new Output({
|
const output = new Output({
|
||||||
target: new BufferTarget(),
|
target: new BufferTarget(),
|
||||||
@@ -224,7 +224,7 @@ This target passes you the data written by the `Output` in small chunks, requiri
|
|||||||
|
|
||||||
`StreamTarget` makes use of the Streams API, meaning you'll need to pass it an instance of `WritableStream`:
|
`StreamTarget` makes use of the Streams API, meaning you'll need to pass it an instance of `WritableStream`:
|
||||||
```ts
|
```ts
|
||||||
import { Output, StreamTarget, StreamTargetChunk } from 'mediakit';
|
import { Output, StreamTarget, StreamTargetChunk } from 'mediabunny';
|
||||||
|
|
||||||
const writable = new WritableStream({
|
const writable = new WritableStream({
|
||||||
write(chunk: StreamTargetChunk) {
|
write(chunk: StreamTargetChunk) {
|
||||||
|
|||||||
@@ -7,7 +7,7 @@ import {
|
|||||||
Mp4OutputFormat,
|
Mp4OutputFormat,
|
||||||
Conversion,
|
Conversion,
|
||||||
QUALITY_VERY_LOW,
|
QUALITY_VERY_LOW,
|
||||||
} from 'mediakit';
|
} from 'mediabunny';
|
||||||
|
|
||||||
const selectMediaButton = document.querySelector('button') as HTMLButtonElement;
|
const selectMediaButton = document.querySelector('button') as HTMLButtonElement;
|
||||||
const fileNameElement = document.querySelector('#file-name') as HTMLParagraphElement;
|
const fileNameElement = document.querySelector('#file-name') as HTMLParagraphElement;
|
||||||
|
|||||||
@@ -4,7 +4,7 @@
|
|||||||
<meta charset="UTF-8">
|
<meta charset="UTF-8">
|
||||||
<meta http-equiv="X-UA-Compatible" content="IE=edge">
|
<meta http-equiv="X-UA-Compatible" content="IE=edge">
|
||||||
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||||||
<title>File compression example | Mediakit</title>
|
<title>File compression example | Mediabunny</title>
|
||||||
<script type="module" src="../base.ts"></script>
|
<script type="module" src="../base.ts"></script>
|
||||||
<script type="module" src="./file-compression.ts"></script>
|
<script type="module" src="./file-compression.ts"></script>
|
||||||
<link rel="stylesheet" href="../base.css">
|
<link rel="stylesheet" href="../base.css">
|
||||||
@@ -12,7 +12,7 @@
|
|||||||
|
|
||||||
<body class="flex flex-col items-center py-10 bg-zinc-50 text-zinc-800 dark:bg-zinc-900 dark:text-zinc-200 px-2">
|
<body class="flex flex-col items-center py-10 bg-zinc-50 text-zinc-800 dark:bg-zinc-900 dark:text-zinc-200 px-2">
|
||||||
<h1 class="text-3xl font-bold text-teal-800 dark:text-teal-200 text-center">File compression example</h1>
|
<h1 class="text-3xl font-bold text-teal-800 dark:text-teal-200 text-center">File compression example</h1>
|
||||||
<p class="max-w-lg text-center">Select or drop a media file, and Mediakit will convert it to a heavily-compressed MP4 file.</p>
|
<p class="max-w-lg text-center">Select or drop a media file, and Mediabunny will convert it to a heavily-compressed MP4 file.</p>
|
||||||
|
|
||||||
<div class="flex gap-2 mt-4">
|
<div class="flex gap-2 mt-4">
|
||||||
<button class="rounded-lg bg-zinc-200 dark:bg-zinc-750 hover:bg-zinc-300 dark:hover:bg-zinc-700 px-5 py-2">
|
<button class="rounded-lg bg-zinc-200 dark:bg-zinc-750 hover:bg-zinc-300 dark:hover:bg-zinc-700 px-5 py-2">
|
||||||
@@ -38,8 +38,8 @@
|
|||||||
<p class="text-xs font-medium mt-1" id="compression-facts" style="display: none;"></p>
|
<p class="text-xs font-medium mt-1" id="compression-facts" style="display: none;"></p>
|
||||||
|
|
||||||
<div class="fixed top-0 left-0 flex gap-2 py-2 px-5 items-center">
|
<div class="fixed top-0 left-0 flex gap-2 py-2 px-5 items-center">
|
||||||
<img src="../../assets/mediakit-logo.svg" class="size-6 dark:invert">
|
<img src="../../assets/mediabunny-logo.svg" class="size-6 dark:invert">
|
||||||
<p class="text-sm font-semibold">Mediakit</p>
|
<p class="text-sm font-semibold">Mediabunny</p>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<a
|
<a
|
||||||
|
|||||||
@@ -4,7 +4,7 @@
|
|||||||
<meta charset="UTF-8">
|
<meta charset="UTF-8">
|
||||||
<meta http-equiv="X-UA-Compatible" content="IE=edge">
|
<meta http-equiv="X-UA-Compatible" content="IE=edge">
|
||||||
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||||||
<title>Live recording example | Mediakit</title>
|
<title>Live recording example | Mediabunny</title>
|
||||||
<script type="module" src="../base.ts"></script>
|
<script type="module" src="../base.ts"></script>
|
||||||
<script type="module" src="./live-recording.ts"></script>
|
<script type="module" src="./live-recording.ts"></script>
|
||||||
<link rel="stylesheet" href="../base.css">
|
<link rel="stylesheet" href="../base.css">
|
||||||
@@ -39,8 +39,8 @@
|
|||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class="fixed top-0 left-0 flex gap-2 py-2 px-5 items-center">
|
<div class="fixed top-0 left-0 flex gap-2 py-2 px-5 items-center">
|
||||||
<img src="../../assets/mediakit-logo.svg" class="size-6 dark:invert">
|
<img src="../../assets/mediabunny-logo.svg" class="size-6 dark:invert">
|
||||||
<p class="text-sm font-semibold">Mediakit</p>
|
<p class="text-sm font-semibold">Mediabunny</p>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<a
|
<a
|
||||||
|
|||||||
@@ -5,7 +5,7 @@ import {
|
|||||||
Output,
|
Output,
|
||||||
QUALITY_MEDIUM,
|
QUALITY_MEDIUM,
|
||||||
StreamTarget,
|
StreamTarget,
|
||||||
} from 'mediakit';
|
} from 'mediabunny';
|
||||||
|
|
||||||
const toggleRecordingButton = document.querySelector('#toggle-button') as HTMLButtonElement;
|
const toggleRecordingButton = document.querySelector('#toggle-button') as HTMLButtonElement;
|
||||||
const horizontalRule = document.querySelector('hr') as HTMLHRElement;
|
const horizontalRule = document.querySelector('hr') as HTMLHRElement;
|
||||||
|
|||||||
@@ -4,7 +4,7 @@
|
|||||||
<meta charset="UTF-8">
|
<meta charset="UTF-8">
|
||||||
<meta http-equiv="X-UA-Compatible" content="IE=edge">
|
<meta http-equiv="X-UA-Compatible" content="IE=edge">
|
||||||
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||||||
<title>Media player example | Mediakit</title>
|
<title>Media player example | Mediabunny</title>
|
||||||
<script type="module" src="../base.ts"></script>
|
<script type="module" src="../base.ts"></script>
|
||||||
<script type="module" src="./media-player.ts"></script>
|
<script type="module" src="./media-player.ts"></script>
|
||||||
<link rel="stylesheet" href="../base.css">
|
<link rel="stylesheet" href="../base.css">
|
||||||
@@ -12,7 +12,7 @@
|
|||||||
|
|
||||||
<body class="flex flex-col items-center py-10 bg-zinc-50 text-zinc-800 dark:bg-zinc-900 dark:text-zinc-200 px-2 h-svh">
|
<body class="flex flex-col items-center py-10 bg-zinc-50 text-zinc-800 dark:bg-zinc-900 dark:text-zinc-200 px-2 h-svh">
|
||||||
<h1 class="text-3xl font-bold text-purple-800 dark:text-purple-200 text-center">Media player example</h1>
|
<h1 class="text-3xl font-bold text-purple-800 dark:text-purple-200 text-center">Media player example</h1>
|
||||||
<p class="max-w-lg text-center">Select or drop a media file, and a fully custom, Mediakit-powered player will appear.</p>
|
<p class="max-w-lg text-center">Select or drop a media file, and a fully custom, Mediabunny-powered player will appear.</p>
|
||||||
|
|
||||||
<div class="flex gap-2 mt-4">
|
<div class="flex gap-2 mt-4">
|
||||||
<button class="rounded-lg bg-zinc-200 dark:bg-zinc-750 hover:bg-zinc-300 dark:hover:bg-zinc-700 px-5 py-2">
|
<button class="rounded-lg bg-zinc-200 dark:bg-zinc-750 hover:bg-zinc-300 dark:hover:bg-zinc-700 px-5 py-2">
|
||||||
@@ -74,8 +74,8 @@
|
|||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class="fixed top-0 left-0 flex gap-2 py-2 px-5 items-center">
|
<div class="fixed top-0 left-0 flex gap-2 py-2 px-5 items-center">
|
||||||
<img src="../../assets/mediakit-logo.svg" class="size-6 dark:invert">
|
<img src="../../assets/mediabunny-logo.svg" class="size-6 dark:invert">
|
||||||
<p class="text-sm font-semibold">Mediakit</p>
|
<p class="text-sm font-semibold">Mediabunny</p>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<a
|
<a
|
||||||
|
|||||||
@@ -6,7 +6,7 @@ import {
|
|||||||
Input,
|
Input,
|
||||||
WrappedAudioBuffer,
|
WrappedAudioBuffer,
|
||||||
WrappedCanvas,
|
WrappedCanvas,
|
||||||
} from 'mediakit';
|
} from 'mediabunny';
|
||||||
|
|
||||||
const selectMediaButton = document.querySelector('button') as HTMLButtonElement;
|
const selectMediaButton = document.querySelector('button') as HTMLButtonElement;
|
||||||
const fileNameElement = document.querySelector('#file-name') as HTMLParagraphElement;
|
const fileNameElement = document.querySelector('#file-name') as HTMLParagraphElement;
|
||||||
|
|||||||
@@ -4,7 +4,7 @@
|
|||||||
<meta charset="UTF-8">
|
<meta charset="UTF-8">
|
||||||
<meta http-equiv="X-UA-Compatible" content="IE=edge">
|
<meta http-equiv="X-UA-Compatible" content="IE=edge">
|
||||||
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||||||
<title>Metadata extraction example | Mediakit</title>
|
<title>Metadata extraction example | Mediabunny</title>
|
||||||
<script type="module" src="../base.ts"></script>
|
<script type="module" src="../base.ts"></script>
|
||||||
<script type="module" src="./metadata-extraction.ts"></script>
|
<script type="module" src="./metadata-extraction.ts"></script>
|
||||||
<link rel="stylesheet" href="../base.css">
|
<link rel="stylesheet" href="../base.css">
|
||||||
@@ -12,7 +12,7 @@
|
|||||||
|
|
||||||
<body class="flex flex-col items-center py-10 bg-zinc-50 text-zinc-800 dark:bg-zinc-900 dark:text-zinc-200 px-2">
|
<body class="flex flex-col items-center py-10 bg-zinc-50 text-zinc-800 dark:bg-zinc-900 dark:text-zinc-200 px-2">
|
||||||
<h1 class="text-3xl font-bold text-blue-800 dark:text-blue-200 text-center">Metadata extraction example</h1>
|
<h1 class="text-3xl font-bold text-blue-800 dark:text-blue-200 text-center">Metadata extraction example</h1>
|
||||||
<p class="max-w-lg text-center">Select or drop a media file, and Mediakit will start extracting various metadata about that file.</p>
|
<p class="max-w-lg text-center">Select or drop a media file, and Mediabunny will start extracting various metadata about that file.</p>
|
||||||
|
|
||||||
<div class="flex gap-2 mt-4">
|
<div class="flex gap-2 mt-4">
|
||||||
<button class="rounded-lg bg-zinc-200 dark:bg-zinc-750 hover:bg-zinc-300 dark:hover:bg-zinc-700 px-5 py-2">
|
<button class="rounded-lg bg-zinc-200 dark:bg-zinc-750 hover:bg-zinc-300 dark:hover:bg-zinc-700 px-5 py-2">
|
||||||
@@ -31,8 +31,8 @@
|
|||||||
<div id="metadata-container" class="text-sm"></div>
|
<div id="metadata-container" class="text-sm"></div>
|
||||||
|
|
||||||
<div class="fixed top-0 left-0 flex gap-2 py-2 px-5 items-center">
|
<div class="fixed top-0 left-0 flex gap-2 py-2 px-5 items-center">
|
||||||
<img src="../../assets/mediakit-logo.svg" class="size-6 dark:invert">
|
<img src="../../assets/mediabunny-logo.svg" class="size-6 dark:invert">
|
||||||
<p class="text-sm font-semibold">Mediakit</p>
|
<p class="text-sm font-semibold">Mediabunny</p>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<a
|
<a
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
import { Input, ALL_FORMATS, BlobSource } from 'mediakit';
|
import { Input, ALL_FORMATS, BlobSource } from 'mediabunny';
|
||||||
|
|
||||||
const selectMediaButton = document.querySelector('button') as HTMLButtonElement;
|
const selectMediaButton = document.querySelector('button') as HTMLButtonElement;
|
||||||
const fileNameElement = document.querySelector('#file-name') as HTMLParagraphElement;
|
const fileNameElement = document.querySelector('#file-name') as HTMLParagraphElement;
|
||||||
|
|||||||
@@ -4,7 +4,7 @@
|
|||||||
<meta charset="UTF-8">
|
<meta charset="UTF-8">
|
||||||
<meta http-equiv="X-UA-Compatible" content="IE=edge">
|
<meta http-equiv="X-UA-Compatible" content="IE=edge">
|
||||||
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||||||
<title>Procedural Generation example | Mediakit</title>
|
<title>Procedural Generation example | Mediabunny</title>
|
||||||
<script type="module" src="../base.ts"></script>
|
<script type="module" src="../base.ts"></script>
|
||||||
<script type="module" src="./procedural-generation.ts"></script>
|
<script type="module" src="./procedural-generation.ts"></script>
|
||||||
<link rel="stylesheet" href="../base.css">
|
<link rel="stylesheet" href="../base.css">
|
||||||
@@ -12,7 +12,7 @@
|
|||||||
|
|
||||||
<body class="flex flex-col items-center py-10 bg-zinc-50 text-zinc-800 dark:bg-zinc-900 dark:text-zinc-200 px-2">
|
<body class="flex flex-col items-center py-10 bg-zinc-50 text-zinc-800 dark:bg-zinc-900 dark:text-zinc-200 px-2">
|
||||||
<h1 class="text-3xl font-bold text-teal-800 dark:text-teal-200 text-center">Procedural generation example</h1>
|
<h1 class="text-3xl font-bold text-teal-800 dark:text-teal-200 text-center">Procedural generation example</h1>
|
||||||
<p class="max-w-lg text-center">Using Mediakit, this page will procedurally generate a video of musical bouncing balls as fast as possible.</p>
|
<p class="max-w-lg text-center">Using Mediabunny, this page will procedurally generate a video of musical bouncing balls as fast as possible.</p>
|
||||||
|
|
||||||
<div class="flex flex-col gap-6 mt-8 w-full max-w-80">
|
<div class="flex flex-col gap-6 mt-8 w-full max-w-80">
|
||||||
<div class="flex flex-col gap-2">
|
<div class="flex flex-col gap-2">
|
||||||
@@ -45,8 +45,8 @@
|
|||||||
<p class="text-xs font-medium mt-1" id="video-info" style="display: none;"></p>
|
<p class="text-xs font-medium mt-1" id="video-info" style="display: none;"></p>
|
||||||
|
|
||||||
<div class="fixed top-0 left-0 flex gap-2 py-2 px-5 items-center">
|
<div class="fixed top-0 left-0 flex gap-2 py-2 px-5 items-center">
|
||||||
<img src="../../assets/mediakit-logo.svg" class="size-6 dark:invert">
|
<img src="../../assets/mediabunny-logo.svg" class="size-6 dark:invert">
|
||||||
<p class="text-sm font-semibold">Mediakit</p>
|
<p class="text-sm font-semibold">Mediabunny</p>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<a
|
<a
|
||||||
|
|||||||
@@ -7,7 +7,7 @@ import {
|
|||||||
QUALITY_HIGH,
|
QUALITY_HIGH,
|
||||||
getFirstEncodableAudioCodec,
|
getFirstEncodableAudioCodec,
|
||||||
getFirstEncodableVideoCodec,
|
getFirstEncodableVideoCodec,
|
||||||
} from 'mediakit';
|
} from 'mediabunny';
|
||||||
|
|
||||||
const durationSlider = document.querySelector('#duration-slider') as HTMLInputElement;
|
const durationSlider = document.querySelector('#duration-slider') as HTMLInputElement;
|
||||||
const durationValue = document.querySelector('#duration-value') as HTMLParagraphElement;
|
const durationValue = document.querySelector('#duration-value') as HTMLParagraphElement;
|
||||||
|
|||||||
@@ -4,7 +4,7 @@
|
|||||||
<meta charset="UTF-8">
|
<meta charset="UTF-8">
|
||||||
<meta http-equiv="X-UA-Compatible" content="IE=edge">
|
<meta http-equiv="X-UA-Compatible" content="IE=edge">
|
||||||
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||||||
<title>Thumbnail generation example | Mediakit</title>
|
<title>Thumbnail generation example | Mediabunny</title>
|
||||||
<script type="module" src="./../base.ts"></script>
|
<script type="module" src="./../base.ts"></script>
|
||||||
<script type="module" src="./thumbnail-generation.ts"></script>
|
<script type="module" src="./thumbnail-generation.ts"></script>
|
||||||
<link rel="stylesheet" href="../base.css">
|
<link rel="stylesheet" href="../base.css">
|
||||||
@@ -12,7 +12,7 @@
|
|||||||
|
|
||||||
<body class="flex flex-col items-center py-10 bg-gray-50 text-gray-800 dark:bg-zinc-900 dark:text-zinc-200 px-2">
|
<body class="flex flex-col items-center py-10 bg-gray-50 text-gray-800 dark:bg-zinc-900 dark:text-zinc-200 px-2">
|
||||||
<h1 class="text-3xl font-bold text-emerald-800 dark:text-emerald-200 text-center">Thumbnail generation example</h1>
|
<h1 class="text-3xl font-bold text-emerald-800 dark:text-emerald-200 text-center">Thumbnail generation example</h1>
|
||||||
<p class="max-w-lg text-center">Select or drop a media file, and Mediakit will extract video thumbnails for it.</p>
|
<p class="max-w-lg text-center">Select or drop a media file, and Mediabunny will extract video thumbnails for it.</p>
|
||||||
|
|
||||||
<div class="flex gap-2 mt-4">
|
<div class="flex gap-2 mt-4">
|
||||||
<button class="rounded-lg bg-gray-200 dark:bg-zinc-750 hover:bg-gray-300 dark:hover:bg-zinc-700 px-5 py-1">
|
<button class="rounded-lg bg-gray-200 dark:bg-zinc-750 hover:bg-gray-300 dark:hover:bg-zinc-700 px-5 py-1">
|
||||||
@@ -31,8 +31,8 @@
|
|||||||
<div id="thumbnail-container" class="grid grid-cols-1 sm:grid-cols-2 md:grid-cols-3 lg:grid-cols-4 gap-4"></div>
|
<div id="thumbnail-container" class="grid grid-cols-1 sm:grid-cols-2 md:grid-cols-3 lg:grid-cols-4 gap-4"></div>
|
||||||
|
|
||||||
<div class="fixed top-0 left-0 flex gap-2 py-2 px-5 items-center">
|
<div class="fixed top-0 left-0 flex gap-2 py-2 px-5 items-center">
|
||||||
<img src="../../assets/mediakit-logo.svg" class="size-6 dark:invert">
|
<img src="../../assets/mediabunny-logo.svg" class="size-6 dark:invert">
|
||||||
<p class="text-sm font-semibold">Mediakit</p>
|
<p class="text-sm font-semibold">Mediabunny</p>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<a
|
<a
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
import { Input, ALL_FORMATS, BlobSource, CanvasSink } from 'mediakit';
|
import { Input, ALL_FORMATS, BlobSource, CanvasSink } from 'mediabunny';
|
||||||
|
|
||||||
const selectMediaButton = document.querySelector('button') as HTMLButtonElement;
|
const selectMediaButton = document.querySelector('button') as HTMLButtonElement;
|
||||||
const fileNameElement = document.querySelector('#file-name') as HTMLParagraphElement;
|
const fileNameElement = document.querySelector('#file-name') as HTMLParagraphElement;
|
||||||
|
|||||||
+1
-1
@@ -6,7 +6,7 @@
|
|||||||
"composite": true,
|
"composite": true,
|
||||||
"noEmit": false,
|
"noEmit": false,
|
||||||
"paths": {
|
"paths": {
|
||||||
"mediakit": ["./dist/metamuxer.d.ts"],
|
"mediabunny": ["./dist/metamuxer.d.ts"],
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
"include": [
|
"include": [
|
||||||
|
|||||||
+1
-1
@@ -20,7 +20,7 @@ const rollupInput = Object.fromEntries(
|
|||||||
export default defineConfig({
|
export default defineConfig({
|
||||||
resolve: {
|
resolve: {
|
||||||
alias: {
|
alias: {
|
||||||
mediakit: path.resolve(__dirname, './dist/metamuxer.mjs'),
|
mediabunny: path.resolve(__dirname, './dist/metamuxer.mjs'),
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
plugins: [
|
plugins: [
|
||||||
|
|||||||
Reference in New Issue
Block a user