Skip to content

Commit

Permalink
Add examples/stats
Browse files Browse the repository at this point in the history
Example demonstrates how to use the new webrtc-stats interceptor
  • Loading branch information
Sean-Der committed Apr 26, 2023
1 parent 03c83a1 commit 2bf9486
Show file tree
Hide file tree
Showing 4 changed files with 192 additions and 3 deletions.
48 changes: 48 additions & 0 deletions examples/stats/README.md
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
141 changes: 141 additions & 0 deletions examples/stats/main.go
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 {}
}
2 changes: 1 addition & 1 deletion go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ require (
github.com/pion/datachannel v1.5.5
github.com/pion/dtls/v2 v2.2.6
github.com/pion/ice/v2 v2.3.2
github.com/pion/interceptor v0.1.15
github.com/pion/interceptor v0.1.16
github.com/pion/logging v0.2.2
github.com/pion/randutil v0.1.0
github.com/pion/rtcp v1.2.10
Expand Down
4 changes: 2 additions & 2 deletions go.sum
Original file line number Diff line number Diff line change
Expand Up @@ -46,8 +46,8 @@ github.com/pion/dtls/v2 v2.2.6 h1:yXMxKr0Skd+Ub6A8UqXTRLSywskx93ooMRHsQUtd+Z4=
github.com/pion/dtls/v2 v2.2.6/go.mod h1:t8fWJCIquY5rlQZwA2yWxUS1+OCrAdXrhVKXB5oD/wY=
github.com/pion/ice/v2 v2.3.2 h1:vh+fi4RkZ8H5fB4brZ/jm3j4BqFgMmNs+aB3X52Hu7M=
github.com/pion/ice/v2 v2.3.2/go.mod h1:AMIpuJqcpe+UwloocNebmTSWhCZM1TUCo9v7nW50jX0=
github.com/pion/interceptor v0.1.15 h1:vBjnKoSqcNYg2Xq3kz/2m7qp57c0yVH0n/2HJ2rP0hQ=
github.com/pion/interceptor v0.1.15/go.mod h1:SY8kpmfVBvrbUzvj2bsXz7OJt5JvmVNZ+4Kjq7FcwrI=
github.com/pion/interceptor v0.1.16 h1:0GDZrfNO+BmVNWymS31fMlVtPO2IJVBzy2Qq5XCYMIg=
github.com/pion/interceptor v0.1.16/go.mod h1:SY8kpmfVBvrbUzvj2bsXz7OJt5JvmVNZ+4Kjq7FcwrI=
github.com/pion/logging v0.2.2 h1:M9+AIj/+pxNsDfAT64+MAVgJO0rsyLnoJKCqf//DoeY=
github.com/pion/logging v0.2.2/go.mod h1:k0/tDVsRCX2Mb2ZEmTqNa7CWsQPc+YYCB7Q+5pahoms=
github.com/pion/mdns v0.0.7 h1:P0UB4Sr6xDWEox0kTVxF0LmQihtCbSAdW0H2nEgkA3U=
Expand Down

0 comments on commit 2bf9486

Please sign in to comment.