Examples: exchange entire RTCSessionDescription

Resolves #39
This commit is contained in:
backkem
2018-12-08 08:30:32 +01:00
committed by Michiel De Backker
parent 756d74196d
commit 7a527fadb3
21 changed files with 65 additions and 87 deletions

View File

@@ -10,7 +10,7 @@ We've build an extensive collection of examples covering common use-cases. Modif
* [data-channels](data-channels/README.md): Use data channels to send text between Pion WebRTC and your browser
* [data-channels-create](data-channels/README.md): Similar to data channels but now Pion initiates the creation of the data channel.
* [sfu](sfu/README.md): Broadcast a video to many peers, while only requiring the broadcaster to upload once
* [WIP] [pion-to-pion](pion-to-pion/README.md): An example of two Pion instances communicating directly.
* [pion-to-pion](pion-to-pion/README.md): An example of two Pion instances communicating directly.
All examples can be executed on your local machine.

View File

@@ -8,7 +8,7 @@ go get github.com/pions/webrtc/examples/data-channels-create
```
### Open data-channels-create example page
[jsfiddle.net](https://jsfiddle.net/swgxrp94/19/)
[jsfiddle.net](https://jsfiddle.net/swgxrp94/20/)
### Run data-channels-create
Just run run `data-channels-create`.

View File

@@ -15,7 +15,7 @@ pc.onsignalingstatechange = e => log(pc.signalingState)
pc.oniceconnectionstatechange = e => log(pc.iceConnectionState)
pc.onicecandidate = event => {
if (event.candidate === null) {
document.getElementById('localSessionDescription').value = btoa(pc.localDescription.sdp)
document.getElementById('localSessionDescription').value = btoa(JSON.stringify(pc.localDescription))
}
}
@@ -41,6 +41,6 @@ window.startSession = () => {
return alert('Session Description must not be empty')
}
pc.setRemoteDescription(new RTCSessionDescription({type: 'offer', sdp: atob(sd)})).catch(log)
pc.setRemoteDescription(new RTCSessionDescription(JSON.parse(atob(sd)))).catch(log)
pc.createAnswer().then(d => pc.setLocalDescription(d)).catch(log)
}

View File

@@ -39,8 +39,8 @@ func main() {
// Register channel opening handling
dataChannel.OnOpen(func() {
fmt.Printf("Data channel '%s'-'%d' open. Random messages will now be sent to any connected DataChannels every 5 seconds\n", dataChannel.Label, dataChannel.ID)
for {
time.Sleep(5 * time.Second)
for range time.NewTicker(5 * time.Second).C {
message := util.RandSeq(15)
fmt.Printf("Sending %s \n", message)
@@ -66,16 +66,10 @@ func main() {
util.Check(err)
// Output the offer in base64 so we can paste it in browser
fmt.Println(util.Encode(offer.Sdp))
fmt.Println(util.Encode(offer))
// Wait for the answer to be pasted
sd := util.Decode(util.MustReadStdin())
// Set the remote SessionDescription
answer := webrtc.RTCSessionDescription{
Type: webrtc.RTCSdpTypeAnswer,
Sdp: sd,
}
answer := util.Decode(util.MustReadStdin())
// Apply the answer as the remote description
err = peerConnection.SetRemoteDescription(answer)

View File

@@ -8,7 +8,7 @@ go get github.com/pions/webrtc/examples/data-channels
```
### Open data-channels example page
[jsfiddle.net](http://jsfiddle.net/9tsx15mg/35/)
[jsfiddle.net](https://jsfiddle.net/9tsx15mg/90/)
### Run data-channels, with your browsers SessionDescription as stdin
In the jsfiddle the top textarea is your browser's session description, copy that and:

View File

@@ -19,7 +19,7 @@ sendChannel.onmessage = e => log(`Message from DataChannel '${sendChannel.label}
pc.oniceconnectionstatechange = e => log(pc.iceConnectionState)
pc.onicecandidate = event => {
if (event.candidate === null) {
document.getElementById('localSessionDescription').value = btoa(pc.localDescription.sdp)
document.getElementById('localSessionDescription').value = btoa(JSON.stringify(pc.localDescription))
}
}
@@ -42,7 +42,7 @@ window.startSession = () => {
}
try {
pc.setRemoteDescription(new RTCSessionDescription({type: 'answer', sdp: atob(sd)}))
pc.setRemoteDescription(new RTCSessionDescription(JSON.parse(atob(sd))))
} catch (e) {
alert(e)
}

View File

@@ -39,8 +39,8 @@ func main() {
// Register channel opening handling
d.OnOpen(func() {
fmt.Printf("Data channel '%s'-'%d' open. Random messages will now be sent to any connected DataChannels every 5 seconds\n", d.Label, d.ID)
for {
time.Sleep(5 * time.Second)
for range time.NewTicker(5 * time.Second).C {
message := util.RandSeq(15)
fmt.Printf("Sending %s \n", message)
@@ -63,13 +63,9 @@ func main() {
})
// Wait for the offer to be pasted
sd := util.Decode(util.MustReadStdin())
offer := util.Decode(util.MustReadStdin())
// Set the remote SessionDescription
offer := webrtc.RTCSessionDescription{
Type: webrtc.RTCSdpTypeOffer,
Sdp: string(sd),
}
err = peerConnection.SetRemoteDescription(offer)
util.Check(err)
@@ -78,7 +74,7 @@ func main() {
util.Check(err)
// Output the answer in base64 so we can paste it in browser
fmt.Println(util.Encode(answer.Sdp))
fmt.Println(util.Encode(answer))
// Block forever
select {}

View File

@@ -14,7 +14,7 @@ go get github.com/pions/webrtc/examples/gstreamer-receive
```
### Open gstreamer-receive example page
[jsfiddle.net](https://jsfiddle.net/usd3xmtz/45/) you should see your Webcam, two text-areas and a 'Start Session' button
[jsfiddle.net](https://jsfiddle.net/usd3xmtz/109/) you should see your Webcam, two text-areas and a 'Start Session' button
### Run gstreamer-receive with your browsers SessionDescription as stdin
In the jsfiddle the top textarea is your browser, copy that and:

View File

@@ -18,7 +18,7 @@ navigator.mediaDevices.getUserMedia({video: true, audio: true})
pc.oniceconnectionstatechange = e => log(pc.iceConnectionState)
pc.onicecandidate = event => {
if (event.candidate === null) {
document.getElementById('localSessionDescription').value = btoa(pc.localDescription.sdp)
document.getElementById('localSessionDescription').value = btoa(JSON.stringify(pc.localDescription))
}
}
@@ -32,7 +32,7 @@ window.startSession = () => {
}
try {
pc.setRemoteDescription(new RTCSessionDescription({type: 'answer', sdp: atob(sd)}))
pc.setRemoteDescription(new RTCSessionDescription(JSON.parse(atob(sd))))
} catch (e) {
alert(e)
}

View File

@@ -48,13 +48,9 @@ func main() {
})
// Wait for the offer to be pasted
sd := util.Decode(util.MustReadStdin())
offer := util.Decode(util.MustReadStdin())
// Set the remote SessionDescription
offer := webrtc.RTCSessionDescription{
Type: webrtc.RTCSdpTypeOffer,
Sdp: string(sd),
}
err = peerConnection.SetRemoteDescription(offer)
util.Check(err)
@@ -63,7 +59,7 @@ func main() {
util.Check(err)
// Output the answer in base64 so we can paste it in browser
fmt.Println(util.Encode(answer.Sdp))
fmt.Println(util.Encode(answer))
// Block forever
select {}

View File

@@ -52,16 +52,12 @@ func main() {
util.Check(err)
// Output the offer in base64 so we can paste it in browser
fmt.Println(util.Encode(offer.Sdp))
fmt.Println(util.Encode(offer))
// Wait for the answer to be pasted
sd := util.Decode(util.MustReadStdin())
answer := util.Decode(util.MustReadStdin())
// Set the remote SessionDescription
answer := webrtc.RTCSessionDescription{
Type: webrtc.RTCSdpTypeAnswer,
Sdp: sd,
}
err = peerConnection.SetRemoteDescription(answer)
util.Check(err)

View File

@@ -14,7 +14,7 @@ go get github.com/pions/webrtc/examples/gstreamer-send
```
### Open gstreamer-send example page
[jsfiddle.net](https://jsfiddle.net/Laf7ujeo/14/) you should see two text-areas and a 'Start Session' button
[jsfiddle.net](https://jsfiddle.net/Laf7ujeo/164/) you should see two text-areas and a 'Start Session' button
### Run gstreamer-send with your browsers SessionDescription as stdin
In the jsfiddle the top textarea is your browser, copy that and:

View File

@@ -23,7 +23,7 @@ pc.ontrack = function (event) {
pc.oniceconnectionstatechange = e => log(pc.iceConnectionState)
pc.onicecandidate = event => {
if (event.candidate === null) {
document.getElementById('localSessionDescription').value = btoa(pc.localDescription.sdp)
document.getElementById('localSessionDescription').value = btoa(JSON.stringify(pc.localDescription))
}
}
@@ -36,7 +36,7 @@ window.startSession = () => {
}
try {
pc.setRemoteDescription(new RTCSessionDescription({type: 'answer', sdp: atob(sd)}))
pc.setRemoteDescription(new RTCSessionDescription(JSON.parse(atob(sd))))
} catch (e) {
alert(e)
}

View File

@@ -48,13 +48,9 @@ func main() {
util.Check(err)
// Wait for the offer to be pasted
sd := util.Decode(util.MustReadStdin())
offer := util.Decode(util.MustReadStdin())
// Set the remote SessionDescription
offer := webrtc.RTCSessionDescription{
Type: webrtc.RTCSdpTypeOffer,
Sdp: string(sd),
}
err = peerConnection.SetRemoteDescription(offer)
util.Check(err)
@@ -63,7 +59,7 @@ func main() {
util.Check(err)
// Output the answer in base64 so we can paste it in browser
fmt.Println(util.Encode(answer.Sdp))
fmt.Println(util.Encode(answer))
// Start pushing buffers on these tracks
gst.CreatePipeline(webrtc.Opus, opusTrack.Samples).Start()

View File

@@ -8,7 +8,7 @@ go get github.com/pions/webrtc/examples/save-to-disk
```
### Open save-to-disk example page
[jsfiddle.net](https://jsfiddle.net/dyj8qpek/1/) you should see your Webcam, two text-areas and a 'Start Session' button
[jsfiddle.net](https://jsfiddle.net/dyj8qpek/19/) you should see your Webcam, two text-areas and a 'Start Session' button
### Run save-to-disk, with your browsers SessionDescription as stdin
In the jsfiddle the top textarea is your browser, copy that and:

View File

@@ -18,7 +18,7 @@ navigator.mediaDevices.getUserMedia({video: true, audio: true})
pc.oniceconnectionstatechange = e => log(pc.iceConnectionState)
pc.onicecandidate = event => {
if (event.candidate === null) {
document.getElementById('localSessionDescription').value = btoa(pc.localDescription.sdp)
document.getElementById('localSessionDescription').value = btoa(JSON.stringify(pc.localDescription))
}
}
@@ -32,7 +32,7 @@ window.startSession = () => {
}
try {
pc.setRemoteDescription(new RTCSessionDescription({type: 'answer', sdp: atob(sd)}))
pc.setRemoteDescription(new RTCSessionDescription(JSON.parse(atob(sd))))
} catch (e) {
alert(e)
}

View File

@@ -52,13 +52,9 @@ func main() {
})
// Wait for the offer to be pasted
sd := util.Decode(util.MustReadStdin())
offer := util.Decode(util.MustReadStdin())
// Set the remote SessionDescription
offer := webrtc.RTCSessionDescription{
Type: webrtc.RTCSdpTypeOffer,
Sdp: string(sd),
}
err = peerConnection.SetRemoteDescription(offer)
util.Check(err)
@@ -67,7 +63,7 @@ func main() {
util.Check(err)
// Output the answer in base64 so we can paste it in browser
fmt.Println(util.Encode(answer.Sdp))
fmt.Println(util.Encode(answer))
// Block forever
select {}

View File

@@ -10,7 +10,7 @@ go get github.com/pions/webrtc/examples/sfu
```
### Open sfu example page
[jsfiddle.net](https://jsfiddle.net/5cwx0rns/) You should see two buttons 'Publish a Broadcast' and 'Join a Broadcast'
[jsfiddle.net](https://jsfiddle.net/5cwx0rns/11/) You should see two buttons 'Publish a Broadcast' and 'Join a Broadcast'
### Run SFU
#### Linux/macOS

View File

@@ -14,7 +14,7 @@ window.createSession = isPublisher => {
pc.oniceconnectionstatechange = e => log(pc.iceConnectionState)
pc.onicecandidate = event => {
if (event.candidate === null) {
document.getElementById('localSessionDescription').value = btoa(pc.localDescription.sdp)
document.getElementById('localSessionDescription').value = btoa(JSON.stringify(pc.localDescription))
}
}
@@ -47,7 +47,7 @@ window.createSession = isPublisher => {
}
try {
pc.setRemoteDescription(new RTCSessionDescription({type: 'answer', sdp: atob(sd)}))
pc.setRemoteDescription(new RTCSessionDescription(JSON.parse(atob(sd))))
} catch (e) {
alert(e)
}

View File

@@ -10,6 +10,7 @@ import (
"encoding/base64"
"github.com/pions/webrtc"
"github.com/pions/webrtc/examples/util"
"github.com/pions/webrtc/pkg/media"
"github.com/pions/webrtc/pkg/media/samplebuilder"
"github.com/pions/webrtc/pkg/rtcp"
@@ -47,7 +48,7 @@ const (
func main() {
reader := bufio.NewReader(os.Stdin)
sd := mustReadStdin(reader)
offer := util.Decode(mustReadStdin(reader))
fmt.Println("")
/* Everything below is the pion-WebRTC API, thanks for using it! */
@@ -90,22 +91,19 @@ func main() {
})
// Set the remote SessionDescription
check(peerConnection.SetRemoteDescription(webrtc.RTCSessionDescription{
Type: webrtc.RTCSdpTypeOffer,
Sdp: string(sd),
}))
check(peerConnection.SetRemoteDescription(offer))
// Sets the LocalDescription, and starts our UDP listeners
answer, err := peerConnection.CreateAnswer(nil)
check(err)
// Get the LocalDescription and take it to base64 so we can paste in browser
fmt.Println(base64.StdEncoding.EncodeToString([]byte(answer.Sdp)))
fmt.Println(util.Encode(answer))
for {
fmt.Println("")
fmt.Println("Paste an SDP to start sendonly peer connection")
recvOnlyOffer := mustReadStdin(reader)
recvOnlyOffer := util.Decode(mustReadStdin(reader))
// Create a new RTCPeerConnection
peerConnection, err := webrtc.New(peerConnectionConfig)
@@ -123,16 +121,14 @@ func main() {
outboundSamplesLock.Unlock()
// Set the remote SessionDescription
check(peerConnection.SetRemoteDescription(webrtc.RTCSessionDescription{
Type: webrtc.RTCSdpTypeOffer,
Sdp: string(recvOnlyOffer),
}))
err = peerConnection.SetRemoteDescription(recvOnlyOffer)
check(err)
// Sets the LocalDescription, and starts our UDP listeners
answer, err := peerConnection.CreateAnswer(nil)
check(err)
// Get the LocalDescription and take it to base64 so we can paste in browser
fmt.Println(base64.StdEncoding.EncodeToString([]byte(answer.Sdp)))
fmt.Println(util.Encode(answer))
}
}

View File

@@ -5,6 +5,7 @@ import (
"bytes"
"compress/gzip"
"encoding/base64"
"encoding/json"
"fmt"
"io"
"io/ioutil"
@@ -12,6 +13,8 @@ import (
"os"
"strings"
"time"
"github.com/pions/webrtc"
)
// Allows compressing offer/answer to bypass terminal input limits.
@@ -49,27 +52,32 @@ func MustReadStdin() string {
// Encode encodes the input in base64
// It can optionally zip the input before encoding
func Encode(in string) string {
func Encode(sdp webrtc.RTCSessionDescription) string {
b, err := json.Marshal(sdp)
Check(err)
if compress {
in = zip(in)
b = zip(b)
}
return base64.StdEncoding.EncodeToString([]byte(in))
return base64.StdEncoding.EncodeToString(b)
}
// Decode decodes the input from base64
// It can optionally unzip the input after decoding
func Decode(in string) string {
func Decode(in string) webrtc.RTCSessionDescription {
b, err := base64.StdEncoding.DecodeString(in)
Check(err)
out := string(b)
if compress {
out = unzip(out)
b = unzip(b)
}
return out
var sdp webrtc.RTCSessionDescription
err = json.Unmarshal(b, &sdp)
Check(err)
return sdp
}
// RandSeq generates a random string to serve as dummy data
@@ -83,25 +91,25 @@ func RandSeq(n int) string {
return string(b)
}
func zip(in string) string {
func zip(in []byte) []byte {
var b bytes.Buffer
gz := gzip.NewWriter(&b)
_, err := gz.Write([]byte(in))
_, err := gz.Write(in)
Check(err)
err = gz.Flush()
Check(err)
err = gz.Close()
Check(err)
return string(b.Bytes())
return b.Bytes()
}
func unzip(in string) string {
func unzip(in []byte) []byte {
var b bytes.Buffer
_, err := b.Write([]byte(in))
_, err := b.Write(in)
Check(err)
r, err := gzip.NewReader(&b)
Check(err)
res, err := ioutil.ReadAll(r)
Check(err)
return string(res)
return res
}