容器格式 ​

Mediabunny 支持许多常用的媒体容器格式,所有格式均支持双向操作(读取与写入):

  • 基于 ISOBMFF 的格式 (.mp4, .m4v, .m4a, ...)
  • QuickTime 文件格式 (.mov)
  • 分段 MP4 (CMAF) (.m4s)
  • Matroska (.mkv)
  • WebM (.webm)
  • Ogg (.ogg)
  • MP3 (.mp3)
  • WAVE (.wav)
  • ADTS (.aac)
  • FLAC (.flac)
  • MPEG 传输流 (.ts)
  • HLS (.m3u8)

编解码器 ​

Mediabunny 支持广泛的视频、音频和字幕编解码器。更具体地说,它支持 WebCodecs API 指定的所有编解码器,并开箱即用支持一些额外的 PCM 编解码器。

WebCodecs API 提供的编解码器的可用性取决于浏览器,因此本库无法保证。Mediabunny 提供特殊的工具函数来检查哪些编解码器可以进行编码。如果浏览器不支持该编解码器的原生实现,您也可以指定自定义编码器以提供您自己的编码器/解码器实现。

关于每种编解码器及其对应数据包格式的精确定义,请参阅 Mediabunny 编解码器注册表。

Mediabunny 内置了所有音频 PCM 编解码器的解码器和编码器,这意味着它们始终受支持。

视频编解码器 ​

  • 'avc' - 高级视频编码 (AVC) / H.264
  • 'hevc' - 高效视频编码 (HEVC) / H.265
  • 'vp8' - VP8
  • 'vp9' - VP9
  • 'av1' - AOMedia Video 1 (AV1)
  • 'prores' - Apple ProRes [1]

音频编解码器 ​

  • 'aac' - 高级音频编码 (AAC) [2]
  • 'opus' - Opus
  • 'mp3' - MP3 [3]
  • 'vorbis' - Vorbis
  • 'flac' - 无损音频编解码器 (FLAC) [4]
  • 'ac3' - 杜比数字 (AC-3) [5]
  • 'eac3' - 杜比数字增强 (E-AC-3) [5:1]
  • 'dts' - DTS 相干声学 [6]
  • 'pcm-u8' - 8 位无符号 PCM
  • 'pcm-s8' - 8 位有符号 PCM
  • 'pcm-s16' - 16 位小端有符号 PCM
  • 'pcm-s16be' - 16 位大端有符号 PCM
  • 'pcm-s24' - 24 位小端有符号 PCM
  • 'pcm-s24be' - 24 位大端有符号 PCM
  • 'pcm-s32' - 32 位小端有符号 PCM
  • 'pcm-s32be' - 32 位大端有符号 PCM
  • 'pcm-f32' - 32 位小端浮点 PCM
  • 'pcm-f32be' - 32 位大端浮点 PCM
  • 'pcm-f64' - 64 位小端浮点 PCM
  • 'pcm-f64be' - 64 位大端浮点 PCM
  • 'ulaw' - μ-law PCM
  • 'alaw' - A-law PCM

字幕编解码器 ​

  • 'webvtt' - WebVTT

兼容性表 ​

并非所有编解码器都能与所有容器配合使用。下表列出了支持的编解码器 - 容器组合:

.mp4.mov.mkv.webm[7].ogg.mp3.wav.aac.flac.ts
'avc'✓✓✓✓
'hevc'✓✓✓✓
'vp8'✓✓✓✓
'vp9'✓✓✓✓
'av1'✓✓✓✓
'prores'✓✓✓
'aac'✓✓✓✓✓
'opus'✓✓✓✓✓
'mp3'✓✓✓✓✓
'vorbis'✓✓✓✓✓
'flac'✓✓✓✓
'ac3'✓✓✓✓
'eac3'✓✓✓✓
'dts'✓✓✓✓
'pcm-u8'✓✓✓
'pcm-s8'✓
'pcm-s16'✓✓✓✓
'pcm-s16be'✓✓✓
'pcm-s24'✓✓✓✓
'pcm-s24be'✓✓✓
'pcm-s32'✓✓✓✓
'pcm-s32be'✓✓✓
'pcm-f32'✓✓✓✓
'pcm-f32be'✓✓
'pcm-f64'✓✓✓
'pcm-f64be'✓✓
'ulaw'✓✓
'alaw'✓✓
'webvtt'[8](✓)(✓)(✓)

