Skip to content

Instantly share code, notes, and snippets.

@MSamman
Created February 24, 2020 01:15
Show Gist options
  • Save MSamman/821fe0a3ef54246c4e3dcf9e53ad66cd to your computer and use it in GitHub Desktop.
Save MSamman/821fe0a3ef54246c4e3dcf9e53ad66cd to your computer and use it in GitHub Desktop.
Attempt at one to many multi peer audio streaming
package main
import (
"fmt"
"io"
"os"
"time"
"io/ioutil"
"net/http"
"github.com/pion/webrtc/v2"
)
const (
rtcpPLIInterval = time.Second * 3
)
var localTracks = []*webrtc.Track{}
var peerConnections = []*webrtc.PeerConnection{}
var sdpChan = HTTPSDPServer()
func main() {
mux := http.NewServeMux()
mux.HandleFunc("/sdp", sdpHandler)
mux.Handle("/", http.FileServer(http.Dir("./jsfiddle")))
s := http.Server{
Addr: fmt.Sprintf(":%s", os.Getenv("PORT")),
Handler: mux,
}
fmt.Println("Starting server...")
// err := s.ListenAndServeTLS("server.crt", "server.key")
err := s.ListenAndServe()
if err != nil {
panic(err)
}
fmt.Println("Stopping server.")
}
func sdpHandler(w http.ResponseWriter, r *http.Request) {
// Everything below is the Pion WebRTC API, thanks for using it ❤️.
// Create a MediaEngine object to configure the supported codec
m := webrtc.MediaEngine{}
// Setup the codecs you want to use.
// Only support VP8, this makes our proxying code simpler
m.RegisterCodec(webrtc.NewRTPOpusCodec(webrtc.DefaultPayloadTypeOpus, 48000))
// Create the API object with the MediaEngine
api := webrtc.NewAPI(webrtc.WithMediaEngine(m))
var peerConnectionConfig = webrtc.Configuration{
ICEServers: []webrtc.ICEServer{
{
URLs: []string{"stun:stun.l.google.com:19302"},
},
},
}
// Create a new PeerConnection
peerConnection, err := api.NewPeerConnection(peerConnectionConfig)
if err != nil {
panic(err)
}
// Track peer connections
peerConnections = append(peerConnections, peerConnection)
offer := webrtc.SessionDescription{}
sdpBytes, err := ioutil.ReadAll(r.Body)
if err != nil {
panic(err)
}
Decode(string(sdpBytes), &offer)
// Allow receiving of one remote audio track
if _, err = peerConnection.AddTransceiverFromKind(webrtc.RTPCodecTypeAudio); err != nil {
panic(err)
}
// All remote audio tracks for other peers should get added to the current peer.
for i, track := range localTracks {
fmt.Printf("Adding track %d to peer connection...\n", i)
_, err = peerConnection.AddTrack(track)
if err != nil {
panic(err)
}
}
// Create a new track for each remot track and add to local track array
peerConnection.OnTrack(func(remoteTrack *webrtc.Track, receiver *webrtc.RTPReceiver) {
// Create a local track, all our SFU clients will be fed via this track
fmt.Println("Creating new local track!")
outputTrack, newTrackErr := peerConnection.NewTrack(remoteTrack.PayloadType(), remoteTrack.SSRC(), remoteTrack.ID(), "pion")
if newTrackErr != nil {
panic(newTrackErr)
}
localTracks = append(localTracks, outputTrack)
rtpBuf := make([]byte, 1400)
for {
i, readErr := remoteTrack.Read(rtpBuf)
if readErr != nil {
panic(readErr)
}
// ErrClosedPipe means we don't have any subscribers, this is ok if no peers have connected yet
if _, err := outputTrack.Write(rtpBuf[:i]); err != nil && err != io.ErrClosedPipe {
panic(err)
}
}
})
// Set remote description
err = peerConnection.SetRemoteDescription(offer)
if err != nil {
panic(err)
}
// Create answer
answer, err := peerConnection.CreateAnswer(nil)
if err != nil {
panic(err)
}
// Sets the LocalDescription, and starts our UDP listeners
err = peerConnection.SetLocalDescription(answer)
if err != nil {
panic(err)
}
// Get the LocalDescription and take it to base64 so we can paste in browser
w.Write([]byte(Encode(answer)))
}
@MSamman
Copy link
Author

MSamman commented Feb 24, 2020

Behavior I am trying to create:

As peers hit the SDP handler, they register their audio tracks to be sent to all other connected peers. They also register themselves to receive the audio tracks of all previously registered peers. Each audio track received by this server creates a new track on all connected peers.

What happens:

The first peer to connect will have their audio broadcast to all subsequently connected peer. All following peers do not have their audio forwarded to other peers. Only one 'ontrack' event is ever fired on connected peers.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment