For a project I’ve been using Pion WebRTC which is a Golang implementation of the WebRTC API.
It is easy to set up and provides great performance.
Some tips when using Pion WebRTC, or WebRTC in general:
- Use multiple TURN/STUN servers. I’ve been using coturn and Twilio’s WebRTC servers.
- Use Trickle ICE to speed up the initial connection
- When using h264, use the h264reader to send NALs
Streaming with Pion WebRTC
Once you’ve done all the peer/ICE handling, you can send video/audio. Below is the piece of code I’ve been using to send a h264 stream through WebRTC:
<-iceConnectedCtx.Done()
h264FrameDuration := time.Millisecond * 33
ticker := time.NewTicker(h264FrameDuration)
for ; true; <-ticker.C {
nal, h264Err := h264.NextNAL()
if h264Err == io.EOF {
fmt.Printf("All video frames parsed and sent")
}
if h264Err != nil {
panic(h264Err)
}
if h264Err = videoTrack.WriteSample(media.Sample{Data: nal.Data, Duration: time.Second}); h264Err != nil {
panic(h264Err)
}
}
Similar for audio, you can send incoming Opus packets like this:
audioTrack, audioTrackErr := webrtc.NewTrackLocalStaticSample(webrtc.RTPCodecCapability{MimeType: webrtc.MimeTypeOpus}, "audio", "pion")
p := make([]byte, 960)
for {
n, err := audioReader.Read(p)
if err == io.EOF {
break
}
if audioTrackErr = audioTrack.WriteSample(media.Sample{Data: p[:n], Duration: time.Millisecond * 20}); audioTrackErr != nil {
panic(audioTrackErr)
}
}
Signaling and WebRTC
A great way to do signaling is through Websockets. I can highly recommend using Gorilla WebSocket which provides a clean API to handle Websockets with Go.
Upon receiving an ICE candidate through a Websocket message, you can pass the candidate to Pion through a Go channel. The answer can be sent back, by sending a Websocket message back to the sender.