rtpengine-recording(8)
π rtpengine-recording β the rtpengine-recording(8) manual, but make it make sense β¨
okay bestie, grab a strawberry π and sit down, because we're doing the NGCP rtpengine-recording manual page and I am genuinely obsessed with it. it's giving "media recording daemon for Sipwise rtpengine" and honestly? she ate. π
π NAME
rtpengine-recording β media recording daemon for Sipwise rtpengine π
πΈ SYNOPSIS
rtpengine-recording [option...]
π DESCRIPTION
so the Sipwise rtpengine media proxy has support for exporting media (RTP) packets that it forwards. and the rtpengine-recording daemon? she collects all those exported packets and decodes them into an audio format that you can actually listen to. no cap, that's the whole vibe. π¦
π OPTIONS π
quick heads-up before we dive in: all options can β and honestly should β be provided in a config file instead of at the command line. peek at the --config-file option below for the deets. π
and if you give her no options at all, then default values are assumed, which should be totally sufficient for a standard installation of rtpengine. easy. β¨
--helpβ prints the usage information. iconic of her tbh.-v,--versionβ if you call thertpengine-recordingdaemon with this option, she'll simply print her version number and exit. she's like "here's who I am π bye". π--config-file=FILEβ specifies the location of a config file to be used. π the config file is an.inistyle config file, and all command-line options listed on this page are also valid options in the config file. important: for every command-line option, you have to use the long name version instead of the single-character version (so like,tableinstead of justt). for boolean options that are either present or not (thinkoutput-mixed), you must use a boolean value in the config file β eithertrueorfalse, no vibes-based guessing. and if an option is given in both the config file and the command line? the command-line value overrides the value from the config file. command line has main character energy, periodt. π
as a special value, you can pass none here to suppress loading of the default config file.
--config-section=STRINGβ specifies the.inistyle section to be used in the config file. multiple sections can be present in the config file, but only one can be used at a time π. the default value isrtpengine-recording. a config file section is started in the config file using square brackets, like[rtpengine-recording]. π§-L,--log-level=INTβ takes an integer as argument and controls the highest log level which will be sent to syslog. the log levels correspond to the ones found in thesyslog(3)man page, iykyk. the default value is6, equivalent toLOG_INFO. the highest possible value is7(LOG_DEBUG) which will log everything β like, everything everything. π--log-facilty=daemon|local0|...|local7|...β the syslog facilty to use when sending log messages to the syslog daemon. defaults todaemon. (and yes, the option is literally spelledfaciltyin the manual, no I'm not fixing her, she's perfect the way she is π«Ά)-E,--log-stderrβ log to stderr instead of syslog. only useful in combination with--foreground. π₯οΈ--split-logsβ split multi-line log messages into individual log messages, so that each line receives its own log line prefix. one line, one prefix, one vibe. βοΈ--no-log-timestampsβ don't add timestamps to log lines written to stderr. only useful in combination with--log-stderr. π--log-mark-prefix=STRINGβ prefix to be added to particular data fields in log files that are deemed sensitive and/or private information. defaults to an empty string. π--log-mark-suffix=STRINGβ suffix to be added to particular data fields in log files that are deemed sensitive and/or private information. defaults to an empty string. π-p,--pidfile=FILEβ specifies a path and file name to write the daemon's PID number to. π-f,--foregroundβ if given, prevents the daemon from daemonizing, meaning she'll stay in the foreground. super useful for debugging, bestie. π-t,--table=INTβ takes an integer argument. the value must match the table option given to the rtpengine media proxy to use for in-kernel packet forwarding. defaults to0if not specified. π’--spool-dir=PATHβ the path given here must match the recording-dir path given to the rtpengine media proxy. defaults to/var/spool/rtpengine. also, the path must reside on a file system that supports the inotify mechanism. β οΈ--num-threads=INTβ how many worker threads to launch. defaults to the number of CPU cores available, or8if there are fewer than that or if the number is not known. she's adaptive. πͺ--thread-stack=INTβ set the stack size of each thread to the value given in kB. defaults to2048kB. can be set to-1to leave the default provided by the OS unchanged. π§΅--evs-lib-path=FILEβ points to the shared object file (.so) containing the reference implementation for the EVS codec. see the README for more details. π--output-storage=file|db|memory|notify|s3|gcs|noneβ where to store media files. ποΈ this option can be given multiple times (or, in the config file, using a comma-separated list) to enable multiple storage modes. by default only the file storage is enabled.
the file storage writes media files directly to the file system (see output-dir).
setting none overrides file storage as being the default and allows forwarding-only operation. π«
the db storage writes media files as a BLOB in a MySQL database. π¬
the string both is recognised as legacy alternative to enabling both file and db storage.
the notify output attaches the recording to the HTTP notification request. if enabled, notification requests behave as HTTP POST (implicitly enabling notify-post). π¨
the string memory acts as a modifier and can be used if file storage is not enabled. without the memory modifier, media is first written to a temporary file before being placed into its destination storage when recording is finished. with memory set, use of temporary files is disabled and media is kept in memory only until recording is complete. π§
db-mem can be used as a shortcut to setting both db and memory.
the s3 storage option enables upload to an S3-compatible service via HTTPS, for example to AWS or MiniO. see the related option below for configuration. βοΈ
use the gcs storage option to enable uploads to Google Cloud Storage or a compatible service. see the related options below. βοΈβ¨
--output-dir=PATHβ path for media files to be written to if file output is enabled. defaults to/var/lib/rtpengine-recording. β οΈ the path must not be the same as used for thespool-dir.--output-pattern=STRINGβ file name pattern to be used for recording files. the pattern can reference sub-directories, and parent directories will be created on demand. ποΈ the default setting is%c-%r-%t.
the pattern must include printf-style format sequences. here are the supported ones, and bestie, I'm listing every single one because they all matter:
%%β a literal percent sign.%cβ the call ID. it is mandatory for the output pattern to include this format sequence. β%rβ a random tag generated by rtpengine to distinguish possibly repeated or duplicated call IDs. π²%tβ the stream type. for single streams this is the SSRC written as hexadecimal; for mix stream this is the stringmix. it is mandatory for the output pattern to include this format sequence. β%lβ the label for the participating party as communicated from the controlling daemon. π·οΈ%Y%m%d%H%M%S
these format sequence reference the current system time (when the output file was created) and are the same as the format sequences supported by date(1) or strftime(3) (year, month, day, hours, minutes, and seconds, respectively). β°
%uβ microseconds, expanded to 6 digits (000000through999999). π¬%INTβ references a prefix from the call ID of the given length. if this format sequence is present more than once, then the prefixes are cumulative. for example, if the call ID isabcdefghand the output pattern is configured as%2/%3/%c, then the resulting output file name would beab/cde/abcdefgh. π€―%{β take the string between the enclosing opening and closing brace (between this{and the next}) and use it as a key to look up a corresponding value in the metadata string provided by rtpengine. the metadata string must be given as a pipe (|) separated list ofkey:valuepairs, as described in the rtpengine documentation. π
example: if the metadata string is given as foo:bar|blah:baz and the pattern includes the format %{foo} then bar will be inserted into the file name at that position. π―
--output-format=wav|mp3|noneβ file format to be used for media files that are produced. defaults to PCM WAV (RIFF) files. π΅ applicable for both files stored on the file system and in a database.
none is a legacy alias for output-storage=none.
--resample-to=INTβ resample all audio to the given sample rate (e.g.48000). resampling is disabled by default, meaning that files will be written with the same sample rate as the source media. πΆ--mp3-bitrate=INTβ if MP3 output is selected, use the given bitrate for the MP3 encoder (e.g.64000). there is no default value, so this option must be given if MP3 output is selected. β οΈ note that not all bitrates are valid in combinations with all sample rates. for MP3 output it's therefore recommended to also setresample-to. π§--output-mixed--output-single
whether to produce mixed audio files, or single audio files, or both. if neither option is given, then by default both are enabled. β¨ if no file output is desired, set output-format to none.
a single audio file contains the audio for a single RTP SSRC, which usually means an unidirectional audio stream. these are decoded directly from an RTP stream and do not take timestamping into account, meaning that gaps or pauses in the RTP stream are not reflected in the output audio file. π
a mixed audio file consists of the first four RTP SSRC seen, mixed together into a single output file, which usually means that a bidirectional audio stream is produced. audio mixing does take RTP timestamping into account, so gaps and pauses in the RTP media are reflected in the output audio to keep the multiple audio sources in sync. π«Ά
--mix-method=direct|channelsβ selects a method to mix multiple audio inputs into a single output file for mixed output. the default isdirectwhich directly mixes all audio inputs together, producing a mixed output file with the same format as an audio file from a single input (output-single) would be. ποΈ
okay so this first bit is still riding the wave of the mixing settings, mmkay? The channels mixing method is the one that splits every audio input into its own audio channel in the output file, so what you get back is a whole multi-channel output file. You can have up to four separate RTP SSRCs in one mixed output, which means if every single input is mono audio, then that mixed output file is gonna be carrying 4 audio channels. π Big caveat though: this mixing method requires an output file format that actually supports these kinds of multi-channel audio formats (e.g. wav). Like, don't come crying to me when your format can't hold four channels bestie, it's giving format-limited π
--mix-num-inputs=INTβ changes the number of recording channels in the output file. The value lives between 1 to 4 (e.g.4, which is also the default value). β¨--output-chmod=INTβ sets the file permissions of recording files to the given mode. Has to be an octal integer, for example0660. π--output-chmod-dir=INTβ same energy, changes the file permissions to the given mode. Also must be an octal integer, for example0700(which is also the default value, no cap).--output-chown=USER|UID--output-chgrp=GROUP|GID
Both of these change the ownership of recording files. You can hand it user/group names or numeric IDs, whichever vibe you're on. And if the value is blank or given as -1 then the user/group is just left unchanged, periodt. π«Ά
--output-buffer=INTβ sets the size of the I/O buffer used for writing files. Default is 2^18 bytes (256 kB). You can set it to zero to effect unbuffered I/O. πΈ--mysql-host=HOST|IP--mysql-port=INT--mysql-user=USERNAME--mysql-pass=PASSWORD--mysql-db=STRING
Configuration for a MySQL storage backend. Details about the calls and the media files that get produced are stored into the database. Optionally the media files themselves can be stored as well β go look at output-storage for that one. π
For the MySQL database schema, see Database schema.
--forward-to=PATHβ forwards raw RTP packets to a Unix socket. Disabled by default. π--tcp-send-to=IP:PORT--tcp-resample=INT__--tcp-mixed--tls-send-to=IP:PORT--tls-resample=INT__--tls-mixed
These send decoded audio over a TCP or TLS connection to the destination you specified. The audio goes out as raw 16-bit PCM at the given sample rate. π
By default, one connection with one mono audio stream gets established for each SSRC. If mixed mode is enabled, then β similar to the mixed file output β you get one connection per call instead, containing audio mixed together from all captured SSRCs. The mix-method setting is honoured in exactly the same way, so the audio will be either mono or multi-channel depending on that setting.
Only one of these option combinations (TCP or TLS) can be active at the same time. Pick a lane bestie π
--notify-uri=URIβ enables HTTP notification about finished recordings to the specified URI, which must be an HTTP or HTTPS URI. Info about the finished recording gets handed over via custom HTTP headers, and all of them use a prefix ofX-Recording-. π¬--notify-postβ use HTTP POST instead of GET for the HTTP notification requests. The request body is empty even if POST is used. (Yes, empty. That's the whole point. π)--notify-no-verifyβ disables TLS peer certificate verification for HTTPS requests. π--notify-command=PATHβ an external command to launch to send a notification about a new recording. That command receives two command line arguments: the full path and file name of the recording, and the ID number from the database entry.--notify-concurrency=INTβ the maximum number of HTTP requests to perform simultaneously.--notify-retries=INTβ how many times to retry a failed HTTP notification before giving up. An exponential falloff time is used for each subsequent attempt, starting with 5 seconds. β°--notify-recordβ legacy alias foroutput-storage=notify. If no other output storage is enabled, then the default file storage remains enabled (unless the following option is also set). π΅--notify-purgeβ legacy option to disable the default file storage when notification output is enabled.--output-mixed-per-mediaβ forces one channel per media instead of per SSRC. Note that this option is only useful if--output-mixedis also enabled. π--flush-packetsβ forces the output buffer to be flushed after every packet, ensuring that the recording file grows steadily and becomes available for processing without delays. β¨--s3-host=HOST--s3-port=INT--s3-path=STR--s3-access-key=STR--s3-secret-key=STR--s3-region=STR--s3-no-verify
These options must be configured if S3 storage upload is enabled. The port is optional and defaults to 443 (HTTPS) if you don't configure it. πͺ£
The host name may or may not need to include the bucket name. For example minio.example.com or examplebucket.s3.amazonaws.com.
The path can be blank if the host name includes the bucket name. Otherwise the bucket name becomes part of the path (such as /examplebucket). This option must still be set even if the path is blank β yes, even then, don't skip it.
Access key and secret key are the credentials provided by the service (e.g. AKIAIOSFODNN7EXAMPLE and wJalrXUtnFEMI/K7MDENG/bPxRfiCYEXAMPLEKEY).
The region code is part of the credentials (e.g. us-east-1). If the service doesn't use a region code, then this must be set to a blank string. π
TLS certificates are verified by default, unless the no-verify option is set.
--gcs-uri=URI--gcs-key=STR--gcs-service-account=FILE--gcs-scope=STR--gcs-no-verify
Configure these settings to use GCS storage. At least the URI and an authentication method must be set, both of them, no half-sending it. π«Ά
The gcs-uri must point to the full URI to post uploads to. Typically it would contain the name of the storage bucket. The URI must not contain a query string (i.e. no ?). For example:
https://storage.googleapis.com/upload/storage/v1/b/examplebucket/o
For authentication, either an API key must be provided via gcs-key, or OAuth2 authentication via a service account file must be configured. Pick one, they're not a couple. π
To use OAuth2/JWT authentication, the gcs-service-account setting must point to a service account file in JSON format. This file should at least contain a client_email, a private_key in RSA/PEM format, and a token_uri. The authentication scope defaults to https://www.googleapis.com/auth/cloud-platform but can be changed via gcs-scope.
Set gcs-no-verify to disable TLS certificate verification. Note that this only applies to the uploads themselves, not to OAuth2 requests. π
πͺβ¨ EXIT STATUS β¨πͺ
0β successful termination. slay, we're done π1β an error occurred. π
π FILES π
/etc/rtpengine/rtpengine-recording.confβ configuration file. That's the one, the whole vibe lives here. π
ποΈπΎ DATABASE SCHEMA πΎποΈ
Saving recordings into a MySQL database requires the correct database schema, no shortcuts bestie:
CREATE TABLE `recording_calls` (
`id` int(10) unsigned NOT NULL AUTO_INCREMENT,
`call_id` varchar(250) NOT NULL,
`start_timestamp` decimal(13,3) DEFAULT NULL,
`end_timestamp` decimal(13,3) DEFAULT NULL,
`status` enum('recording','completed','confirmed') DEFAULT 'recording',
PRIMARY KEY (`id`),
KEY `call_id` (`call_id`)
);
CREATE TABLE `recording_streams` (
`id` int(10) unsigned NOT NULL AUTO_INCREMENT,
`call` int(10) unsigned NOT NULL,
`local_filename` varchar(250) NOT NULL,
`full_filename` varchar(250) NOT NULL,
`file_format` varchar(10) NOT NULL,
`stream` mediumblob,
`output_type` enum('mixed','single') NOT NULL,
`stream_id` int(10) unsigned NOT NULL,
`sample_rate` int(10) unsigned NOT NULL DEFAULT '0',
`channels` int(10) unsigned NOT NULL DEFAULT '0',
`ssrc` int(10) unsigned NOT NULL,
`start_timestamp` decimal(13,3) DEFAULT NULL,
`end_timestamp` decimal(13,3) DEFAULT NULL,
`tag_label` varchar(255) NOT NULL DEFAULT '',
PRIMARY KEY (`id`),
KEY `call` (`call`),
CONSTRAINT `fk_call_id` FOREIGN KEY (`call`) REFERENCES `recording_calls` (`id`) ON DELETE CASCADE ON UPDATE CASCADE
);
CREATE TABLE `recording_metakeys` (
`id` int(10) unsigned NOT NULL AUTO_INCREMENT,
`call` int(10) unsigned NOT NULL,
`key` char(255) NOT NULL,
`value` char(255) NOT NULL,
PRIMARY KEY (`id`),
KEY `prim_lookup` (`value`,`key`),
KEY `fk_call_idx` (`call`),
CONSTRAINT `fk_call_idx` FOREIGN KEY (`call`) REFERENCES `recording_calls` (`id`) ON DELETE CASCADE ON UPDATE CASCADE
);
π SEE ALSO π
rtpengine(8). Go read that one too, it's the main character of this whole cinematic universe. π
and that's a wrap on this page bestie π this was version 26.0.1.21+0~mr26.0.1.21, dated 2026-07-31, and yes, rtpengine-recording(8) is the name, don't wear it out π
go record something iconic β¨π¦
π¦ where this page comes from
- ubuntu stonking: rtpengine-recording-daemon 26.0.1.21-1 Β· GPL-3.0-or-later WITH OpenSSL exception
- π girlified by deepseek-ai/DeepSeek-V4.1-Flash on : a language model's rewrite of the original, under its terms