Skip to content

Commit 66a2883

Browse files
committed
Provide easy example of video without browser
Combine `gstreamer-receive` and `gstreamer-send-offer` so people can easily see how to transport audio/video without using their browser. This moves the HTTP endpoint out of `examples/sfu` so it can be used in multiple examples Resolves #472
1 parent d2100fb commit 66a2883

File tree

4 files changed

+89
-45
lines changed

4 files changed

+89
-45
lines changed

gstreamer-send-offer/README.md

Lines changed: 44 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,44 @@
1+
# gstreamer-send-offer
2+
gstreamer-send-offer is a simple application that shows how to send video using pion-WebRTC and GStreamer. This is meant to be used with `gstreamer-receive`, if you want to send via to your browser try `gstreamer-send`
3+
4+
## Instructions
5+
### Install GStreamer
6+
This example requires you have GStreamer installed, these are the supported platforms
7+
#### Debian/Ubuntu
8+
`sudo apt-get install libgstreamer1.0-dev libgstreamer-plugins-base1.0-dev gstreamer1.0-plugins-good`
9+
#### Windows MinGW64/MSYS2
10+
`pacman -S mingw-w64-x86_64-gstreamer mingw-w64-x86_64-gst-libav mingw-w64-x86_64-gst-plugins-good mingw-w64-x86_64-gst-plugins-bad mingw-w64-x86_64-gst-plugins-ugly`
11+
12+
### Run gstreamer-send-offer and make an offer to gstreamer-receive via stdin
13+
```
14+
go run examples/gstreamer-send-offer/*.go | go run examples/gstreamer-receive/*.go
15+
```
16+
17+
### post the answer from gstreamer-receive back to gstreamer-send-offer
18+
You will see a base64 SDP printed to your console. You now need to communicate this back to `gstreamer-send-offer` this can be done via a HTTP endpoint
19+
20+
`curl localhost:8080/sdp -d "BASE_64_SDP"`
21+
22+
### enjoy your video!
23+
A video should start playing via GStreamer and will continue playing until you close the application.
24+
25+
Congrats, you have used pion-WebRTC! Now start building something cool
26+
27+
## Customizing your video or audio
28+
`gstreamer-send-offer` also accepts the command line arguments `-video-src` and `-audio-src` allowing you to provide custom inputs.
29+
30+
When prototyping with GStreamer it is highly recommended that you enable debug output, this is done by setting the `GST_DEBUG` enviroment variable.
31+
You can read about that [here](https://gstreamer.freedesktop.org/data/doc/gstreamer/head/gstreamer/html/gst-running.html) a good default value is `GST_DEBUG=*:3`
32+
33+
You can also prototype a GStreamer pipeline by using `gst-launch-1.0` to see how things look before trying them with `gstreamer-send` for the examples below you
34+
also may need additional setup to enable extra video codecs like H264. The output from GST_DEBUG should give you hints
35+
36+
These pipelines work on Linux, they may have issues on other platforms. We would love PRs for more example pipelines that people find helpful!
37+
38+
* a webcam, with computer generated audio.
39+
40+
`gstreamer-send-offer -video-src "autovideosrc ! video/x-raw, width=320, height=240 ! videoconvert ! queue"`
41+
42+
* a pre-recorded video, sintel.mkv is available [here](https://durian.blender.org/download/)
43+
44+
`gstreamer-send-offer -video-src "uridecodebin uri=file:///tmp/sintel.mkv ! videoscale ! video/x-raw, width=320, height=240 ! queue " -audio-src "uridecodebin uri=file:///tmp/sintel.mkv ! queue ! audioconvert"`

gstreamer-send-offer/main.go

Lines changed: 9 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
package main
22

33
import (
4+
"flag"
45
"fmt"
56
"math/rand"
67

@@ -11,6 +12,10 @@ import (
1112
)
1213

1314
func main() {
15+
audioSrc := flag.String("audio-src", "audiotestsrc", "GStreamer audio src")
16+
videoSrc := flag.String("video-src", "videotestsrc", "GStreamer video src")
17+
sdpChan := signal.HTTPSDPServer()
18+
1419
// Everything below is the pion-WebRTC API! Thanks for using it ❤️.
1520

1621
// Prepare the configuration
@@ -69,9 +74,9 @@ func main() {
6974
// Output the offer in base64 so we can paste it in browser
7075
fmt.Println(signal.Encode(offer))
7176

72-
// Wait for the answer to be pasted
77+
// Wait for the answer to be submitted via HTTP
7378
answer := webrtc.SessionDescription{}
74-
signal.Decode(signal.MustReadStdin(), &answer)
79+
signal.Decode(<-sdpChan, &answer)
7580

7681
// Set the remote SessionDescription
7782
err = peerConnection.SetRemoteDescription(answer)
@@ -80,8 +85,8 @@ func main() {
8085
}
8186

8287
// Start pushing buffers on these tracks
83-
gst.CreatePipeline(webrtc.Opus, opusTrack, "audiotestsrc").Start()
84-
gst.CreatePipeline(webrtc.VP8, vp8Track, "videotestsrc").Start()
88+
gst.CreatePipeline(webrtc.Opus, opusTrack, *audioSrc).Start()
89+
gst.CreatePipeline(webrtc.VP8, vp8Track, *videoSrc).Start()
8590

8691
// Block forever
8792
select {}

internal/signal/http.go

Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,31 @@
1+
package signal
2+
3+
import (
4+
"flag"
5+
"fmt"
6+
"io/ioutil"
7+
"net/http"
8+
"strconv"
9+
)
10+
11+
// HTTPSDPServer starts a HTTP Server that consumes SDPs
12+
func HTTPSDPServer() chan string {
13+
port := flag.Int("port", 8080, "http server port")
14+
flag.Parse()
15+
16+
sdpChan := make(chan string)
17+
http.HandleFunc("/sdp", func(w http.ResponseWriter, r *http.Request) {
18+
body, _ := ioutil.ReadAll(r.Body)
19+
fmt.Fprintf(w, "done")
20+
sdpChan <- string(body)
21+
})
22+
23+
go func() {
24+
err := http.ListenAndServe(":"+strconv.Itoa(*port), nil)
25+
if err != nil {
26+
panic(err)
27+
}
28+
}()
29+
30+
return sdpChan
31+
}

sfu/main.go

Lines changed: 5 additions & 41 deletions
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,7 @@
11
package main
22

33
import (
4-
"bufio"
5-
"flag"
64
"fmt"
7-
"io/ioutil"
8-
"net/http"
9-
"strconv"
105
"time"
116

127
"github.com/pions/rtcp"
@@ -23,26 +18,14 @@ var peerConnectionConfig = webrtc.Configuration{
2318
},
2419
}
2520

26-
func mustReadStdin(reader *bufio.Reader) string {
27-
rawSd, err := reader.ReadString('\n')
28-
if err != nil {
29-
panic(err)
30-
}
31-
fmt.Println("")
32-
33-
return rawSd
34-
}
35-
36-
func mustReadHTTP(sdp chan string) string {
37-
ret := <-sdp
38-
return ret
39-
}
40-
4121
const (
4222
rtcpPLIInterval = time.Second * 3
4323
)
4424

4525
func main() {
26+
sdpChan := signal.HTTPSDPServer()
27+
28+
// Everything below is the pion-WebRTC API, thanks for using it ❤️.
4629
// Create a MediaEngine object to configure the supported codec
4730
m := webrtc.MediaEngine{}
4831

@@ -53,29 +36,10 @@ func main() {
5336
// Create the API object with the MediaEngine
5437
api := webrtc.NewAPI(webrtc.WithMediaEngine(m))
5538

56-
port := flag.Int("port", 8080, "http server port")
57-
flag.Parse()
58-
59-
sdp := make(chan string)
60-
http.HandleFunc("/sdp", func(w http.ResponseWriter, r *http.Request) {
61-
body, _ := ioutil.ReadAll(r.Body)
62-
fmt.Fprintf(w, "done")
63-
sdp <- string(body)
64-
})
65-
66-
go func() {
67-
err := http.ListenAndServe(":"+strconv.Itoa(*port), nil)
68-
if err != nil {
69-
panic(err)
70-
}
71-
}()
72-
7339
offer := webrtc.SessionDescription{}
74-
signal.Decode(mustReadHTTP(sdp), &offer)
40+
signal.Decode(<-sdpChan, &offer)
7541
fmt.Println("")
7642

77-
// Everything below is the pion-WebRTC API, thanks for using it ❤️.
78-
7943
// Create a new RTCPeerConnection
8044
peerConnection, err := api.NewPeerConnection(peerConnectionConfig)
8145
if err != nil {
@@ -144,7 +108,7 @@ func main() {
144108
fmt.Println("Curl an base64 SDP to start sendonly peer connection")
145109

146110
recvOnlyOffer := webrtc.SessionDescription{}
147-
signal.Decode(mustReadHTTP(sdp), &recvOnlyOffer)
111+
signal.Decode(<-sdpChan, &recvOnlyOffer)
148112

149113
// Create a new PeerConnection
150114
peerConnection, err := api.NewPeerConnection(peerConnectionConfig)

0 commit comments

Comments
 (0)