Login | Register


Documentation -> Tutorials -> Call Recording using OpenSIPS and SIPREC

This page has been visited 19820 times.

1.  Tutorial Overview

SIPREC is a standard that specifies how to do call recording in a non-intrusive way, using an external recorder. Using this protocol you can move the call recording features out of your media server to one (or many) other recorder(s), without interfering with the actual RTP flow. According to the SIPREC architecture, in order to record a call, you need two components:

  • SRC (Session Recording Client) - this is the SIP component in the call's path which triggers the call recording - this is where OpenSIPS gets involved.
  • SRS (Session Recording Server) - this is the actual recorder, the SIP component that only receives the traffic forked by the SRC and dumps it in a file - an example of a SRS is Oreka, an Open Source Enterprise Telephony Recording provided by OrecX.

This document describes the steps to configure OpenSIPS to engage one (or more) SRS recorder(s) in an ongoing call.

The work for the SIPREC module has been sponsored by the OrecX Company.

2.  Architecture

The purpose of this article is to show how one can record a call between two clients, let's call them Alice and Bob. In order to do that, we need the following components:

  • OpenSIPS - will act as a SRC, providing metadata about the call to the SRS
  • Oreka - will act as a SRS, doing the actual recording of the call
  • RTPProxy - will fork the RTP traffic to the SRS

The following diagram shows the setup and how each component interact to each other:

According to the diagram, Alice and Bob do not need to have any recording capabilities (although the SIPREC protocol also supports this model, but it is not part of this article). They will simply behave as a regular SIP client, sending SIP traffic to the OpenSIPS proxy and the RTP media to a Media Server, in our case, RTPProxy. However, when a new call is started, OpenSIPS needs to start a SIPREC session to the SRS, providing it metadata description of Alice and Bob, as well as media description in the SDP. At this point, the SRS decides whether the call is indeed intended to be recorded - if it is not, it simply rejects the call, otherwise, it sends a 200 OK, containing the SDP where to fork the media. Upon receiving this information, OpenSIPS instructs RTPProxy to start forking the clients' RTP traffic to the SRS. When the call is ended, OpenSIPS needs to also close the SIPREC session with the SRS.

3.  Basic Configuration

In this article we will only discuss about how OpenSIPS can be used to record calls using the SIPREC protocol. We will not address the SRS and RTPProxy configuration, but these should already work with the basic/default config.

We will start from an existing working setup for OpenSIPS and gradually add the necessary parts to it until we end up with a working Call Recording script. We will use OpenSIPS 2.4 default script, which provides basic call routing for clients.

The first thing we need to do is load the necessary modules involved:

  • dialog: used to keep track of the call status and close the recording when the call ends. It is also needed to handle sequential messages.
  • b2b_entities: automatically manages the SIPREC session to the SRS
  • siprec: provides the call recording logic
  • rtpproxy: used to proxy media and fork RTP traffic to the SRS

So at the beginning section of our script, we need to add the following lines:

loadmodule "dialog.so"
loadmodule "b2b_entities.so"
loadmodule "siprec.so"
loadmodule "rtpproxy.so"

We also need to specify the connector to the RTPProxy server:

modparam("rtpproxy", "rtpproxy_sock", "udp:")

