first commit
This commit is contained in:
@@ -0,0 +1,84 @@
|
||||
# `encode-pipeline.ts`
|
||||
|
||||
<!-- begin:auto-docs -->
|
||||
_(no submodules)_
|
||||
<!-- end:auto-docs -->
|
||||
|
||||
## Purpose
|
||||
|
||||
This module owns the pure logic of the encode pipeline: validating the
|
||||
requested format against the supported set *before* the worker is touched,
|
||||
interleaving per-channel PCM into a single `Float32Array`, projecting
|
||||
that into ffmpeg's `f32le` wire format, building the format-specific
|
||||
ffmpeg command for each of `wav` / `mp3` / `ogg` / `opus` / `flac` /
|
||||
`aac` / `webm`, and dispatching the call through the supplied
|
||||
`WorkerHost`. All MEMFS lifecycle is owned by the host.
|
||||
|
||||
## Features
|
||||
|
||||
- `interleave` and `float32ToBytes` produce the exact wire layout ffmpeg
|
||||
expects for `-f f32le`.
|
||||
- `buildCommand` returns the ffmpeg argument list per supported format,
|
||||
honouring caller-supplied `bitrate` (`mp3`, `opus`, `aac`, `webm`) and
|
||||
`quality` (`ogg`).
|
||||
- `assertSupported` throws `UNSUPPORTED_CODEC` synchronously, before any
|
||||
worker message is posted — required by the spec.
|
||||
- `runEncode` drives the full pipeline through `WorkerHost.submitFfmpeg`.
|
||||
|
||||
## Usage: Basic
|
||||
|
||||
```ts
|
||||
import { runEncode } from "@suaveplan/audio-codec-ffmpeg-wasm/encode/encode-pipeline";
|
||||
|
||||
const bytes = await runEncode({
|
||||
host,
|
||||
channelData: [leftFloats, rightFloats],
|
||||
format: "mp3",
|
||||
sampleRate: 44_100,
|
||||
bitrate: 256_000,
|
||||
});
|
||||
```
|
||||
|
||||
## Usage: Advanced
|
||||
|
||||
```ts
|
||||
import {
|
||||
runEncode,
|
||||
interleave,
|
||||
buildCommand,
|
||||
} from "@suaveplan/audio-codec-ffmpeg-wasm/encode/encode-pipeline";
|
||||
|
||||
// Inspect the command ffmpeg will be asked to run
|
||||
const cmd = buildCommand("opus", 48_000, 1, 96_000);
|
||||
console.log(cmd.args);
|
||||
|
||||
const interleaved = interleave([mono]);
|
||||
const result = await runEncode({
|
||||
host,
|
||||
channelData: [mono],
|
||||
format: "opus",
|
||||
sampleRate: 48_000,
|
||||
bitrate: 96_000,
|
||||
signal: controller.signal,
|
||||
timeoutMs: 60_000,
|
||||
});
|
||||
```
|
||||
|
||||
## API Reference
|
||||
|
||||
- `interleave(channelData): Float32Array`.
|
||||
- `float32ToBytes(samples): Uint8Array`.
|
||||
- `buildCommand(format, sampleRate, channels, bitrate?, quality?): FormatCommand`.
|
||||
- `runEncode(opts: EncodePipelineOptions): Promise<Uint8Array>`.
|
||||
|
||||
## Implementation Notes
|
||||
|
||||
`assertSupported` is intentionally written as a TypeScript `asserts`
|
||||
function so its throw branch narrows the format type for the rest of the
|
||||
function — no extra runtime branch is needed. Format-specific defaults
|
||||
(192 kbps for MP3/AAC, 96 kbps for Opus/WebM, q=5 for Vorbis) are
|
||||
chosen to match the ffmpeg.wasm reference build's documented sweet
|
||||
spots; callers always override via `bitrate`/`quality` for production
|
||||
use. The interleaved `Float32Array` is wrapped in a `Uint8Array` view
|
||||
without an extra copy so the worker `postMessage` boundary takes one
|
||||
transferable buffer instead of two.
|
||||
Reference in New Issue
Block a user