Transparent video read/write support (#145)

* Add support for reading transparent Matroska and implement alpha side data & decode

* Few fixes

* Implement alpha encoding

* Gracefully handle inability to acquire WebGL context, properly clean up WebGL contexts

* Improve touch device detection

* Test test

* Test test #2

* Test test 3

* Test test 4

* Test test 5

* Test test 6

* Test test 7

* Test test 8

* Test test 9

* Test test 10

* Test test 11

* Test test 12

* Test test 13

* Test test 14

* Test test 15

* Test test 16

* Test test 17

* Test test 18

* Test test 19

* Test test 20

* Fix type errors, improve MetadataTags docs

* Do a bunch of docs work

* Test test?

* "Unexpected only modifier 🤓"

* Add InputVideoTrack.canBeTransparent()

* Some clean-up

* Adjust CI to be less spammy in PRs

* Fix broken license headers
This commit is contained in:
David P.
2025-09-24 21:20:14 +02:00
committed by GitHub
parent 0878dd2ca9
commit fa4e064345
34 changed files with 1537 additions and 181 deletions
+14 -1
View File
@@ -107,6 +107,14 @@ export const validateVideoEncodingConfig = (config: VideoEncodingConfig) => {
* @public
*/
export type VideoEncodingAdditionalOptions = {
/**
* What to do with alpha data contained in the video samples.
*
* - `'discard'` (default): Only the samples' color data is kept; the video is opaque.
* - `'keep'`: The samples' alpha data is also encoded as side data. Make sure to pair this mode with a container
* format that supports transparency (such as WebM or Matroska).
*/
alpha?: 'discard' | 'keep';
/** Configures the bitrate mode. */
bitrateMode?: 'constant' | 'variable';
/** The latency mode used by the encoder; controls the performance-quality tradeoff. */
@@ -136,6 +144,9 @@ export const validateVideoEncodingAdditionalOptions = (codec: VideoCodec, option
if (!options || typeof options !== 'object') {
throw new TypeError('Encoding options must be an object.');
}
if (options.alpha !== undefined && !['discard', 'keep'].includes(options.alpha)) {
throw new TypeError('options.alpha, when provided, must be \'discard\' or \'keep\'.');
}
if (options.bitrateMode !== undefined && !['constant', 'variable'].includes(options.bitrateMode)) {
throw new TypeError('bitrateMode, when provided, must be \'constant\' or \'variable\'.');
}
@@ -189,7 +200,8 @@ export const buildVideoEncoderConfig = (options: {
height: options.height,
bitrate: resolvedBitrate,
bitrateMode: options.bitrateMode,
framerate: options.framerate, // this.source._connectedTrack?.metadata.frameRate,
alpha: options.alpha ?? 'discard',
framerate: options.framerate,
latencyMode: options.latencyMode,
hardwareAcceleration: options.hardwareAcceleration,
scalabilityMode: options.scalabilityMode,
@@ -506,6 +518,7 @@ export const canEncodeVideo = async (
bitrate,
framerate: undefined,
...restOptions,
alpha: 'discard', // Since we handle alpha ourselves
});
const support = await VideoEncoder.isConfigSupported(encoderConfig);