mirror of
https://github.com/pion/webrtc.git
synced 2025-10-13 02:43:48 +08:00

committed by
Michiel De Backker

parent
756d74196d
commit
7a527fadb3
@@ -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.
|
||||
|
||||
|
@@ -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`.
|
||||
|
@@ -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)
|
||||
}
|
||||
|
@@ -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)
|
||||
|
@@ -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:
|
||||
|
@@ -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)
|
||||
}
|
||||
|
@@ -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 {}
|
||||
|
@@ -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:
|
||||
|
@@ -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)
|
||||
}
|
||||
|
@@ -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 {}
|
||||
|
@@ -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)
|
||||
|
||||
|
@@ -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:
|
||||
|
@@ -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)
|
||||
}
|
||||
|
@@ -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()
|
||||
|
@@ -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:
|
||||
|
@@ -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)
|
||||
}
|
||||
|
@@ -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 {}
|
||||
|
@@ -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
|
||||
|
@@ -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)
|
||||
}
|
||||
|
@@ -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))
|
||||
}
|
||||
}
|
||||
|
@@ -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
|
||||
}
|
||||
|
Reference in New Issue
Block a user