Wednesday 3 February 2016

Extracting Opus from a pcap file into an audible wav

From time to time I need to verify that the audio inside a trace is as expected. Not much in terms of quality, but more often content and duration.

A few years ago I wrote a small program to transform a pcap into a wav file - the codec in use was SILK.

These days I'm dealing with Opus, and I have to say things are greatly simplified, in particular if you consider opus-tools, a set of utilities to handle opus files and traces.

One of those tools, opusrtp, can do live captures and write the interpreted payload into a .opus file.
Still, what I needed was to achieve the same result but from a pcap already existing, i.e. "offline".

So I come up with a small - quite shamlessly copy&pasted - patch to opusrtc, which is now in this fork.
Once you have a pcap with an RTP stream with opus (say in input.pcap) you can retrieve the .opus equivalent (in rtpdump.opus) with:

./opusrtp --extract input.pcap

Then you can generate an audible wav file with:

./opusdec --rate 8000 rtpdump.opus output.wav

Happy decoding.


  1. Thanks Giacomo

    I found this tool very useful!

    In order to get it to work for me I had to make a couple of fixes. I was using a Linux cooked capture pcap file so I did not have the standard length ethernet packet header in the PCAP file. I worked around this by setting
    #define ETH_HEADER_LEN 20
    #define ETH_FILE_HEADER_LEN 20
    in opusrtp.c

    OPUS has a dynamically allocated payload type so the payload type can be between 96-127. Your code had a hard-coded value for the Opus payload type so I had to change this to get the decoding to work for me. To workaround this I just set
    #define OPUS_PAYLOAD_TYPE 117
    #define OPUS_FILE_PAYLOAD_TYPE 117

  2. Thanks for your comment, and I'm glad you found that work useful.
    There are indeed a couple of hardcoded values, which possibly can be either managed as input arguments for the binary, or extracted somehow from the original pcap in a more dynamic fashion.

  3. Hi Giacomo,

    thank you for your post, I'm using it. I just add an input argument to set the payload type. I use the binary in a bash script in conjunction with tshark. Tshark allows me to inspect the pcap file, extracting rtp infos from sdp messages if SIP signaling is present in pcap, and filtering opus packets before pass to opusrtp.

    Thanks a lot!

  4. Good to hear it. Happy decoding ;)
    Any improvement you may want to suggest, please feel free to raise a Pull Request.

  5. Thanks Giacomo for sharing this
    I m facing problems in running opusrtp

    When i ran the below command as you suggested
    ./opusrtp --extract input.pcap

    I got the below error
    Timestamp: 1466490413:383288
    eth 0x0800 00:07:7d:67:e1:bf -> 54:ee:75:65:3b:6a
    unhandled ip version 0
    error parsing ip header
    Got 127 byte packet (127 bytes captured)

    Though i am using ip version 4, it is displaying as version 0

  6. Hi praveen,
    please take into account that I've just hardcoded the payload type:


    and header lenght:

    #define ETH_FILE_HEADER_LEN 16

    You should in particular check the payload type. It would be great to make it dynamic or pass it as command argument.

  7. Hello!

    Thank you for your code.
    Please help me to understand where is the problem?

    root@ip-10-23-254-74:/home/ubuntu# ./opusrtp --extract opus.pcap
    Got 120 byte packet (120 bytes captured)
    skipping packet: unrecognized linktype 12
    Got 146 byte packet (146 bytes captured)
    skipping packet: unrecognized linktype 12


    1. I think this could be due to multiple streams in the packet capture, filter only one stream and then run with opusrto and hope it works , let me know if it works


  8. Hi Denys, please upload your opus.pcap somewhere and let me know when I can download it. So I can take a look.

  9. Hey!

    I have uploaded file to Google:

    This trace was from rtpengine:

    But as I see now eth header is empty, maybe that is the reason.

    Thank you for the help!


  10. Hi Giacomo,

    I'm not yet able to test the script. I'm having some issues compiling the code ( ) on Ubuntu Linux.

    I was wondering if you could provide me a quick step to follow to do the compilation, I usually get away with make install, but it's not working this time.


  11. Hi Giacomo,

    I'm not yet able to test the script. I'm having issues while trying to compile the script ( )

    I usually get away with "make install" but it's not working this time. I was wondering if you could provide a quick info I can follow to compile the script.


  12. Hi, thanks for your comment. I've never used that repo; instead I was referring to

    In general though, I'd expect you to:

    ./configure --with-opus-includes=/usr/local/include/opus --without-flac

    You don't even need 'make install' as long as you identify the location of opusrtp and opusdec binaries. Also please note that you need opus-dev installed.

    Good luck.

  13. Hi Giacomo,

    When I run the command:
    ./opusrtp --extract input.pcap
    pcap support disabled, sorry.

    Could you help me?


    1. I also encountered this problem, then I found the line 199 in, which indicates "AC_DEFINE([HAVE_PCAP], 1, [Define if building with libpcap support])", so I installed the "libpcap" and solved the problem. I hope this solution will help anyone who encountered the same problem.

  14. Thanks Giacomo,
    when I proceed as you suggested I get a rtpdump.opus of only 111bytes. Obviously opusrtp is skipping the packets.
    Wireshark suggests : payload type G.711 PCMU
    Anything needs to be adapted in the source code?
    Thx for help

    Got 105 byte packet (105 bytes captured)
    eth 0x0800 01:00:5e:05:06:08 -> b8:27:eb:74:bb:8c
    ipv4 protocol 17 -> header 20 bytes
    udp 71 bytes 54840 -> 8000 crc 0xcfc4
    rtp 0x0cf157d0 0 43406 2062153920 v2 ... CC 0 51 bytes
    skipping non-opus packet

    1. Hi, to keep it simple I've hardcoded the payload type as 120, see:

      #define OPUS_PAYLOAD_TYPE 120

      Check what's used in the actual negotiation (maybe it's 96 instead?). If it's different, change it, re-compile and try again.

    2. Ah yes, thank you.
      I just read it in the original blog:


Wireshark setting to interpret UDP as RTP automatically

 Before I forget again, a Wireshark setting that can help saving time by trying to interpret any UDP as RTP, if possible: Analyze --> Ena...