MixMonitor is the Asterisk application that records a channel’s audio to a file. By default it
mixes both directions of the call — what the channel hears and what it says — into a single mono
file. That is fine for a plain recording of an operator talking to a customer. But once the
recording goes into speech-to-text, sentiment analysis or QA scoring, a mixed file gets in the way:
you no longer know who said what.
This post shows how to record each side of an Asterisk call into its own file with the r() and
t() options, when the stereo D option is the better choice, and what to watch out for.
Basic call
MixMonitor(filename.extension,[options,[command]])
The extension picks the audio format (.wav, .gsm, .sln and so on). A relative filename ends up
in Asterisk’s monitor directory, /var/spool/asterisk/monitor by default.
The channel has to be answered (Answer or Progress) before MixMonitor runs — it doesn’t do
that itself. If you need the file inside the same dialplan run, for example to process it right
away, close the recording with StopMixMonitor. That is what guarantees the file is fully written
and available on disk.
Two options are worth knowing before the split:
aappends to an existing file instead of overwriting it;bsaves audio only while the channel is bridged, so ringing and IVR time stay out of the recording.
How to record each side of a call separately: r() and t()
Two options write each direction of the audio to its own file, independently of each other:
r(file)— the receive stream: what the channel hears;t(file)— the transmit stream: what the channel says.
MixMonitor(call.wav,r(call-in.wav)t(call-out.wav))
call.wav is still the ordinary mixed file, because the filename argument is mandatory. The other
two are independent streams written at the same time. This is not post-processing of one file; it
is three recordings made in parallel.
In an AEL dialplan it looks like this:
context incoming {
s => {
Answer();
MixMonitor(${UNIQUEID}.wav,r(${UNIQUEID}-in.wav)t(${UNIQUEID}-out.wav));
Dial(PJSIP/operator);
StopMixMonitor();
}
}
Using ${UNIQUEID} in the names gives every call its own set of files and makes them easy to match
with a CDR row later.
When r() or t() is used, MixMonitor inserts silence into both files so they stay in sync with
each other. The n option turns that off when synchronization isn’t needed.
One stereo file instead: the D option
The D option does something different: it interleaves both directions into a single stereo
file, one direction per channel (left and right). The choice comes down to “two separate files”
versus “one file with two audio channels”.
| You need | Use |
|---|---|
| A recording to play back to a person | the default mixed file |
| Two files you can send to different services or tools | r() and t() |
| One file that keeps the speakers apart, easy to move around | D |
Most speech-to-text services accept stereo input and treat each channel as a separate speaker, so
D is often the shortest path. If your pipeline wants one file per speaker, use r() and t().
Why separate channels matter for speech-to-text and analytics
When the operator and the customer are already on separate tracks, a recognition service doesn’t have to separate speakers (diarization) on a mixed stream. Each track goes into recognition by itself, with a guaranteed answer to “who said this”. The same applies to sentiment analysis or QA scoring: when the input is already split by role, the accuracy doesn’t depend on how well a third-party diarization algorithm happens to work.
It also makes simple metrics possible without any AI: talk-time ratio, how often the operator interrupts the customer, and silence at the start of the call.
Recording in PearlPBX2
PearlPBX2 starts recordings from its FastAGI handler. For each call it looks at the recording rules
(force-enable or force-disable by caller ID or destination), sets the MIXMONITOR channel variable
to 1 or 0, creates the database record and the YYYY/MM/DD directory, and then runs
MixMonitor on a .wav file with the a option. The result is one mixed file per call, indexed by
source, destination and CDR uniqueid, and downloadable via GET /api/v1/recordings/<uniqueid>/
with HTTP Range support. Queue calls are recorded by app_queue itself, which PearlPBX2 configures
with monitor-type = MixMonitor.
So out of the box PearlPBX2 does not split channels. If you want separate streams, MixMonitor is
on the application whitelist of the AEL editor, so you can call it with r() and t() from your own
dialplan. Keep in mind that a recording started this way is your responsibility: the FastAGI handler
is what creates the database record for a recording.
Things to watch out for
- Disk space. An 8 kHz mono WAV takes roughly 1 MB per minute. With
r()andt()you get the mixed file plus two more, so plan for about three times as much. Converting finished recordings to MP3 cuts it down. - Answer first.
MixMonitoron an unanswered channel records nothing useful. - Read the file only after
StopMixMonitorif you use it in the same dialplan run. - Consent. Recording rules differ by country. Check what you must tell the caller before you turn recording on.
Summary
| Option | What it does |
|---|---|
| no options | one mixed mono file (default) |
a |
append to the file instead of overwriting it |
b |
record only while the channel is bridged |
r(file) |
separate file for the incoming (receive) stream |
t(file) |
separate file for the outgoing (transmit) stream |
n |
disables automatic silence insertion for r()/t() synchronization |
D |
one stereo file instead of two separate ones (receive/transmit per channel) |
For the full list of options, see the MixMonitor page in the Asterisk documentation.