Created
February 24, 2020 01:15
-
-
Save MSamman/821fe0a3ef54246c4e3dcf9e53ad66cd to your computer and use it in GitHub Desktop.
Attempt at one to many multi peer audio streaming
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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))) | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
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.