# `commands/convert` — `runConvert` ## Purpose `runConvert` is a deliberately thin wrapper around `runProcess`. It validates the small `ConvertOptions` surface (`format`, `bitDepth`, `signal`) and forwards into the shared decode/encode path with no pipeline ops. Keeping it this thin means the format mapping, codec lookup, abort handling, and error translation live in exactly one place — the `process` command — which the spec calls out as the single source of truth for streaming through `audio-core`/`audio-codecs`/`audio-engine-server`. ## Features - Zod-strict validation of `ConvertOptions`. - Optional explicit `format` overriding extension detection. - Optional `bitDepth` forwarded to the codec encoder where supported. - Pre-aborted signal short-circuits via `runProcess`. ## Usage: Basic ```ts import { AudioCLI } from "@suaveplan/audio-cli"; const cli = new AudioCLI(); await cli.convert("input.wav", "output.flac"); ``` ## Usage: Advanced ```ts import { runConvert } from "@suaveplan/audio-cli/commands/convert"; await runConvert(cli, "input.wav", "output.aiff", { bitDepth: 24 }); ``` ## API Reference - `runConvert(cli, input, output, opts?): Promise` - `ConvertOptions` — `{ format?, bitDepth?, signal? }` - `ConvertOptionsSchema` — Zod boundary validation. ## Implementation Notes Because the implementation forwards into `runProcess`, every error code that `runProcess` produces (`INPUT_NOT_FOUND`, `BAD_OUTPUT`, `PIPELINE_FAILED`, `ABORTED`) is reachable from `convert` as well. The empty pipeline path is not a special case in `runProcess`: an empty edit chain just means "decode → re-encode", which is exactly the conversion semantic. The Zod schema is `strict()`, so a typo in an option key (`{ formt: "wav" }`) fails fast at the boundary with `AUDIO_CLI.INVALID_ARGS` rather than being silently dropped. The `bitDepth` field is constrained to the union `8 | 16 | 24 | 32` so encoders that only accept those depths receive a correctly-typed value. Passing an `AbortSignal` that is already aborted at call time short-circuits inside `runProcess` before any file is opened, so `convert` participates in the same SIGINT contract as every other command. `convert` is the cheapest way to migrate a file between formats in shell pipelines: it skips the planner and the op chain entirely, so a file with no edits goes straight through the codec stack. For copying with an op chain attached, prefer the `process` command directly — `convert` is deliberately a forward-only wrapper with a smaller option surface.