浏览器通常在其 WebCodecs 实现中不支持 MP3 编码。鉴于该格式的普及性,此扩展包为 Mediabunny 提供了一个 MP3 编码器。它使用 Mediabunny 的 自定义编码器 API 实现,并在底层使用了高度优化的 LAME MP3 编码器 的 WASM 构建版本。

GitHub 页面

安装 ​

此库与 Mediabunny 互为对等依赖。请使用 npm 同时安装两者:

npm install mediabunny @mediabunny/mp3-encoder

或者,直接使用 script 标签引入它们:

<script src="mediabunny.js"></script>
<script src="mediabunny-mp3-encoder.js"></script>

这将暴露全局对象 Mediabunny 和 MediabunnyMp3Encoder。使用 mediabunny-mp3-encoder.d.ts 可为这些全局变量提供类型定义。您可以从 发布页面 下载构建好的分发文件。

用法 ​

import { registerMp3Encoder } from '@mediabunny/mp3-encoder';

registerMp3Encoder();

完成以上步骤后 - Mediabunny 现在会自动使用已注册的 MP3 编码器。

如果您希望更加严谨,请先检查浏览器的原生支持情况:

import { canEncodeAudio } from 'mediabunny';
import { registerMp3Encoder } from '@mediabunny/mp3-encoder';

if (!(await canEncodeAudio('mp3'))) {
    registerMp3Encoder();
}

示例 ​

此处,我们将输入文件转换为 MP3:

import {
    Input,
    ALL_FORMATS,
    BlobSource,
    Output,
    BufferTarget,
    Mp3OutputFormat,
    canEncodeAudio,
    Conversion,
} from 'mediabunny';
import { registerMp3Encoder } from '@mediabunny/mp3-encoder';

if (!(await canEncodeAudio('mp3'))) {
    // 如果没有原生支持,仅注册自定义编码器
    registerMp3Encoder();
}

const input = new Input({
    source: new BlobSource(file), // 例如来自文件选择器
    formats: ALL_FORMATS,
});
const output = new Output({
    format: new Mp3OutputFormat(),
    target: new BufferTarget(),
});

const conversion = await Conversion.init({
    input,
    output,
});
await conversion.execute();

output.target.buffer; // => 包含 MP3 文件的 ArrayBuffer

实现细节 ​

此库通过向 Mediabunny 注册一个自定义编码器类来实现 MP3 编码器。该类在初始化时会启动一个 worker,随后立即加载 LAME MP3 编码器的 WASM 构建版本。然后,原始数据被发送到 worker,并从中接收编码后的数据。这些编码后的块随后在主线程中被拼接,并正确分割成独立的 MP3 帧。

我们极力确保此包具有最大的兼容性;它适用于打包工具、直接在浏览器中运行,以及 Node、Deno 和 Bun 环境。所有代码(包括 worker 和 WASM)都被打包到单个文件中,消除了对 CDN 或 WASM 路径参数的需求。因此,此包可作为 Mediabunny 基于 WASM 的编码器扩展的参考实现。

WASM 构建本身是 LAME 3.100 的性能优化版,启用了 SIMD,并禁用了所有不必要的功能。由于性能优先,构建体积稍大,但压缩后约 130 kB 在我看来仍然非常合理。在我的测试中,它能在约 90 毫秒内编码 5 秒的音频(实时速度的 55 倍)。