Browser To Recorder
This is the reverse of the "stream to browser" path.
The pipeline is:
browser -> WebRtcTrackReceiver -> VideoDecoder -> MultiplexPacketEncoder -> fileIt matters because it proves the receive side is real: not just signalling, not just an open peer connection, but actual browser-originated media getting decoded and written to disk.
What The Recorder Actually Does
The current media-recorder sample:
- connects to Symple
- creates a receive-capable
PeerSession - auto-accepts incoming calls
- waits for
Active - attaches to
videoReceiver() - decodes H.264
- lazily opens the MP4 mux once the first decodable frame arrives
- writes the file until the call ends
That lazy mux open is important. It means the output file takes its real dimensions and pixel format from the stream that actually arrived, instead of from hard-coded guesses.
It also means the sample can survive a browser joining mid-GOP. If the first packets are not decodable yet, it waits for the first usable keyframe instead of creating garbage output.
Minimal Shape
The session side:
session.IncomingCall += [&](const std::string&) {
session.accept();
};
session.StateChanged += [&](wrtc::PeerSession::State state) {
if (state == wrtc::PeerSession::State::Active)
startRecording();
else if (state == wrtc::PeerSession::State::Ended)
stopRecording();
};The receive path is driven from the receiver emitter:
session->media().videoReceiver().emitter +=
packetSlot(this, &MediaRecorder::onEncodedVideo);Then:
VideoDecoderturns encoded H.264 into decoded framesMultiplexPacketEncoderwrites MP4 output
Why The Sample Still Configures Video Codec
Even though the recorder is receive-only, the session config still declares the codec it is prepared to receive cleanly. The WebRTC layer is now strict about codec setup instead of inventing defaults behind your back.
That is a good thing. It makes negotiation and failure modes honest.
What To Watch For
- Do not assume the first browser packet is decodable.
- Do not open the mux before you know the real decoded frame shape.
- Stop cleanly on
Endedso the file is finalized properly.
Those three rules are why the sample is useful instead of just being a demo that "usually works."
Browser Side
Any browser client that can:
- call the recorder peer over Symple
- offer H.264 video
- complete the normal SDP and ICE flow
can drive this path.
The intended local pairing is with the Symple player stack, but the important part is the protocol shape, not the specific UI.
Good Next Stops
- WebRTC guide for the wider send/receive model
- PacketStream for how the decode and mux stages fit together
media-recorderfor the runnable sample- Run icey-server if you want this receive-and-record flow as part of a single deployed service