对于 HLS,支持的编解码器取决于所选的段格式。

查询编解码器的可编码性 ​

Mediabunny 提供了实用函数,您可以用来检查浏览器是否可以编码给定的编解码器。此外,您还可以检查编解码器是否可以使用特定的配置进行编码。

canEncode测试编解码器是否可以使用典型设置进行编码:

import { canEncode } from 'mediabunny';

canEncode('avc'); // => Promise<boolean>
canEncode('opus'); // => Promise<boolean>

视频编解码器使用 1280x720 进行检查,而音频编解码器使用 2 通道、48 kHz 进行检查。

您也可以使用特定配置检查可编码性:

import { canEncodeVideo, canEncodeAudio, Quality } from 'mediabunny';

canEncodeVideo('hevc', {
	width: 1920, height: 1080, frameRate: 60, quality: new Quality({ bitrate: 1e7 })
}); // => Promise<boolean>

canEncodeAudio('aac', {
	numberOfChannels: 1, sampleRate: 44100, quality: new Quality({ bitrate: 192e3 })
}); // => Promise<boolean>

此外,VideoEncodingConfig和AudioEncodingConfig的大多数属性也可以在此处使用。


此外,您可以使用以下函数一次性检查多个编解码器的可编码性,并返回受支持的编解码器列表:

import {
	getEncodableCodecs,
	getEncodableVideoCodecs,
	getEncodableAudioCodecs,
	getEncodableSubtitleCodecs,
	Quality,
} from 'mediabunny';

getEncodableCodecs(); // => Promise<MediaCodec[]>
getEncodableVideoCodecs(); // => Promise<VideoCodec[]>
getEncodableAudioCodecs(); // => Promise<AudioCodec[]>
getEncodableSubtitleCodecs(); // => Promise<SubtitleCodec[]>

// 这些函数也接受可选的配置选项。
// 这里,我们检查 AVC、HEVC 和 VP8 中哪些可以在 1920x1080 @10Mbps 下编码:
getEncodableVideoCodecs(
	['avc', 'hevc', 'vp8'],
	{ width: 1920, height: 1080, quality: new Quality({ bitrate: 1e7 }) },
); // => Promise<VideoCodec[]>

如果您只想查找浏览器可以编码的最佳编解码器,可以使用这些函数,它们将返回浏览器支持的第一个编解码器:

import {
	getFirstEncodableVideoCodec,
	getFirstEncodableAudioCodec,
	getFirstEncodableSubtitleCodec,
	Quality,
} from 'mediabunny';

getFirstEncodableVideoCodec(['avc', 'vp9', 'av1']); // => Promise<VideoCodec | null>
getFirstEncodableAudioCodec(['opus', 'aac']); // => Promise<AudioCodec | null>

getFirstEncodableVideoCodec(
	['avc', 'hevc', 'vp8'],
	{ width: 1920, height: 1080, quality: new Quality({ bitrate: 1e7 }) },
); // => Promise<VideoCodec | null>

如果列出的编解码器均不受支持,则返回 null。

这些函数与 输出格式 结合使用时特别有用,可检索同时被编码器及容器格式支持的最佳编解码器:

import {
	Mp4OutputFormat,
	getFirstEncodableVideoCodec,
} from 'mediabunny';

const outputFormat = new Mp4OutputFormat();
const containableVideoCodecs = outputFormat.getSupportedVideoCodecs();
const bestVideoCodec = await getFirstEncodableVideoCodec(containableVideoCodecs);

编解码器可编码性检查会考虑自定义编码器。

查询编解码器可解码性 ​

如果您已经有一个 InputTrack,可以使用其 canDecode 方法检查其可解码性,该方法会使用轨道的实际编解码器配置:

const canDecodeTrack = await inputTrack.canDecode(); // => boolean

然而,即使没有具体的轨道,您也可以评估可解码性。canDecode 测试是否可以使用典型设置对编解码器进行解码:

import { canDecode } from 'mediabunny';

canDecode('avc'); // => Promise<boolean>
canDecode('opus'); // => Promise<boolean>

视频编解码器使用 1280x720 进行检查,而音频编解码器使用 2 声道、48 kHz 进行检查。

