npm package: @silyze/async-audio-ffmpeg
Description: ffmpeg wrapper for @silyze/async-audio-stream
Author: Mihail Mojsoski
Latest version: 1.0.0

# Async Audio FFmpeg

**Async Audio FFmpeg** is a thin, zero‑dependency wrapper around **FFmpeg** that plugs straight into [`@silyze/async-audio-stream`](https://www.npmjs.com/package/@silyze/async-audio-stream).  
It lets you _encode_ and _decode_ audio on‑the‑fly using FFmpeg’s pipes, fully async/await‑friendly and abort‑signal aware.

---

## Install

```bash
npm install @silyze/async-audio-ffmpeg
```

> **Prerequisite:** FFmpeg must be available in your `$PATH` (≥ 5.x recommended).

---

## Quick start

```ts
import createAudioFormat from "@silyze/async-audio-ffmpeg";

// Define an Opus‑in‑WebM format:
export const OpusFormat = createAudioFormat("webm-opus", () => [
  "-c:a",
  "libopus",
  "-b:a",
  "24k",
  "-f",
  "webm",
]);

// Use it:
const format = new OpusFormat(8000); // PCM sample‑rate → 8 kHz

console.log(format.name); // "webm-opus"
console.log(format.pcmSampleRate); // 8000
```

---

## API

### `createAudioFormat(name, flags, extraFlags?) ⇒ AudioFormat subclass`

| Parameter    | Type                                                    | Description                                                                     |
| ------------ | ------------------------------------------------------- | ------------------------------------------------------------------------------- |
| `name`       | `string`                                                | Human‑readable format name.                                                     |
| `flags`      | `(sampleRate: number) → string[]`                       | Function that returns the **output flags** for FFmpeg (e.g. codec & container). |
| `extraFlags` | `string[]` **(optional)** default: _low‑latency_ preset | Extra global flags appended to every FFmpeg call.                               |

`createAudioFormat` returns a **dynamic subclass** of `AudioFormat` (`@silyze/async-audio-stream`) implementing:

```ts
/** Decode from <name> → PCM */
decode(input: AsyncReadStream<Buffer>): AsyncReadStream<Buffer>;

/** Encode from PCM → <name> */
encode(input: AsyncReadStream<Buffer>): AsyncReadStream<Buffer>;

readonly name: string;          // e.g. "webm-opus"
readonly pcmSampleRate: number; // sample‑rate passed to constructor
```

Internally it shells out to:

```bash
ffmpeg <inputFlags> pipe:0 <outputFlags> pipe:1 <extraFlags>
```

All data flows through **stdio** (`pipe:0`, `pipe:1`), keeping memory usage low and latency minimal.

---

## Cancellation & errors

Both `decode()` and `encode()` accept an optional `AbortSignal` (via the `pipe()` options).  
If the signal is aborted **or** the FFmpeg process exits, streaming stops cleanly.

---

## Customising FFmpeg

- **Low‑latency preset:** The default `extraFlags` array applies a sensible set of FFmpeg flags (`-flush_packets 1`, `-fflags +flush_packets+nobuffer`, …) for live scenarios.  
  Supply your own `extraFlags` if you need different behaviour.

- **Sample‑rate aware flags:** The `flags(sampleRate)` callback receives the PCM sample‑rate so you can adjust bit‑rates, filters, etc., dynamically.

Example – AAC in ADTS with 48 kHz PCM input:

```ts
export const AacAdts = createAudioFormat("aac-adts", (sr) => [
  "-c:a",
  "aac",
  "-b:a",
  sr <= 24000 ? "64k" : "128k",
  "-f",
  "adts",
]);
```

---

## Type definitions

```ts
import { AsyncReadStream } from "@mojsoski/async-stream";
import { AudioFormat } from "@silyze/async-audio-stream";

/** Factory */
declare function createAudioFormat(
  name: string,
  flags: (sampleRate: number) => string[],
  extraFlags?: string[]
): {
  new (sampleRate: number): AudioFormat;
};
```