Call recording storage, retention, off-host transfer, and CDR extraction on Vicidial
Call recordings and CDR data are the two artifacts Vicidial® generates that always grow without bound and always become a compliance or storage problem the day you ignore them. This article covers where they live, how to size, how to move them off the VPS, and how to extract reporting data for external consumption.
Where recordings live
Default Asterisk monitor path on ViciBox:
/var/spool/asterisk/monitor/— in-progress recordings (audio still being written)./var/spool/asterisk/monitorDONE/— completed recordings. Files are moved here on call hangup.
Filename format:
<callerid>_<date>_<time>_<uniqueid>.<ext>
— e.g.,
5551234567_20260620-143055_1718908255.42-out.wav.
The Vicidial database table recording_log maps
each recording filename to the call's lead_id, campaign_id,
agent_user, length, and start_time.
Storage sizing
| Codec / format | Per minute | Per 10K calls (5min avg) |
|---|---|---|
| WAV (linear PCM) | ~1.4 MB | ~70 GB |
| WAV49 (gsm-in-wav) | ~165 KB | ~8 GB |
| gsm (raw) | ~160 KB | ~8 GB |
| mp3 (post-encode, 32kbps) | ~240 KB | ~12 GB |
WAV is the Vicidial default and produces the best audio for QA / scoring; the storage cost adds up fast at any volume. Most operators encode to mp3 (32-64 kbps) shortly after the call ends, which gets storage to manageable levels without losing the intelligibility needed for review.
Configuring the recording format
Per-campaign: Admin → Campaigns → Modify → Audio
Format. WAV is default; switching to GSM or MP3 changes
new recordings only — existing files keep their format. The MP3
option requires lame installed on the VPS
(zypper install lame on openSUSE Leap).
Server-wide default is in Admin → Servers → Modify Server → Recording File Format. Per-campaign overrides server-wide.
Off-host transfer pattern
The standard pattern: cron job runs every 5-15 minutes,
rsyncs monitorDONE/ to an archive target,
optionally deletes the source after successful transfer. The
key safeties:
- Only move files older than ~5 minutes (avoid in-flight confusion where Asterisk hasn't fully released the file handle).
- Use
--remove-source-filesonly after confirming the rsync succeeded (rsync's own behavior is to remove on success; cron's exit-code handling matters if you wrap it). - Keep the recording_log database rows even after the file moves — they're tiny and you'll want them for complaint research.
Example crontab:
*/10 * * * * find /var/spool/asterisk/monitorDONE -type f -mmin +5 \
-exec rsync -aR --remove-source-files {} archive@archive.example.com:/recordings/ \;
If you prefer object storage (S3-compatible), use
rclone with --min-age 5m --delete-after
against a bucket. rclone is in openSUSE's main repo.
Retention policy
How long to keep recordings is driven by:
- TCPA / complaint defense — 4 years federal statute of limitations on TCPA private right of action. Carriers may produce records older than that as evidence.
- PCI/HIPAA — if your prospects ever speak credit card or health info, you have higher retention/encryption obligations. Either ensure they never do (script discipline, agent training) or treat recordings as PCI/HIPAA workload.
- Storage cost — backwards from your archive cost-per-GB and your monthly recording volume.
Most outbound-only operations land at 90 days hot (searchable on the VPS), then archive to cheaper storage for 1-4 years. Operations dialing into regulated verticals (insurance, healthcare, financial) often keep 7 years per their own compliance regimes.
Linking recordings to leads after they're archived
The recording_log rows have a
filename field that's the path to the recording at
record time. After you archive, the file is no longer at that
path. Two approaches:
- Update the path — write back the new
archive URL into
recording_log.filenameas part of the archive cron. Vicidial's recording playback UI will then link to the archive directly (or fail gracefully if you require authentication). - Keep two paths — add a column to
recording_logfor archive_url; original filename column is unchanged. Build your own playback UI that checks both. More flexible, more work.
CDR extraction
Vicidial keeps multiple call-detail tables:
vicidial_log— every outbound dial attempt, success or fail. Joins to leads vialead_id.vicidial_closer_log— inbound calls handled by closers (agents on inbound queues).vicidial_agent_log— agent state changes (login, logout, pause, available). Useful for productivity reporting.vicidial_xfer_log— agent-to-agent transfers.call_log— raw Asterisk-side CDR rows (one per channel).
For external reporting (BI tools, dashboards), the simplest pattern is a read-only MySQL/MariaDB account that pulls from these tables nightly. Don't query the live database during working hours from a heavy external tool — the dialer is already hitting these tables thousands of times an hour.
Example queries that get used a lot:
-- Per-campaign daily call summary
SELECT
campaign_id,
DATE(call_date) AS day,
COUNT(*) AS attempts,
SUM(status='A') AS answered,
SUM(status='AB') AS abandoned,
AVG(length_in_sec) AS avg_seconds
FROM vicidial_log
WHERE call_date >= CURDATE() - INTERVAL 30 DAY
GROUP BY campaign_id, DATE(call_date);
-- Per-agent productivity for one day
SELECT
user,
SUM(event = 'LOGIN') AS logins,
SUM(sub_status = 'PAUSE') * 60 AS paused_seconds,
SUM(sub_status = 'IDLE') * 60 AS idle_seconds,
SUM(sub_status = 'INCALL') * 60 AS oncall_seconds
FROM vicidial_agent_log
WHERE event_date BETWEEN '2026-06-20 00:00' AND '2026-06-20 23:59'
GROUP BY user;
Database archiving — keep CDR queries fast
The Vicidial database grows linearly with call volume. At ~50,000 calls/day, after a year vicidial_log alone has 18M rows. Reporting queries get slow.
Archive pattern (per the ViciDial documentation but worth restating):
- Monthly:
SELECT INTO OUTFILErows older than 6 months from vicidial_log, vicidial_closer_log, vicidial_agent_log, and call_log into per-table CSVs. - Verify the CSV row counts match the rows you intend to delete.
DELETEthe same range.OPTIMIZE TABLEafter the delete to reclaim the space.
If you need queryable history, load the CSVs into a separate "archive" database on the same server (or a different host) and keep your reports configured to UNION across hot + archive when they need to.
Also Read
Powered by WHMCompleteSolution