github.com/pion/webrtc/v3@v3.2.24/examples/stats/main.go (about) 1 // SPDX-FileCopyrightText: 2023 The Pion community <https://pion.ly> 2 // SPDX-License-Identifier: MIT 3 4 //go:build !js 5 // +build !js 6 7 // stats demonstrates how to use the webrtc-stats implementation provided by Pion WebRTC. 8 package main 9 10 import ( 11 "fmt" 12 "time" 13 14 "github.com/pion/interceptor" 15 "github.com/pion/interceptor/pkg/stats" 16 "github.com/pion/webrtc/v3" 17 "github.com/pion/webrtc/v3/examples/internal/signal" 18 ) 19 20 // nolint:gocognit 21 func main() { 22 // Everything below is the Pion WebRTC API! Thanks for using it ❤️. 23 24 // Create a MediaEngine object to configure the supported codec 25 m := &webrtc.MediaEngine{} 26 27 if err := m.RegisterDefaultCodecs(); err != nil { 28 panic(err) 29 } 30 31 // Create a InterceptorRegistry. This is the user configurable RTP/RTCP Pipeline. 32 // This provides NACKs, RTCP Reports and other features. If you use `webrtc.NewPeerConnection` 33 // this is enabled by default. If you are manually managing You MUST create a InterceptorRegistry 34 // for each PeerConnection. 35 i := &interceptor.Registry{} 36 37 statsInterceptorFactory, err := stats.NewInterceptor() 38 if err != nil { 39 panic(err) 40 } 41 42 var statsGetter stats.Getter 43 statsInterceptorFactory.OnNewPeerConnection(func(_ string, g stats.Getter) { 44 statsGetter = g 45 }) 46 i.Add(statsInterceptorFactory) 47 48 // Use the default set of Interceptors 49 if err = webrtc.RegisterDefaultInterceptors(m, i); err != nil { 50 panic(err) 51 } 52 53 // Create the API object with the MediaEngine 54 api := webrtc.NewAPI(webrtc.WithMediaEngine(m), webrtc.WithInterceptorRegistry(i)) 55 56 // Prepare the configuration 57 config := webrtc.Configuration{ 58 ICEServers: []webrtc.ICEServer{ 59 { 60 URLs: []string{"stun:stun.l.google.com:19302"}, 61 }, 62 }, 63 } 64 65 // Create a new RTCPeerConnection 66 peerConnection, err := api.NewPeerConnection(config) 67 if err != nil { 68 panic(err) 69 } 70 71 // Allow us to receive 1 audio track, and 1 video track 72 if _, err = peerConnection.AddTransceiverFromKind(webrtc.RTPCodecTypeAudio); err != nil { 73 panic(err) 74 } else if _, err = peerConnection.AddTransceiverFromKind(webrtc.RTPCodecTypeVideo); err != nil { 75 panic(err) 76 } 77 78 // Set a handler for when a new remote track starts. We read the incoming packets, but then 79 // immediately discard them 80 peerConnection.OnTrack(func(track *webrtc.TrackRemote, receiver *webrtc.RTPReceiver) { 81 fmt.Printf("New incoming track with codec: %s\n", track.Codec().MimeType) 82 83 go func() { 84 for { 85 stats := statsGetter.Get(uint32(track.SSRC())) 86 87 fmt.Printf("Stats for: %s\n", track.Codec().MimeType) 88 fmt.Println(stats.InboundRTPStreamStats) 89 90 time.Sleep(time.Second * 5) 91 } 92 }() 93 94 rtpBuff := make([]byte, 1500) 95 for { 96 _, _, readErr := track.Read(rtpBuff) 97 if readErr != nil { 98 panic(readErr) 99 } 100 } 101 }) 102 103 // Set the handler for ICE connection state 104 // This will notify you when the peer has connected/disconnected 105 peerConnection.OnICEConnectionStateChange(func(connectionState webrtc.ICEConnectionState) { 106 fmt.Printf("Connection State has changed %s \n", connectionState.String()) 107 }) 108 109 // Wait for the offer to be pasted 110 offer := webrtc.SessionDescription{} 111 signal.Decode(signal.MustReadStdin(), &offer) 112 113 // Set the remote SessionDescription 114 err = peerConnection.SetRemoteDescription(offer) 115 if err != nil { 116 panic(err) 117 } 118 119 // Create answer 120 answer, err := peerConnection.CreateAnswer(nil) 121 if err != nil { 122 panic(err) 123 } 124 125 // Create channel that is blocked until ICE Gathering is complete 126 gatherComplete := webrtc.GatheringCompletePromise(peerConnection) 127 128 // Sets the LocalDescription, and starts our UDP listeners 129 err = peerConnection.SetLocalDescription(answer) 130 if err != nil { 131 panic(err) 132 } 133 134 // Block until ICE Gathering is complete, disabling trickle ICE 135 // we do this because we only can exchange one signaling message 136 // in a production application you should exchange ICE Candidates via OnICECandidate 137 <-gatherComplete 138 139 // Output the answer in base64 so we can paste it in browser 140 fmt.Println(signal.Encode(*peerConnection.LocalDescription())) 141 142 // Block forever 143 select {} 144 }