您还可以使用特定配置检查可解码性:

import { canDecodeVideo, canDecodeAudio } from 'mediabunny';

canDecodeVideo('hevc', {
	codedWidth: 1920, codedHeight: 1080
}); // => Promise<boolean>

canDecodeAudio('aac', {
	numberOfChannels: 1, sampleRate: 44100
}); // => Promise<boolean>

此处也可以使用 VideoDecoderConfig 和 AudioDecoderConfig 的所有其他属性。


此外,您可以使用以下函数一次性检查多个编解码器的可解码性,并获取受支持的编解码器列表:

import {
	getDecodableCodecs,
	getDecodableVideoCodecs,
	getDecodableAudioCodecs,
} from 'mediabunny';

getDecodableCodecs(); // => Promise<MediaCodec[]>
getDecodableVideoCodecs(); // => Promise<VideoCodec[]>
getDecodableAudioCodecs(); // => Promise<AudioCodec[]>

// 这些函数也接受可选的配置选项。
// 这里,我们检查 AVC、HEVC 和 VP8 中哪些可以在 1920x1080 下解码:
getDecodableVideoCodecs(
	['avc', 'hevc', 'vp8'],
	{ codedWidth: 1920, codedHeight: 1080 },
); // => Promise<VideoCodec[]>

编解码器可解码性检查会考虑自定义解码器。

自定义编码器/解码器 ​

Mediabunny 允许您注册自己的自定义编码器和解码器——如果您想在所有浏览器都不支持的编解码器上进行多态填充,或者希望在非 WebCodecs 环境(如 Node.js)中使用 Mediabunny,这将非常有用。

可以为库支持的所有视频和音频编解码器注册编码器和解码器。无法添加新的编解码器。

警告

Mediabunny 要求自定义编码器和解码器遵循非常具体的实现规则。请特别注意标有 "必须" 的部分以确保兼容性。

自定义编码器 ​

要创建自定义视频或音频编码器,您需要创建一个扩展 CustomVideoEncoder 或 CustomAudioEncoder 的类。然后,您 必须 使用 registerEncoder 注册此类:

import { CustomAudioEncoder, registerEncoder } from 'mediabunny';

class MyAwesomeMp3Encoder extends CustomAudioEncoder {
	// ...
}
registerEncoder(MyAwesomeMp3Encoder);

以下属性在每个编码器实例上可用,并由库设置:

class {
	// 对于视频编码器:
	codec: VideoCodec;
	config: VideoEncoderConfig;
	onPacket: (packet: EncodedPacket, meta?: EncodedVideoChunkMetadata) => unknown;

	// 对于音频编码器:
	codec: AudioCodec;
	config: AudioEncoderConfig;
	onPacket: (packet: EncodedPacket, meta?: EncodedAudioChunkMetadata) => unknown;

	// 对于两者:
	onError: (error: unknown) => void;
}

codec 和 config 指定要使用的具体编解码器配置,而 onPacket 是一个方法,您的代码在创建每个编码包时必须调用它。onError 是一个您可以调用的方法,用于抛出发生在常规方法调用之外的任何带外错误(例如来自异步后台任务);否则这些错误将不会被捕获。

您必须在自定义编码器类中实现以下方法:

class {
	// For video encoders:
	static supports(codec: VideoCodec, config: VideoEncoderConfig): boolean;
	// For audio encoders:
	static supports(codec: AudioCodec, config: AudioEncoderConfig): boolean;

	init(): Promise<void> | void;
	encode(sample: VideoSample, options: VideoEncoderEncodeOptions): Promise<void> | void; // For video
	encode(sample: AudioSample): Promise<void> | void; // For audio
	flush(): Promise<void> | void;
	close(): Promise<void> | void;
}
  • supports
    这是一个静态方法,如果编码器能够编码指定的编解码器则必须返回 true,否则返回 false。如果返回 true,库将创建您编码器类的新实例并用于编码,其优先级高于默认编码器。
  • init
    由库在您的类实例化后调用。在此处放置任何初始化逻辑。
  • encode
    对每个待编码的样本进行调用。生成的编码包必须随后传递给 onPacket 方法。
  • flush
    当期望编码器完成所有尚未完成编码的剩余样本的编码过程时调用。此方法必须仅在所有传递给 encode 的样本都已完全编码后才返回/解析。之后,它必须重置其内部状态以准备下一批编码。
  • close
    当不再需要编码器且可以释放其内部资源时调用。