Now we need to "identify" the calls we want to do call recording for. This can be done using whatever logic you want in your script, but for simplicity in this example, we will engage call recording for all users. To do this, we need to find in our script the code's section that handles the initial INVITEs. In the default script, this is done in the following snippet:

    # account only INVITEs
    if (is_method("INVITE")) {


In this code section, we need to do 3 things:

  • create the dialog, to manage the call - you can use any flags to modify the behavior - for simplicity we will use the default behavior.
  • engage RTPProxy in the call - again, for simplicity, we will use the auto-mode rtpproxy_engage provides.
  • instruct the SIPREC module that this call is intended to be recorded - we need to provision the SIP URI of the SRS - in this simple scenario, we will consider the SRS is located on the same machine as OpenSIPS, but it is listening on port 5090.

After all these changes, the previous snippet will look like this:

    # account only INVITEs
    if (is_method("INVITE")) {

And that's all! All you need to do is start OpenSIPS with the new script and make a call test.

You can find here the final configuration example.

4.  Advanced Configuration

4.1  Communicate with SRS over TCP

Although UDP communication is lightweight and the base protocol for SIP, in practice it has a big limitation: it cannot always carry large packets of data. This is SIPREC's case: when adding large SDP payloads, combined with large XML data, to a SIP overhead, you will definitely exceed the MTU (which is usually 1500 bytes), and you end up fragmenting the package. Unfortunately IP fragmentation makes a lot of routers unhappy, thus we might want to use a different method to communicate with the SRS. Luckily, we can achieve this by using TCP.

To do so, we need to make three extra changes to our previous script:

  • import the proto_tcp module, that handles the communication to a TCP endpoint

loadmodule "proto_tcp.so"

  • add a TCP listener - an interface which OpenSIPS will use to communicate to the SRS over TCP

listen = tcp:

  • change the SRS URI, adding the ;transport=tcp parameter


After these changes you can reliably communicate with your SRS Recorder over TCP.

4.2  Use a specific interface to communicate with SRC

In real scenarios, you might want to put the communication with SRS on a separate/dedicated IP in a local LAN. In order to do this, you need to also specify the desired interface to OpenSIPS, by forcing the communication socket before engaging siprec:

force_send_socket(udp:; # restore the initial interface

"""Note""" that after forcing the SRS interface, you need to restore the initial interface, otherwise OpenSIPS will try to reach the callee using the dedicated interface.

4.3  Advanced RTPProxy configuration

In the initial scenario we used the rtpproxy_engage function, which blindly handles the RTPProxy media proxy. However, in practice, you need to make some fine tuning to the flags passed to the RTPProxy server, such as whether it should trust the IP in the SDP, whether it should act as an asymmetric proxy, etc. This means that you will probably need to use the rtpproxy_offer/rtpproxy_answer combination. This will work perfectly fine and there are no restrictions regarding the order of the rtpproxy_offer and siprec_start_recording calls.

However, if you configuration runs in a more advanced setup, where you are using RTPProxy sets, you need to make sure that you are providing the same set to SIPREC as well, otherwise recording will fail. So for example if you are using set """5""" for a specific group of users, you will also have to specify it in the 5th parameter of siprec_start_recording. A configration example is below:


4.4  Changing Call Participants Metadata

The SIPREC protocol consists of a set of metadata information about the participants of the call. By default, OpenSIPS takes those participants from the From and To headers. However, if the received message contains a DID, or an alias of the User, you do not want to forward that information, but the actual account. You can tune this information in the 3rd and 4th parameters of the siprec_start_recording() function. The format of these parameters is a name-addr as specified by the SIP RFC, followed by the \r\n header termination. Here is an example:

$var(caller) = "\"John Doe\" <sip:john@opensips.org>\r\n";
$var(callee) = "\"Jane Doe\" <sip:jane@opensips.org>\r\n";
siprec_start_recording("sip:;transport=tcp",, "$var(caller)", "$var(callee)");

One can also group the calls recorded based on a tag (group as specified in the SIPREC RFC). This is done by the second parameter of the siprec_start_recording() function:

siprec_start_recording("sip:;transport=tcp", "regular", "$var(caller)", "$var(callee)");

4.5  SRS Fail-over

There might be cases when a SRS might be down, or cannot be reachable, and you want to fail-over to a different server. This can be achieved by enlisting all the servers in the first parameter of the siprec_start_recording() function, separated by comma. The following example tries to connect to the SRS over TCP, and if that fails, it tries to reach it over UDP:

siprec_start_recording("sip:;transport=tcp, sip:");

By default, fail-over is driven by a negative response from the SRS, or by an auto-generated 408 if the SRS does not respond. However, not all responses mean the service is unavailable, some of them might simply indicate that the call should not recorded. In this case, you might want to ignore some response codes from the fail-over algorithm. This is done using the skip_failover_codes parameter. The following example prevents fail-over for any class 3 and 4 response codes - thus it only fails-over 5xx and 6xx classes:

modparam("siprec", "skip_failover_codes", "[34][0-9][0-9]")

Page last modified on October 25, 2017, at 07:00 PM