AirPlay.Decoder (AirPlay v0.4.1)

Copy Markdown View Source

Stream-decode an audio file to AirPlay frames with bounded memory.

Runs ffmpeg as a port, reads its interleaved s16le stdout, slices it into 352-sample stereo frames, and hands them to AirPlay.Player on demand via take/2. The alternative — decoding the whole file to one PCM buffer (see AirPlay.Source.pcm/1) — costs ~2.4 GB for a 4-hour book; this keeps only a few seconds of frames around at a time.

Flow control comes from ffmpeg's -re flag (read input at its native rate), set by AirPlay.Source.stream_args/2: ffmpeg only produces PCM at ~1× real time, which is the same rate Player drains it, so the buffer neither floods the mailbox nor grows without bound.

Summary

Functions

Wait until the decoder has buffered at least min_frames frames, or until ffmpeg exits before enough audio is available.

Returns a specification to start this module under a supervisor.

Start a decoder. Options

Take up to n buffered frames. Returns {frames, eos?}. frames may be shorter than n (or empty) if decoding is briefly behind; eos? is true once ffmpeg has finished and the buffer is drained.

Functions

await_ready(pid, min_frames \\ 16, timeout \\ 5000)

@spec await_ready(pid(), pos_integer(), timeout()) ::
  {:ok, non_neg_integer()} | {:error, term()}

Wait until the decoder has buffered at least min_frames frames, or until ffmpeg exits before enough audio is available.

child_spec(init_arg)

Returns a specification to start this module under a supervisor.

See Supervisor.

start_link(opts)

Start a decoder. Options:

stop(pid)

take(pid, n)

@spec take(pid(), non_neg_integer()) :: {[binary()], boolean()}

Take up to n buffered frames. Returns {frames, eos?}. frames may be shorter than n (or empty) if decoding is briefly behind; eos? is true once ffmpeg has finished and the buffer is drained.