该类的所有实例方法都可以返回 promises。在这种情况下,库将确保对所有方法调用进行序列化,以确保没有两个方法会同时运行。

WARNING

传递给 onPacket 的包必须处于解码顺序。

Custom decoders ​

要创建自定义视频或音频解码器,您需要创建一个扩展 CustomVideoDecoder 或 CustomAudioDecoder 的类。然后,您必须使用 registerDecoder 注册此类:

import { CustomAudioDecoder, registerDecoder } from 'mediabunny';

class MyAwesomeMp3Decoder extends CustomAudioDecoder {
	// ...
}
registerDecoder(MyAwesomeMp3Decoder);

以下属性在每个解码器实例上可用,并由库设置:

class {
	// For video decoders:
	codec: VideoCodec;
	config: VideoDecoderConfig;
	onSample: (sample: VideoSample) => unknown;

	// For audio decoders:
	codec: AudioCodec;
	config: AudioDecoderConfig;
	onSample: (sample: AudioSample) => unknown;

	// For both:
	onError: (error: unknown) => void;
}

codec 和 config 指定要使用的具体编解码器配置,而 onSample 是一个方法,您的代码在创建每个视频/音频样本时必须调用它。onError 是一个您可以调用的方法,用于抛出发生在常规方法调用之外的任何带外错误(例如来自异步后台任务);否则这些错误将不会被捕获。

您必须在自定义解码器类中实现以下方法:

class {
	// For video decoders:
	static supports(codec: VideoCodec, config: VideoDecoderConfig): boolean;
	// For audio decoders:
	static supports(codec: AudioCodec, config: AudioDecoderConfig): boolean;

	init(): Promise<void> | void;
	decode(packet: EncodedPacket): Promise<void> | void;
	flush(): Promise<void> | void;
	close(): Promise<void> | void;
}
  • supports
    这是一个静态方法,如果解码器能够解码指定的编解码器则必须返回 true,否则返回 false。如果返回 true,库将创建您解码器类的新实例并用于解码,其优先级高于默认解码器。
  • init
    由库在您的类实例化后调用。在此处放置任何初始化逻辑。
  • decode
    对每个待解码的 EncodedPacket 进行调用。生成的视频或音频样本必须随后传递给 onSample 方法。
  • flush
    当期望解码器完成所有尚未完成解码的剩余包的解码过程时调用。此方法必须仅在所有传递给 decode 的包都已完全解码后才返回/解析。之后,它必须重置其内部状态以准备下一批解码。
  • close
    当不再需要解码器且可以释放其内部资源时调用。

该类的所有实例方法都可以返回 promises。在这种情况下,库将确保对所有方法调用进行序列化,以确保没有两个方法会同时运行。

WARNING

传递给 onSample 的样本必须按递增的时间戳排序。这尤其意味着如果解码器正在解码使用B 帧的视频流,则解码器必须在内部保留这些帧,以便能够按显示时间戳对其排序发出。每次调用 flush 时,此严格排序要求都会重置。


  1. WebCodecs 不支持 ProRes。要对其进行解码,请使用 @mediabunny/prores 扩展包。@mediabunny/server 扩展包为服务器端环境提供解码和编码支持。

  2. 在某些浏览器中,WebCodecs 不支持 AAC 编码。您可以使用 @mediabunny/aac-encoder 扩展包进行填充。

  3. WebCodecs 不支持 MP3 编码。您可以使用 @mediabunny/mp3-encoder 扩展包进行填充。

  4. WebCodecs 不支持 FLAC 编码。您可以使用 @mediabunny/flac-encoder 扩展包进行填充。

  5. AC-3 和 E-AC-3 不是 WebCodecs 原生支持的编解码器。要编码或解码这些编解码器,可以使用 @mediabunny/ac3 扩展包。

  6. DTS 不是 WebCodecs 原生支持的编解码器。要编码或解码它,可以使用 @mediabunny/dts 扩展包。

  7. WebM 仅支持 Matroska 所支持的一小部分编解码器。但是,该库在技术上可以读取 WebM 中所有 Matroska 支持的编解码器。

  8. WebVTT 只能写入,不能读取。