Add custom processing to Conversion API

This commit is contained in:
Vanilagy
2025-10-17 14:52:13 +02:00
parent 21456e3bf6
commit e880f54553
4 changed files with 362 additions and 44 deletions
+56
View File
@@ -16,6 +16,7 @@ It has the following features:
- Video transparency removal/preservation
- Audio resampling
- Audio up/downmixing
- User-defined video & audio processing
The conversion API was built to be simple, versatile and extremely performant.
@@ -126,7 +127,14 @@ type ConversionVideoOptions = {
alpha?: 'discard' | 'keep'; // Defaults to 'discard'
keyFrameInterval?: number;
forceTranscode?: boolean;
process?: (sample: VideoSample) => MaybePromise<
CanvasImageSource | VideoSample | (CanvasImageSource | VideoSample)[] | null
>;
processedWidth?: number;
processedHeight?: number;
};
type MaybePromise<T> = T | Promise<T>;
```
For example, here we resize the video track to 720p:
@@ -185,6 +193,39 @@ Use the `keyFrameInterval` property to control the maximum interval in seconds b
If you want to prevent direct copying of media data and force a transcoding step, use `forceTranscode: true`.
### Processing video
The `process` property can be used to define a custom video sample processing function, e.g. for [applying overlays](./quick-start#add-a-video-overlay), color transformations, or timestamp modifications. You are expected to perform this processing yourself, for example using the Canvas API.
An example:
```ts
let ctx: CanvasRenderingContext2D | null = null;
const conversion = await Conversion.init({
video: {
process: (sample) => {
if (!ctx) {
const canvas = new OffscreenCanvas(
sample.displayWidth,
sample.displayHeight,
);
ctx = canvas.getContext('2d')!;
// Convert the video to grayscale
ctx.filter = 'saturate(0)';
}
sample.draw(ctx, 0, 0);
return ctx.canvas;
},
},
});
```
The function is called for each input video sample after transformations and frame rate corrections. It must return a [`VideoSample`](./packets-and-samples#videosample), something that can convert to a `VideoSample`, an array of them, or `null` for dropping the frame.
This function can also be used to manually resize frames. When doing so, you should signal the post-process dimensions using the `processedWidth` and `processedHeight` fields, which enables the encoder to better know what to expect.
## Audio options
You can set the `audio` property in the conversion options to configure the converter's behavior for audio tracks. The options are:
@@ -196,7 +237,14 @@ type ConversionAudioOptions = {
numberOfChannels?: number;
sampleRate?: number;
forceTranscode?: boolean;
process?: (sample: AudioSample) => MaybePromise<
AudioSample | AudioSample[] | null
>;
processedNumberOfChannels?: number;
processedSampleRate?: number;
};
type MaybePromise<T> = T | Promise<T>;
```
For example, here we convert the audio track to mono and set a specific sample rate:
@@ -233,6 +281,14 @@ Use the `bitrate` property to control the bitrate of the output audio. For examp
If you want to prevent direct copying of media data and force a transcoding step, use `forceTranscode: true`.
### Processing audio
The `process` property can be used to define a custom audio sample processing function, e.g. for applying audio effects, transformations, or timestamp modifications. You are expected to perform this processing yourself.
The function is called for each input audio sample after remixing and resampling. It must return an [`AudioSample`](./packets-and-samples#audiosample), an array of them, or `null` for dropping the sample.
This function can also be used to manually perform remixing or resampling. When doing so, you should signal the post-process parameters using the `processedNumberOfChannels` and `processedSampleRate` fields, which enables the encoder to better know what to expect.
## Track-specific options
You may want to configure your video and audio options differently depending on the specifics of the input track. Or, in case a media file has multiple video or audio tracks, you may want to discard only specific tracks or configure each track separately.