PCM stream
While recording, the recorder can send you the raw audio in small chunks, for example to run speech recognition or voice activity detection while the user is still talking.
tsx
import { WaveformRecorderView } from 'react-native-waveform-recorder';
import {
decodePcmChunk,
pcmToMonoFloat32,
} from 'react-native-waveform-recorder/pcm-stream';
<WaveformRecorderView
ref={ref}
style={{ height: 56 }}
output={{ format: 'wav', sampleRate: 16000, channels: 1 }}
enablePcmStream
pcmChunkMs={100}
onPcmChunk={(e) => {
const int16 = decodePcmChunk(e.chunk);
const float32 = pcmToMonoFloat32(int16, e.channels);
vad.push(float32, e.sampleRate);
}}
/>;Requirements
output.formatmust be'wav'. With any other formatenablePcmStreamis ignored and no chunk is sent.- Set
enablePcmStreambeforestart(). The setting is read when a segment starts recording. - The recording file is still written as usual and
onCompletestill fires.
The chunk
| Field | Meaning |
|---|---|
chunk | Base64 string of interleaved little-endian 16-bit PCM. |
sampleRate | Sample rate in Hz, from output.sampleRate. |
channels | Channel count. |
bytesPerSample | Always 2. |
timestampMs | Recorded time when the chunk was sent, in ms. |
pcmChunkMs (default 200, minimum 20) sets the approximate chunk length:
- iOS reads new bytes from the WAV file every
pcmChunkMs, at most 256 KB per chunk. - Android collects samples from
AudioRecorduntil it has aboutpcmChunkMsof audio, then sends them. The remaining samples are sent when recording stops.
Helpers
The helpers live in the react-native-waveform-recorder/pcm-stream subpath, so apps that do not import them do not ship them.
| Function | What it does |
|---|---|
decodePcmChunk(chunk) | Decodes the base64 payload into an Int16Array. Uses globalThis.atob when available and a built-in decoder otherwise. |
pcmToMonoFloat32(int16, channels) | Converts interleaved Int16 into mono Float32Array in [-1, 1]. Stereo pairs are averaged. |
See the API reference for signatures.
Limits
- Chunks cross the bridge as base64 strings. That is fine for speech at 16 kHz mono (32 KB per second), but for several MB per second consider a JSI audio library such as react-native-audio-api.
- On iOS, after
pause()andresume()the stream starts reading the current file from the beginning again, so audio sent before the pause can be sent a second time. On iOS the last partial chunk beforepause()orstop()is not sent. If exact continuity matters, use the final WAV file fromonCompleteas the source of truth. - Chunks are delivered on the JavaScript thread. Keep
onPcmChunklight and hand heavy work to a worker or native module.