Re-chunks a stream of raw PCM audio bytes, of any origin, into fixed-size frames suitable for a codec such as Opus.
- Buffers irregular-sized PCM chunks and emits clean, fixed-size frames
- Frame size can be given directly in bytes or derived from an
AudioFormatand a targetDuration - Trailing bytes on stream end can be zero-padded to a full frame or returned as-is
StreamTransformerwrapper for use directly in aStream<Uint8List>pipeline
import 'package:framer/framer.dart';AudioFormat currently only supports SampleEncoding.pcm16le (16-bit
signed little-endian, interleaved).
const format = AudioFormat(sampleRate: 48000, channels: 2); // PCM16LE
final framer = PcmFramer.forDuration(
format: format,
frameDuration: const Duration(milliseconds: 20),
);
await for (final chunk in pcmByteStream) {
for (final frame in framer.addChunk(chunk)) {
// send `frame` to an encoder — always exactly the configured size
}
}
final tail = framer.flush(); // trailing partial frame, zero-padded by defaultOr as a stream transform:
pcmByteStream.transform(framer.asTransformer()).listen(encoder.encode);Every frame addChunk emits lands on a whole multiple of
AudioFormat.bytesPerFrameStep, the byte size of one sample across all
channels, so a frame boundary never splits a sample.
bytesPerFrameFor(format, frameDuration) computes a frame's byte size
without needing a PcmFramer instance — handy if something downstream
needs to know the number ahead of time.
flush({padWithSilence = true}) takes padWithSilence: false if you'd
rather get the raw short remainder back instead of a zero-padded frame, or
null if nothing was buffered.
reset() clears buffered partial-frame bytes without emitting them, for
reusing a framer across capture sessions.