Initial Commit
This commit is contained in:
60
packages/media/audio/audio-cli/src/commands/play.md
Normal file
60
packages/media/audio/audio-cli/src/commands/play.md
Normal file
@@ -0,0 +1,60 @@
|
||||
# `commands/play` — `runPlay`
|
||||
|
||||
## Purpose
|
||||
|
||||
`runPlay` plays a file through an injected `SpeakerAdapter`. The CLI package
|
||||
intentionally carries no platform audio binding — naming a specific speaker
|
||||
binary (sox, mpv, ffplay) would couple the package to whichever the user has
|
||||
installed. Instead, the function exercises argument validation, the input
|
||||
load path, and the adapter dispatch, and consumers (or installer hooks) wire
|
||||
the actual hardware adapter behind the `SpeakerAdapter` interface.
|
||||
|
||||
A `noopSpeaker` is exported so headless servers, CI, and tests can run the
|
||||
`play` code path without audio output.
|
||||
|
||||
## Features
|
||||
|
||||
- Zod-strict `PlayOptions` accepting an injected `SpeakerAdapter` and an
|
||||
`AbortSignal`.
|
||||
- Default `noopSpeaker` adapter for headless environments.
|
||||
- Same input-error mapping (`AUDIO_CLI.INPUT_NOT_FOUND`) as the other
|
||||
load-driven commands.
|
||||
- Adapter failures wrap as `AUDIO_CLI.PIPELINE_FAILED` with the original
|
||||
cause attached.
|
||||
|
||||
## Usage: Basic
|
||||
|
||||
```ts
|
||||
import { AudioCLI } from "@suaveplan/audio-cli";
|
||||
|
||||
const cli = new AudioCLI();
|
||||
await cli.play("input.wav"); // noop on a headless host
|
||||
```
|
||||
|
||||
## Usage: Advanced
|
||||
|
||||
```ts
|
||||
import { runPlay } from "@suaveplan/audio-cli/commands/play";
|
||||
import type { SpeakerAdapter } from "@suaveplan/audio-cli/commands/play";
|
||||
|
||||
const mySpeaker: SpeakerAdapter = {
|
||||
async play(doc, { signal }) { /* ...write doc to a DAC... */ },
|
||||
};
|
||||
await runPlay(cli, "song.flac", { speaker: mySpeaker });
|
||||
```
|
||||
|
||||
## API Reference
|
||||
|
||||
- `runPlay(cli, input, opts?): Promise<void>`
|
||||
- `PlayOptions` — `{ speaker?, signal? }`
|
||||
- `SpeakerAdapter.play(doc, { signal? }): Promise<void>`
|
||||
- `noopSpeaker: SpeakerAdapter`
|
||||
|
||||
## Implementation Notes
|
||||
|
||||
The function deliberately structures the failure modes so a missing speaker
|
||||
falls through to the no-op rather than throwing — this matches `audio play`
|
||||
on a headless box: argv parses, the file decodes, and the command returns
|
||||
`0`. Real hardware bindings ship as separate adapters consumers add at
|
||||
construction time via `new AudioCLI({ ... })` or by passing `opts.speaker`
|
||||
directly.
|
||||
Reference in New Issue
Block a user