I am confused about the main differences in the usage scenarios of the router.creatPlainRtpTransport and router.router.creatPlainTransport functions. Can you help me clarify this? However, my purpose is to output a data stream from MediaSoup to external tools (ffmpeg, GStreamer), which transport should I use?
router.createPlainRtpTransport() was deprecated like 4 years ago and completely removed maybe 3 years ago, so no idea why you have such a confusion (unless you are using a 5 years old mediasoup version).
router.createPlainTransport() is the only valid API.
The following is my recording code and the packet capture data on port 5004 that I listened to, but the recording failed. I have been searching for the reason for a long time but cannot find where the problem lies. I hope the teacher can answer me. Thank you very much.
code:
console.log(`${logPrefix} Starting recording for producer ${producerId}`);
const transport = await this.router.createPlainTransport({
listenIp : '127.0.0.1',
rtcpMux : true,
comedia : false
});
console.log(`${logPrefix} transport created on port : want: ${this.options.pipePort} realy: ` + transport.tuple.localPort);
let mmpegPort=5004;
let mmpegRtcpPort=5005;
await transport.connect({
ip: "127.0.0.1",
port: mmpegPort,
rtcpPort: mmpegRtcpPort
});
console.log(`${logPrefix} transport connected to FFmpeg at 127.0.0.1:${mmpegPort}`);
const consumer = await transport.consume({
producerId: producer.id,
rtpCapabilities: this.router.rtpCapabilities,
paused: false
});
const rtpParameters = consumer.rtpParameters;
//
const timestamp = new Date().toISOString().replace(/[:.]/g, '-');
// 🔁
const outputFile = path.join(this.options.recordingDir, `${recordingId}_${timestamp}.mkv`);
const codec = rtpParameters.codecs[0];
const payloadType = codec.payloadType;
const mimeType = codec.mimeType; // e.g. "video/VP8"
const clockRate = codec.clockRate || 90000;
const codecName = mimeType.split('/')[1].toUpperCase(); // "VP8"
const ssrc = rtpParameters.encodings[0].ssrc; // e.g. 525103733
//
const sdpContent = [
'v=0',
'o=- 0 0 IN IP4 127.0.0.1',
's=mediasoup-stream',
'c=IN IP4 127.0.0.1',
't=0 0',
`m=video ${mmpegPort} RTP/AVP ${payloadType}`,
`a=rtpmap:${payloadType} VP8/${clockRate}`
].join('\r\n') + '\r\n';
// SDP file
const sdpFile = path.join(tmpdir(), `${recordingId}.sdp`);
writeFileSync(sdpFile, sdpContent);
console.log(`${logPrefix} SDP file created: ${sdpFile}`);
console.log(`${logPrefix} SDP content:\n${sdpContent}`);
let ffmpegArgs = [
'-fflags', '+genpts+discardcorrupt',
'-protocol_whitelist', 'file,udp,rtp',
'-i', sdpFile,
'-max_delay', '1000000000', // 1000
'-use_wallclock_as_timestamps', '1',
'-avoid_negative_ts', 'make_zero',
'-reorder_queue_size', '4000',
'-rtbufsize', '50000000',
//'-vf', 'setpts=N/FRAME_RATE/TB',
'-c:v', 'libvpx',
'-b:v', '800k',
'-g', '60',
//'-af', 'asetpts=N/SR/TB',
'-c:a', 'aac',
'-b:a', '64k',
'-f', 'matroska',
'-y', '-nostdin',
outputFile
];
console.log(`${logPrefix} FFmpeg command: ffmpeg ${ffmpegArgs.map(arg => `'${arg}'`).join(' ')}`);
const ffmpegProcess = spawn('ffmpeg', ffmpegArgs, {
stdio: ['ignore', 'pipe', 'pipe']
});
setTimeout(async () => {
await consumer.resume();
await consumer.requestKeyFrame();
}, 1000);
and logs
[Recording:session_12345] Starting recording for producer aaa4b447-3de7-4c29-b1d9-0706b93b0408
[Recording:session_12345] transport created on port : want: 5002 realy: 10034
[Recording:session_12345] transport connected to FFmpeg at 127.0.0.1:5004
[Recording:session_12345] Consumer created. Codec: video/VP8
producer.rtpParameters:{“mid”:“0”,“codecs”:[{“mimeType”:“video/VP8”,“payloadType”:96,“clockRate”:90000,“parameters”:{},“rtcpFeedback”:[{“type”:“goog-remb”,“parameter”:“”},{“type”:“transport-cc”,“parameter”:“”},{“type”:“ccm”,“parameter”:“fir”},{“type”:“nack”,“parameter”:“”},{“type”:“nack”,“parameter”:“pli”}]},{“mimeType”:“video/rtx”,“payloadType”:97,“clockRate”:90000,“parameters”:{“apt”:96},“rtcpFeedback”:}],“headerExtensions”:[{“uri”:“urn:ietf:params:rtp-hdrext:sdes:mid”,“id”:9,“encrypt”:false,“parameters”:{}},{“uri”:“urn:ietf:params:rtp-hdrext:sdes:rtp-stream-id”,“id”:10,“encrypt”:false,“parameters”:{}},{“uri”:“urn:ietf:params:rtp-hdrext:sdes:repaired-rtp-stream-id”,“id”:11,“encrypt”:false,“parameters”:{}},{“uri”:“http://www.webrtc.org/experiments/rtp-hdrext/abs-send-time",“id”:2,“encrypt”:false,“parameters”:{}},{“uri”:“http://www.ietf.org/id/draft-holmer-rmcat-transport-wide-cc-extensions-01”,“id”:4,“encrypt”:false,“parameters”:{}},{“uri”:“https://aomediacodec.github.io/av1-rtp-spec/#dependency-descriptor-rtp-header-extension”,“id”:13,“encrypt”:false,“parameters”:{}},{“uri”:“urn:3gpp:video-orientation”,“id”:3,“encrypt”:false,“parameters”:{}},{“uri”:“urn:ietf:params:rtp-hdrext:toffset”,“id”:1,“encrypt”:false,“parameters”:{}},{“uri”:“http://www.webrtc.org/experiments/rtp-hdrext/playout-delay”,“id”:5,“encrypt”:false,“parameters”:{}}],“encodings”:[{“active”:true,“scalabilityMode”:“L1T3”,“maxBitrate”:100000,“rid”:“r0”,“dtx”:false},{“active”:true,“scalabilityMode”:“L1T3”,“maxBitrate”:300000,“rid”:“r1”,“dtx”:false},{“active”:true,“scalabilityMode”:“L1T3”,“maxBitrate”:900000,“rid”:“r2”,“dtx”:false}],“rtcp”:{“cname”:“”,"reducedSize”:true}}
consumer.rtpParameters:{“codecs”:[{“mimeType”:“video/VP8”,“payloadType”:101,“clockRate”:90000,“parameters”:{},“rtcpFeedback”:[{“type”:“nack”,“parameter”:“”},{“type”:“nack”,“parameter”:“pli”},{“type”:“ccm”,“parameter”:“fir”},{“type”:“transport-cc”,“parameter”:“”}]},{“mimeType”:“video/rtx”,“payloadType”:102,“clockRate”:90000,“parameters”:{“apt”:101},“rtcpFeedback”:}],“headerExtensions”:[{“uri”:“urn:ietf:params:rtp-hdrext:sdes:mid”,“id”:1,“encrypt”:false,“parameters”:{}},{“uri”:“http://www.webrtc.org/experiments/rtp-hdrext/abs-send-time",“id”:4,“encrypt”:false,“parameters”:{}},{“uri”:“http://www.ietf.org/id/draft-holmer-rmcat-transport-wide-cc-extensions-01”,“id”:5,“encrypt”:false,“parameters”:{}},{“uri”:“urn:3gpp:video-orientation”,“id”:11,“encrypt”:false,“parameters”:{}},{“uri”:“urn:ietf:params:rtp-hdrext:toffset”,“id”:12,“encrypt”:false,“parameters”:{}},{“uri”:“http://www.webrtc.org/experiments/rtp-hdrext/abs-capture-time”,“id”:13,“encrypt”:false,“parameters”:{}},{“uri”:“http://www.webrtc.org/experiments/rtp-hdrext/playout-delay”,“id”:14,“encrypt”:false,“parameters”:{}}],“encodings”:[{“ssrc”:153499211,“rtx”:{“ssrc”:153499212},“scalabilityMode”:“L1T3”,“maxBitrate”:900000}],“rtcp”:{“cname”:“0728ca87”,“reducedSize”:true},“mid”:"0”}
[Recording:session_12345] SDP file created: /tmp/session_12345.sdp
[Recording:session_12345] SDP content:
v=0
o=- 0 0 IN IP4 127.0.0.1
s=mediasoup-stream
c=IN IP4 127.0.0.1
t=0 0
m=video 5004 RTP/AVP 101
a=rtpmap:101 VP8/90000
[Recording:session_12345] FFmpeg command: ffmpeg ‘-fflags’ ‘+genpts+discardcorrupt’ ‘-protocol_whitelist’ ‘file,udp,rtp’ ‘-i’ ‘/tmp/session_12345.sdp’ ‘-max_delay’ ‘1000000000’ ‘-use_wallclock_as_timestamps’ ‘1’ ‘-avoid_negative_ts’ ‘make_zero’ ‘-reorder_queue_size’ ‘4000’ ‘-rtbufsize’ ‘50000000’ ‘-c:v’ ‘libvpx’ ‘-b:v’ ‘800k’ ‘-g’ ‘60’ ‘-c:a’ ‘aac’ ‘-b:a’ ‘64k’ ‘-f’ ‘matroska’ ‘-y’ ‘-nostdin’ ‘/tmp/session_12345_2025-11-28T07-06-02-123Z.mkv’
[Recording:session_12345] Recording started.
[Recording:session_12345] FFmpeg stderr: ffmpeg version 4.4.2-0ubuntu0.22.04.1 Copyright (c) 2000-2021 the FFmpeg developers
built with gcc 11 (Ubuntu 11.2.0-19ubuntu1)
configuration: --prefix=/usr --extra-version=0ubuntu0.22.04.1 --toolchain=hardened --libdir=/usr/lib/x86_64-linux-gnu --incdir=/usr/include/x86_64-linux-gnu --arch=amd64 --enable-gpl --disable-stripping --enable-gnutls --enable-ladspa --enable-libaom --enable-libass --enable-libbluray --enable-libbs2b --enable-libcaca --enable-libcdio --enable-libcodec2 --enable-libdav1d --enable-libflite --enable-libfontconfig --enable-libfreetype --enable-libfribidi --enable-libgme --enable-libgsm --enable-libjack --enable-libmp3lame --enable-libmysofa --enable-libopenjpeg --enable-libopenmpt --enable-libopus --enable-libpulse --enable-librabbitmq --enable-librubberband --enable-libshine --enable-libsnappy --enable-libsoxr --enable-libspeex --enable-libsrt --enable-libssh --enable-libtheora --enable-libtwolame --enable-libvidstab --enable-libvorbis --enable-libvpx --enable-libwebp --enable-libx265 --enable-libxml2 --enable-libxvid --enable-libzimg --enable-libzmq --enable-libzvbi --enable-lv2 --enable-omx --enable-openal --enable-opencl --enable-opengl --enable-sdl2 --enable-pocketsphinx --enable-librsvg --enable-libmfx --enable-libdc1394 --enable-libdrm --enable-libiec61883 --enable-chromaprint --enable-frei0r --enable-libx264 --enable-shared
libavutil 56. 70.100 / 56. 70.100
libavcodec 58.134.100 / 58.134.100
libavformat 58. 76.100 / 58. 76.100
libavdevice 58. 13.100 / 58. 13.100
libavfilter 7.110.100 / 7.110.100
libswscale 5. 9.100 / 5. 9.100
libswresample 3. 9.100 / 3. 9.100
libpostproc 55. 9.100 / 55. 9.100
[Recording:session_12345] Consumer stats - packetCount: 9, byteCount: 9657
[Recording:session_12345] FFmpeg stderr: [sdp @ 0x55f1d83a2540] RTP: dropping old packet received too late
[Recording:session_12345] Consumer stats - packetCount: 9, byteCount: 9657
[Recording:session_12345] Consumer stats - packetCount: 9, byteCount: 9657
[Recording:session_12345] Consumer stats - packetCount: 9, byteCount: 9657
[Recording:session_12345] Consumer stats - packetCount: 9, byteCount: 9657
[Recording:session_12345] Consumer stats - packetCount: 9, byteCount: 9657
[Recording:session_12345] Consumer stats - packetCount: 9, byteCount: 9657
[Recording:session_12345] Consumer stats - packetCount: 9, byteCount: 9657
[Recording:session_12345] Consumer stats - packetCount: 9, byteCount: 9657
[Recording:session_12345] Consumer stats - packetCount: 9, byteCount: 9657
[Recording:session_12345] Consumer stats - packetCount: 9, byteCount: 9657
[Recording:session_12345] Consumer stats - packetCount: 9, byteCount: 9657
[Recording:session_12345] Consumer stats - packetCount: 9, byteCount: 9657
[Recording:session_12345] Consumer stats - packetCount: 9, byteCount: 9657
[Recording:session_12345] Consumer stats - packetCount: 9, byteCount: 9657
[Recording:session_12345] Consumer stats - packetCount: 9, byteCount: 9657
[Recording:session_12345] Consumer stats - packetCount: 9, byteCount: 9657
[Recording:session_12345] Consumer stats - packetCount: 9, byteCount: 9657
[Recording:session_12345] Consumer stats - packetCount: 9, byteCount: 9657
[Recording:session_12345] Consumer stats - packetCount: 9, byteCount: 9657
[Recording:session_12345] Consumer stats - packetCount: 9, byteCount: 9657
[Recording:session_12345] Consumer stats - packetCount: 9, byteCount: 9657
[Recording:session_12345] Consumer stats - packetCount: 9, byteCount: 9657
[Recording:session_12345] Consumer stats - packetCount: 9, byteCount: 9657
[Recording:session_12345] Consumer stats - packetCount: 9, byteCount: 9657
[Recording:session_12345] Consumer stats - packetCount: 9, byteCount: 9657
[Recording:session_12345] Consumer stats - packetCount: 9, byteCount: 9657
[Recording:session_12345] Consumer stats - packetCount: 9, byteCount: 9657
[Recording:session_12345] Consumer stats - packetCount: 9, byteCount: 9657
[Recording:session_12345] Consumer stats - packetCount: 9, byteCount: 9657
[Recording:session_12345] Consumer stats - packetCount: 9, byteCount: 9657
[Recording:session_12345] Consumer stats - packetCount: 9, byteCount: 9657
[Recording:session_12345] Consumer stats - packetCount: 9, byteCount: 9657
[Recording:session_12345] Consumer stats - packetCount: 9, byteCount: 9657
[Recording:session_12345] Consumer stats - packetCount: 9, byteCount: 9657
[Recording:session_12345] Consumer stats - packetCount: 9, byteCount: 9657
[Recording:session_12345] Consumer stats - packetCount: 9, byteCount: 9657
[Recording:session_12345] Consumer stats - packetCount: 9, byteCount: 9657
[Recording:session_12345] Consumer stats - packetCount: 9, byteCount: 9657
[Recording:session_12345] Consumer stats - packetCount: 9, byteCount: 9657

