I was able to create a wav file from a wireshark capture. Here is how I do it.
1. I use tcpdump to capture all the packets and filter for RTP packets. Each RTP packet has a "Synchornization source identifier" and that how you can filter by an audio stream:
That picture shows an Opus codec but if on my phone call I was using ulaw then it would show RTP.
2. Then I save that capture as another pcap file.
3. Then if I use a program to iterate through every packet and remove the first 12 bytes of the payload and append those bytes to a file I end up with a file that I can listen too on audacity by selecting the correct format. Actually I can convert that audio.ulaw file to wav with this command:
# apt-get install ffmpeg -y
ffmpeg -f mulaw -ar 8000 -i audio.ulaw -acodec pcm_s16le -ar 8000 -ac 1 output.wav
Now I am curios how can I build a playable file and do the same thing I did using the ulaw codec but with Opus. I know that the sdp packet contains all the information. How can I build an opus file based on that capture. I know the capture is correct because Wireshark is able to play that opus stream if I go to Telephone -> VOIP Calls -> Play Streams:
This is how I constructed the ulaw file that worked and its the same idea with opus. Its a c# program that reads data from each packet. It checks that the sequence is correct and for now that I am testing I harcoded the values:
using SharpPcap;
using SharpPcap.LibPcap;
var inputFilePath = @"C:\temp.pcap";
var outputFilePath = @"C:\raw.opus";
// Open the pcap file
using var reader = new CaptureFileReaderDevice(inputFilePath);
reader.Open();
using var outputFileStream = new FileStream(outputFilePath, FileMode.Create);
var lastLength = 0;
var i = 0;
// harcoded because of wireshark capture told me
var lastSequence = 20585;
// Read packets
while (reader.GetNextPacket(out var packet) == GetPacketStatus.PacketRead)
{
i++;
var data = packet.Data;
// ignore small packets
if (data.Length < 54)
{
continue;
}
// get the id of packet. In reality this is 4 bytes long but since my capture is already a filter this works for now
if (packet.Data[0x35] != 0x3c)
{
continue;
}
// convert sequence using little endian to a unsigned int
// this sequence has to increment
byte a = packet.Data[0x2c];
byte b = packet.Data[0x2d];
// little indean
var s = BitConverter.ToUInt16(new byte[] { b, a });
if (s == lastSequence)
{
// good
lastSequence++;
}
else
{
Console.WriteLine("errrr");
throw new NotImplementedException();
}
var audio = packet.Data[54..];
outputFileStream.Write(audio);
}
// Cleanup
outputFileStream.Close();
reader.Close();

