mirror of
https://github.com/pion/webrtc.git
synced 2025-10-04 23:02:48 +08:00
Use new intervalpli interceptor in examples
Instead of manually spawning a goroutine this demonstrates how an interceptor can be useful. Co-authored-by: Antoine Baché <antoine@tenten.app>
This commit is contained in:
@@ -8,17 +8,13 @@ import (
|
|||||||
"errors"
|
"errors"
|
||||||
"fmt"
|
"fmt"
|
||||||
"io"
|
"io"
|
||||||
"time"
|
|
||||||
|
|
||||||
"github.com/pion/rtcp"
|
"github.com/pion/interceptor"
|
||||||
|
"github.com/pion/interceptor/pkg/intervalpli"
|
||||||
"github.com/pion/webrtc/v3"
|
"github.com/pion/webrtc/v3"
|
||||||
"github.com/pion/webrtc/v3/examples/internal/signal"
|
"github.com/pion/webrtc/v3/examples/internal/signal"
|
||||||
)
|
)
|
||||||
|
|
||||||
const (
|
|
||||||
rtcpPLIInterval = time.Second * 3
|
|
||||||
)
|
|
||||||
|
|
||||||
func main() { // nolint:gocognit
|
func main() { // nolint:gocognit
|
||||||
sdpChan := signal.HTTPSDPServer()
|
sdpChan := signal.HTTPSDPServer()
|
||||||
|
|
||||||
@@ -35,8 +31,34 @@ func main() { // nolint:gocognit
|
|||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
|
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{}
|
||||||
|
|
||||||
|
// Use the default set of Interceptors
|
||||||
|
if err := webrtc.RegisterDefaultInterceptors(m, i); err != nil {
|
||||||
|
panic(err)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Register a intervalpli factory
|
||||||
|
// This interceptor sends a PLI every 3 seconds. A PLI causes a video keyframe to be generated by the sender.
|
||||||
|
// This makes our video seekable and more error resilent, but at a cost of lower picture quality and higher bitrates
|
||||||
|
// A real world application should process incoming RTCP packets from viewers and forward them to senders
|
||||||
|
intervalPliFactory, err := intervalpli.NewReceiverInterceptor()
|
||||||
|
if err != nil {
|
||||||
|
panic(err)
|
||||||
|
}
|
||||||
|
i.Add(intervalPliFactory)
|
||||||
|
|
||||||
// Create a new RTCPeerConnection
|
// Create a new RTCPeerConnection
|
||||||
peerConnection, err := webrtc.NewPeerConnection(peerConnectionConfig)
|
peerConnection, err := webrtc.NewAPI(webrtc.WithMediaEngine(m), webrtc.WithInterceptorRegistry(i)).NewPeerConnection(peerConnectionConfig)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
panic(err)
|
panic(err)
|
||||||
}
|
}
|
||||||
@@ -55,17 +77,6 @@ func main() { // nolint:gocognit
|
|||||||
// Set a handler for when a new remote track starts, this just distributes all our packets
|
// Set a handler for when a new remote track starts, this just distributes all our packets
|
||||||
// to connected peers
|
// to connected peers
|
||||||
peerConnection.OnTrack(func(remoteTrack *webrtc.TrackRemote, receiver *webrtc.RTPReceiver) {
|
peerConnection.OnTrack(func(remoteTrack *webrtc.TrackRemote, receiver *webrtc.RTPReceiver) {
|
||||||
// Send a PLI on an interval so that the publisher is pushing a keyframe every rtcpPLIInterval
|
|
||||||
// This can be less wasteful by processing incoming RTCP events, then we would emit a NACK/PLI when a viewer requests it
|
|
||||||
go func() {
|
|
||||||
ticker := time.NewTicker(rtcpPLIInterval)
|
|
||||||
for range ticker.C {
|
|
||||||
if rtcpSendErr := peerConnection.WriteRTCP([]rtcp.Packet{&rtcp.PictureLossIndication{MediaSSRC: uint32(remoteTrack.SSRC())}}); rtcpSendErr != nil {
|
|
||||||
fmt.Println(rtcpSendErr)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}()
|
|
||||||
|
|
||||||
// Create a local track, all our SFU clients will be fed via this track
|
// Create a local track, all our SFU clients will be fed via this track
|
||||||
localTrack, newTrackErr := webrtc.NewTrackLocalStaticRTP(remoteTrack.Codec().RTPCodecCapability, "video", "pion")
|
localTrack, newTrackErr := webrtc.NewTrackLocalStaticRTP(remoteTrack.Codec().RTPCodecCapability, "video", "pion")
|
||||||
if newTrackErr != nil {
|
if newTrackErr != nil {
|
||||||
|
@@ -7,10 +7,9 @@ package main
|
|||||||
import (
|
import (
|
||||||
"fmt"
|
"fmt"
|
||||||
"os"
|
"os"
|
||||||
"time"
|
|
||||||
|
|
||||||
"github.com/pion/interceptor"
|
"github.com/pion/interceptor"
|
||||||
"github.com/pion/rtcp"
|
"github.com/pion/interceptor/pkg/intervalpli"
|
||||||
"github.com/pion/webrtc/v3"
|
"github.com/pion/webrtc/v3"
|
||||||
"github.com/pion/webrtc/v3/examples/internal/signal"
|
"github.com/pion/webrtc/v3/examples/internal/signal"
|
||||||
)
|
)
|
||||||
@@ -42,6 +41,16 @@ func main() {
|
|||||||
panic(err)
|
panic(err)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Register a intervalpli factory
|
||||||
|
// This interceptor sends a PLI every 3 seconds. A PLI causes a video keyframe to be generated by the sender.
|
||||||
|
// This makes our video seekable and more error resilent, but at a cost of lower picture quality and higher bitrates
|
||||||
|
// A real world application should process incoming RTCP packets from viewers and forward them to senders
|
||||||
|
intervalPliFactory, err := intervalpli.NewReceiverInterceptor()
|
||||||
|
if err != nil {
|
||||||
|
panic(err)
|
||||||
|
}
|
||||||
|
i.Add(intervalPliFactory)
|
||||||
|
|
||||||
// Create the API object with the MediaEngine
|
// Create the API object with the MediaEngine
|
||||||
api := webrtc.NewAPI(webrtc.WithMediaEngine(m), webrtc.WithInterceptorRegistry(i))
|
api := webrtc.NewAPI(webrtc.WithMediaEngine(m), webrtc.WithInterceptorRegistry(i))
|
||||||
|
|
||||||
@@ -101,18 +110,6 @@ func main() {
|
|||||||
// Set a handler for when a new remote track starts, this handler copies inbound RTP packets,
|
// Set a handler for when a new remote track starts, this handler copies inbound RTP packets,
|
||||||
// replaces the SSRC and sends them back
|
// replaces the SSRC and sends them back
|
||||||
peerConnection.OnTrack(func(track *webrtc.TrackRemote, receiver *webrtc.RTPReceiver) {
|
peerConnection.OnTrack(func(track *webrtc.TrackRemote, receiver *webrtc.RTPReceiver) {
|
||||||
// Send a PLI on an interval so that the publisher is pushing a keyframe every rtcpPLIInterval
|
|
||||||
// This is a temporary fix until we implement incoming RTCP events, then we would push a PLI only when a viewer requests it
|
|
||||||
go func() {
|
|
||||||
ticker := time.NewTicker(time.Second * 3)
|
|
||||||
for range ticker.C {
|
|
||||||
errSend := peerConnection.WriteRTCP([]rtcp.Packet{&rtcp.PictureLossIndication{MediaSSRC: uint32(track.SSRC())}})
|
|
||||||
if errSend != nil {
|
|
||||||
fmt.Println(errSend)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}()
|
|
||||||
|
|
||||||
fmt.Printf("Track has started, of type %d: %s \n", track.PayloadType(), track.Codec().MimeType)
|
fmt.Printf("Track has started, of type %d: %s \n", track.PayloadType(), track.Codec().MimeType)
|
||||||
for {
|
for {
|
||||||
// Read RTP packets being sent to Pion
|
// Read RTP packets being sent to Pion
|
||||||
|
@@ -9,10 +9,9 @@ import (
|
|||||||
"fmt"
|
"fmt"
|
||||||
"net"
|
"net"
|
||||||
"os"
|
"os"
|
||||||
"time"
|
|
||||||
|
|
||||||
"github.com/pion/interceptor"
|
"github.com/pion/interceptor"
|
||||||
"github.com/pion/rtcp"
|
"github.com/pion/interceptor/pkg/intervalpli"
|
||||||
"github.com/pion/rtp"
|
"github.com/pion/rtp"
|
||||||
"github.com/pion/webrtc/v3"
|
"github.com/pion/webrtc/v3"
|
||||||
"github.com/pion/webrtc/v3/examples/internal/signal"
|
"github.com/pion/webrtc/v3/examples/internal/signal"
|
||||||
@@ -50,8 +49,18 @@ func main() {
|
|||||||
// for each PeerConnection.
|
// for each PeerConnection.
|
||||||
i := &interceptor.Registry{}
|
i := &interceptor.Registry{}
|
||||||
|
|
||||||
|
// Register a intervalpli factory
|
||||||
|
// This interceptor sends a PLI every 3 seconds. A PLI causes a video keyframe to be generated by the sender.
|
||||||
|
// This makes our video seekable and more error resilent, but at a cost of lower picture quality and higher bitrates
|
||||||
|
// A real world application should process incoming RTCP packets from viewers and forward them to senders
|
||||||
|
intervalPliFactory, err := intervalpli.NewReceiverInterceptor()
|
||||||
|
if err != nil {
|
||||||
|
panic(err)
|
||||||
|
}
|
||||||
|
i.Add(intervalPliFactory)
|
||||||
|
|
||||||
// Use the default set of Interceptors
|
// Use the default set of Interceptors
|
||||||
if err := webrtc.RegisterDefaultInterceptors(m, i); err != nil {
|
if err = webrtc.RegisterDefaultInterceptors(m, i); err != nil {
|
||||||
panic(err)
|
panic(err)
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -126,16 +135,6 @@ func main() {
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
// Send a PLI on an interval so that the publisher is pushing a keyframe every rtcpPLIInterval
|
|
||||||
go func() {
|
|
||||||
ticker := time.NewTicker(time.Second * 2)
|
|
||||||
for range ticker.C {
|
|
||||||
if rtcpErr := peerConnection.WriteRTCP([]rtcp.Packet{&rtcp.PictureLossIndication{MediaSSRC: uint32(track.SSRC())}}); rtcpErr != nil {
|
|
||||||
fmt.Println(rtcpErr)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}()
|
|
||||||
|
|
||||||
b := make([]byte, 1500)
|
b := make([]byte, 1500)
|
||||||
rtpPacket := &rtp.Packet{}
|
rtpPacket := &rtp.Packet{}
|
||||||
for {
|
for {
|
||||||
|
@@ -8,10 +8,9 @@ import (
|
|||||||
"fmt"
|
"fmt"
|
||||||
"os"
|
"os"
|
||||||
"strings"
|
"strings"
|
||||||
"time"
|
|
||||||
|
|
||||||
"github.com/pion/interceptor"
|
"github.com/pion/interceptor"
|
||||||
"github.com/pion/rtcp"
|
"github.com/pion/interceptor/pkg/intervalpli"
|
||||||
"github.com/pion/webrtc/v3"
|
"github.com/pion/webrtc/v3"
|
||||||
"github.com/pion/webrtc/v3/examples/internal/signal"
|
"github.com/pion/webrtc/v3/examples/internal/signal"
|
||||||
"github.com/pion/webrtc/v3/pkg/media"
|
"github.com/pion/webrtc/v3/pkg/media"
|
||||||
@@ -57,8 +56,18 @@ func main() {
|
|||||||
// for each PeerConnection.
|
// for each PeerConnection.
|
||||||
i := &interceptor.Registry{}
|
i := &interceptor.Registry{}
|
||||||
|
|
||||||
|
// Register a intervalpli factory
|
||||||
|
// This interceptor sends a PLI every 3 seconds. A PLI causes a video keyframe to be generated by the sender.
|
||||||
|
// This makes our video seekable and more error resilent, but at a cost of lower picture quality and higher bitrates
|
||||||
|
// A real world application should process incoming RTCP packets from viewers and forward them to senders
|
||||||
|
intervalPliFactory, err := intervalpli.NewReceiverInterceptor()
|
||||||
|
if err != nil {
|
||||||
|
panic(err)
|
||||||
|
}
|
||||||
|
i.Add(intervalPliFactory)
|
||||||
|
|
||||||
// Use the default set of Interceptors
|
// Use the default set of Interceptors
|
||||||
if err := webrtc.RegisterDefaultInterceptors(m, i); err != nil {
|
if err = webrtc.RegisterDefaultInterceptors(m, i); err != nil {
|
||||||
panic(err)
|
panic(err)
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -88,17 +97,6 @@ func main() {
|
|||||||
// an ivf file, since we could have multiple video tracks we provide a counter.
|
// an ivf file, since we could have multiple video tracks we provide a counter.
|
||||||
// In your application this is where you would handle/process video
|
// In your application this is where you would handle/process video
|
||||||
peerConnection.OnTrack(func(track *webrtc.TrackRemote, receiver *webrtc.RTPReceiver) {
|
peerConnection.OnTrack(func(track *webrtc.TrackRemote, receiver *webrtc.RTPReceiver) {
|
||||||
// Send a PLI on an interval so that the publisher is pushing a keyframe every rtcpPLIInterval
|
|
||||||
go func() {
|
|
||||||
ticker := time.NewTicker(time.Second * 3)
|
|
||||||
for range ticker.C {
|
|
||||||
errSend := peerConnection.WriteRTCP([]rtcp.Packet{&rtcp.PictureLossIndication{MediaSSRC: uint32(track.SSRC())}})
|
|
||||||
if errSend != nil {
|
|
||||||
fmt.Println(errSend)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}()
|
|
||||||
|
|
||||||
if strings.EqualFold(track.Codec().MimeType, webrtc.MimeTypeAV1) {
|
if strings.EqualFold(track.Codec().MimeType, webrtc.MimeTypeAV1) {
|
||||||
fmt.Println("Got AV1 track, saving to disk as output.ivf")
|
fmt.Println("Got AV1 track, saving to disk as output.ivf")
|
||||||
saveToDisk(ivfFile, track)
|
saveToDisk(ivfFile, track)
|
||||||
|
@@ -8,10 +8,9 @@ import (
|
|||||||
"fmt"
|
"fmt"
|
||||||
"os"
|
"os"
|
||||||
"strings"
|
"strings"
|
||||||
"time"
|
|
||||||
|
|
||||||
"github.com/pion/interceptor"
|
"github.com/pion/interceptor"
|
||||||
"github.com/pion/rtcp"
|
"github.com/pion/interceptor/pkg/intervalpli"
|
||||||
"github.com/pion/webrtc/v3"
|
"github.com/pion/webrtc/v3"
|
||||||
"github.com/pion/webrtc/v3/examples/internal/signal"
|
"github.com/pion/webrtc/v3/examples/internal/signal"
|
||||||
"github.com/pion/webrtc/v3/pkg/media"
|
"github.com/pion/webrtc/v3/pkg/media"
|
||||||
@@ -65,8 +64,18 @@ func main() {
|
|||||||
// for each PeerConnection.
|
// for each PeerConnection.
|
||||||
i := &interceptor.Registry{}
|
i := &interceptor.Registry{}
|
||||||
|
|
||||||
|
// Register a intervalpli factory
|
||||||
|
// This interceptor sends a PLI every 3 seconds. A PLI causes a video keyframe to be generated by the sender.
|
||||||
|
// This makes our video seekable and more error resilent, but at a cost of lower picture quality and higher bitrates
|
||||||
|
// A real world application should process incoming RTCP packets from viewers and forward them to senders
|
||||||
|
intervalPliFactory, err := intervalpli.NewReceiverInterceptor()
|
||||||
|
if err != nil {
|
||||||
|
panic(err)
|
||||||
|
}
|
||||||
|
i.Add(intervalPliFactory)
|
||||||
|
|
||||||
// Use the default set of Interceptors
|
// Use the default set of Interceptors
|
||||||
if err := webrtc.RegisterDefaultInterceptors(m, i); err != nil {
|
if err = webrtc.RegisterDefaultInterceptors(m, i); err != nil {
|
||||||
panic(err)
|
panic(err)
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -108,17 +117,6 @@ func main() {
|
|||||||
// an ivf file, since we could have multiple video tracks we provide a counter.
|
// an ivf file, since we could have multiple video tracks we provide a counter.
|
||||||
// In your application this is where you would handle/process video
|
// In your application this is where you would handle/process video
|
||||||
peerConnection.OnTrack(func(track *webrtc.TrackRemote, receiver *webrtc.RTPReceiver) {
|
peerConnection.OnTrack(func(track *webrtc.TrackRemote, receiver *webrtc.RTPReceiver) {
|
||||||
// Send a PLI on an interval so that the publisher is pushing a keyframe every rtcpPLIInterval
|
|
||||||
go func() {
|
|
||||||
ticker := time.NewTicker(time.Second * 3)
|
|
||||||
for range ticker.C {
|
|
||||||
errSend := peerConnection.WriteRTCP([]rtcp.Packet{&rtcp.PictureLossIndication{MediaSSRC: uint32(track.SSRC())}})
|
|
||||||
if errSend != nil {
|
|
||||||
fmt.Println(errSend)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}()
|
|
||||||
|
|
||||||
codec := track.Codec()
|
codec := track.Codec()
|
||||||
if strings.EqualFold(codec.MimeType, webrtc.MimeTypeOpus) {
|
if strings.EqualFold(codec.MimeType, webrtc.MimeTypeOpus) {
|
||||||
fmt.Println("Got Opus track, saving to disk as output.opus (48 kHz, 2 channels)")
|
fmt.Println("Got Opus track, saving to disk as output.opus (48 kHz, 2 channels)")
|
||||||
|
2
go.mod
2
go.mod
@@ -8,7 +8,7 @@ require (
|
|||||||
github.com/pion/datachannel v1.5.5
|
github.com/pion/datachannel v1.5.5
|
||||||
github.com/pion/dtls/v2 v2.2.6
|
github.com/pion/dtls/v2 v2.2.6
|
||||||
github.com/pion/ice/v2 v2.3.2
|
github.com/pion/ice/v2 v2.3.2
|
||||||
github.com/pion/interceptor v0.1.14
|
github.com/pion/interceptor v0.1.15
|
||||||
github.com/pion/logging v0.2.2
|
github.com/pion/logging v0.2.2
|
||||||
github.com/pion/randutil v0.1.0
|
github.com/pion/randutil v0.1.0
|
||||||
github.com/pion/rtcp v1.2.10
|
github.com/pion/rtcp v1.2.10
|
||||||
|
4
go.sum
4
go.sum
@@ -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/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 h1:vh+fi4RkZ8H5fB4brZ/jm3j4BqFgMmNs+aB3X52Hu7M=
|
||||||
github.com/pion/ice/v2 v2.3.2/go.mod h1:AMIpuJqcpe+UwloocNebmTSWhCZM1TUCo9v7nW50jX0=
|
github.com/pion/ice/v2 v2.3.2/go.mod h1:AMIpuJqcpe+UwloocNebmTSWhCZM1TUCo9v7nW50jX0=
|
||||||
github.com/pion/interceptor v0.1.14 h1:066aWutplETQ6I/jxMwECPgAkP9nQC1IsqVqu9KlFtg=
|
github.com/pion/interceptor v0.1.15 h1:vBjnKoSqcNYg2Xq3kz/2m7qp57c0yVH0n/2HJ2rP0hQ=
|
||||||
github.com/pion/interceptor v0.1.14/go.mod h1:SY8kpmfVBvrbUzvj2bsXz7OJt5JvmVNZ+4Kjq7FcwrI=
|
github.com/pion/interceptor v0.1.15/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 h1:M9+AIj/+pxNsDfAT64+MAVgJO0rsyLnoJKCqf//DoeY=
|
||||||
github.com/pion/logging v0.2.2/go.mod h1:k0/tDVsRCX2Mb2ZEmTqNa7CWsQPc+YYCB7Q+5pahoms=
|
github.com/pion/logging v0.2.2/go.mod h1:k0/tDVsRCX2Mb2ZEmTqNa7CWsQPc+YYCB7Q+5pahoms=
|
||||||
github.com/pion/mdns v0.0.7 h1:P0UB4Sr6xDWEox0kTVxF0LmQihtCbSAdW0H2nEgkA3U=
|
github.com/pion/mdns v0.0.7 h1:P0UB4Sr6xDWEox0kTVxF0LmQihtCbSAdW0H2nEgkA3U=
|
||||||
|
Reference in New Issue
Block a user