-
Notifications
You must be signed in to change notification settings - Fork 1.6k
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Example demonstrates how to use the new webrtc-stats interceptor
- Loading branch information
Showing
4 changed files
with
192 additions
and
3 deletions.
There are no files selected for viewing
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
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,48 @@ | ||
# stats | ||
stats demonstrates how to use the [webrtc-stats](https://www.w3.org/TR/webrtc-stats/) implementation provided by Pion WebRTC. | ||
|
||
This API gives you access to the statistical information about a PeerConnection. This can help you understand what is happening | ||
during a session and why. | ||
|
||
## Instructions | ||
### Download stats | ||
``` | ||
export GO111MODULE=on | ||
go get github.com/pion/webrtc/v3/examples/stats | ||
``` | ||
|
||
### Open stats example page | ||
[jsfiddle.net](https://jsfiddle.net/s179hacu/) you should see your Webcam, two text-areas and two buttons: `Copy browser SDP to clipboard`, `Start Session`. | ||
|
||
### Run stats, with your browsers SessionDescription as stdin | ||
In the jsfiddle the top textarea is your browser's Session Description. Press `Copy browser SDP to clipboard` or copy the base64 string manually. | ||
We will use this value in the next step. | ||
|
||
#### Linux/macOS | ||
Run `echo $BROWSER_SDP | stats` | ||
#### Windows | ||
1. Paste the SessionDescription into a file. | ||
1. Run `stats < my_file` | ||
|
||
### Input stats' SessionDescription into your browser | ||
Copy the text that `stats` just emitted and copy into second text area | ||
|
||
### Hit 'Start Session' in jsfiddle | ||
The `stats` program will now print the InboundRTPStreamStats for each incoming stream. You will see the following in | ||
your console. The exact fields will change as we add more values. | ||
|
||
``` | ||
Stats for: video/VP8 | ||
InboundRTPStreamStats: | ||
PacketsReceived: 1255 | ||
PacketsLost: 0 | ||
Jitter: 588.9559641717999 | ||
LastPacketReceivedTimestamp: 2023-04-26 13:16:16.63591134 -0400 EDT m=+18.317378921 | ||
HeaderBytesReceived: 25100 | ||
BytesReceived: 1361125 | ||
FIRCount: 0 | ||
PLICount: 0 | ||
NACKCount: 0 | ||
``` | ||
|
||
Congrats, you have used Pion WebRTC! Now start building something cool |
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
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,141 @@ | ||
//go:build !js | ||
// +build !js | ||
|
||
// stats demonstrates how to use the webrtc-stats implementation provided by Pion WebRTC. | ||
package main | ||
|
||
import ( | ||
"fmt" | ||
"time" | ||
|
||
"github.com/pion/interceptor" | ||
"github.com/pion/interceptor/pkg/stats" | ||
"github.com/pion/webrtc/v3" | ||
"github.com/pion/webrtc/v3/examples/internal/signal" | ||
) | ||
|
||
// nolint:gocognit | ||
func main() { | ||
// Everything below is the Pion WebRTC API! Thanks for using it ❤️. | ||
|
||
// Create a MediaEngine object to configure the supported codec | ||
m := &webrtc.MediaEngine{} | ||
|
||
if err := m.RegisterDefaultCodecs(); err != nil { | ||
panic(err) | ||
} | ||
|
||
// Create a InterceptorRegistry. This is the user configurable RTP/RTCP Pipeline. | ||
// This provides NACKs, RTCP Reports and other features. If you use `webrtc.NewPeerConnection` | ||
// this is enabled by default. If you are manually managing You MUST create a InterceptorRegistry | ||
// for each PeerConnection. | ||
i := &interceptor.Registry{} | ||
|
||
statsInterceptorFactory, err := stats.NewInterceptor() | ||
if err != nil { | ||
panic(err) | ||
} | ||
|
||
var statsGetter stats.Getter | ||
statsInterceptorFactory.OnNewPeerConnection(func(_ string, g stats.Getter) { | ||
statsGetter = g | ||
}) | ||
i.Add(statsInterceptorFactory) | ||
|
||
// Use the default set of Interceptors | ||
if err = webrtc.RegisterDefaultInterceptors(m, i); err != nil { | ||
panic(err) | ||
} | ||
|
||
// Create the API object with the MediaEngine | ||
api := webrtc.NewAPI(webrtc.WithMediaEngine(m), webrtc.WithInterceptorRegistry(i)) | ||
|
||
// Prepare the configuration | ||
config := webrtc.Configuration{ | ||
ICEServers: []webrtc.ICEServer{ | ||
{ | ||
URLs: []string{"stun:stun.l.google.com:19302"}, | ||
}, | ||
}, | ||
} | ||
|
||
// Create a new RTCPeerConnection | ||
peerConnection, err := api.NewPeerConnection(config) | ||
if err != nil { | ||
panic(err) | ||
} | ||
|
||
// Allow us to receive 1 audio track, and 1 video track | ||
if _, err = peerConnection.AddTransceiverFromKind(webrtc.RTPCodecTypeAudio); err != nil { | ||
panic(err) | ||
} else if _, err = peerConnection.AddTransceiverFromKind(webrtc.RTPCodecTypeVideo); err != nil { | ||
panic(err) | ||
} | ||
|
||
// Set a handler for when a new remote track starts. We read the incoming packets, but then | ||
// immediately discard them | ||
peerConnection.OnTrack(func(track *webrtc.TrackRemote, receiver *webrtc.RTPReceiver) { | ||
fmt.Printf("New incoming track with codec: %s\n", track.Codec().MimeType) | ||
|
||
go func() { | ||
for { | ||
stats := statsGetter.Get(uint32(track.SSRC())) | ||
|
||
fmt.Printf("Stats for: %s\n", track.Codec().MimeType) | ||
fmt.Println(stats.InboundRTPStreamStats) | ||
|
||
time.Sleep(time.Second * 5) | ||
} | ||
}() | ||
|
||
rtpBuff := make([]byte, 1500) | ||
for { | ||
_, _, readErr := track.Read(rtpBuff) | ||
if readErr != nil { | ||
panic(readErr) | ||
} | ||
} | ||
}) | ||
|
||
// Set the handler for ICE connection state | ||
// This will notify you when the peer has connected/disconnected | ||
peerConnection.OnICEConnectionStateChange(func(connectionState webrtc.ICEConnectionState) { | ||
fmt.Printf("Connection State has changed %s \n", connectionState.String()) | ||
}) | ||
|
||
// Wait for the offer to be pasted | ||
offer := webrtc.SessionDescription{} | ||
signal.Decode(signal.MustReadStdin(), &offer) | ||
|
||
// Set the remote SessionDescription | ||
err = peerConnection.SetRemoteDescription(offer) | ||
if err != nil { | ||
panic(err) | ||
} | ||
|
||
// Create answer | ||
answer, err := peerConnection.CreateAnswer(nil) | ||
if err != nil { | ||
panic(err) | ||
} | ||
|
||
// Create channel that is blocked until ICE Gathering is complete | ||
gatherComplete := webrtc.GatheringCompletePromise(peerConnection) | ||
|
||
// Sets the LocalDescription, and starts our UDP listeners | ||
err = peerConnection.SetLocalDescription(answer) | ||
if err != nil { | ||
panic(err) | ||
} | ||
|
||
// Block until ICE Gathering is complete, disabling trickle ICE | ||
// we do this because we only can exchange one signaling message | ||
// in a production application you should exchange ICE Candidates via OnICECandidate | ||
<-gatherComplete | ||
|
||
// Output the answer in base64 so we can paste it in browser | ||
fmt.Println(signal.Encode(*peerConnection.LocalDescription())) | ||
|
||
// Block forever | ||
select {} | ||
} |
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
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