mirror of
https://github.com/flavioribeiro/donut.git
synced 2025-10-07 07:50:54 +08:00
add internal demo
This commit is contained in:
8
internal/web/demo/demo.css
Normal file
8
internal/web/demo/demo.css
Normal file
@@ -0,0 +1,8 @@
|
|||||||
|
/*
|
||||||
|
SPDX-FileCopyrightText: 2023 The Pion community <https://pion.ly>
|
||||||
|
SPDX-License-Identifier: MIT
|
||||||
|
*/
|
||||||
|
textarea {
|
||||||
|
width: 500px;
|
||||||
|
min-height: 75px;
|
||||||
|
}
|
67
internal/web/demo/demo.js
Normal file
67
internal/web/demo/demo.js
Normal file
@@ -0,0 +1,67 @@
|
|||||||
|
/* eslint-env browser */
|
||||||
|
|
||||||
|
// SPDX-FileCopyrightText: 2023 The Pion community <https://pion.ly>
|
||||||
|
// SPDX-License-Identifier: MIT
|
||||||
|
|
||||||
|
const pc = new RTCPeerConnection({
|
||||||
|
iceServers: [{
|
||||||
|
urls: 'stun:stun.l.google.com:19302'
|
||||||
|
}]
|
||||||
|
})
|
||||||
|
const log = msg => {
|
||||||
|
document.getElementById('div').innerHTML += msg + '<br>'
|
||||||
|
}
|
||||||
|
|
||||||
|
pc.ontrack = function (event) {
|
||||||
|
const el = document.createElement(event.track.kind)
|
||||||
|
el.srcObject = event.streams[0]
|
||||||
|
el.autoplay = true
|
||||||
|
el.controls = true
|
||||||
|
|
||||||
|
document.getElementById('remoteVideos').appendChild(el)
|
||||||
|
}
|
||||||
|
|
||||||
|
pc.oniceconnectionstatechange = e => log(pc.iceConnectionState)
|
||||||
|
pc.onicecandidate = event => {
|
||||||
|
if (event.candidate === null) {
|
||||||
|
document.getElementById('localSessionDescription').value = btoa(JSON.stringify(pc.localDescription))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Offer to receive 1 audio, and 1 video track
|
||||||
|
pc.addTransceiver('video', {
|
||||||
|
direction: 'sendrecv'
|
||||||
|
})
|
||||||
|
pc.addTransceiver('audio', {
|
||||||
|
direction: 'sendrecv'
|
||||||
|
})
|
||||||
|
|
||||||
|
pc.createOffer().then(d => pc.setLocalDescription(d)).catch(log)
|
||||||
|
|
||||||
|
window.startSession = () => {
|
||||||
|
const sd = document.getElementById('remoteSessionDescription').value
|
||||||
|
if (sd === '') {
|
||||||
|
return alert('Session Description must not be empty')
|
||||||
|
}
|
||||||
|
|
||||||
|
try {
|
||||||
|
pc.setRemoteDescription(JSON.parse(atob(sd)))
|
||||||
|
} catch (e) {
|
||||||
|
alert(e)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
window.copySessionDescription = () => {
|
||||||
|
const browserSessionDescription = document.getElementById('localSessionDescription')
|
||||||
|
|
||||||
|
browserSessionDescription.focus()
|
||||||
|
browserSessionDescription.select()
|
||||||
|
|
||||||
|
try {
|
||||||
|
const successful = document.execCommand('copy')
|
||||||
|
const msg = successful ? 'successful' : 'unsuccessful'
|
||||||
|
log('Copying SessionDescription was ' + msg)
|
||||||
|
} catch (err) {
|
||||||
|
log('Oops, unable to copy SessionDescription ' + err)
|
||||||
|
}
|
||||||
|
}
|
30
internal/web/demo/index.html
Normal file
30
internal/web/demo/index.html
Normal file
@@ -0,0 +1,30 @@
|
|||||||
|
<!--
|
||||||
|
SPDX-FileCopyrightText: 2023 The Pion community <https://pion.ly>
|
||||||
|
SPDX-License-Identifier: MIT
|
||||||
|
-->
|
||||||
|
Browser Session Description
|
||||||
|
<br/>
|
||||||
|
<textarea id="localSessionDescription" readonly="true"></textarea>
|
||||||
|
<br/>
|
||||||
|
|
||||||
|
<button onclick="window.copySessionDescription()">Copy browser Session Description to clipboard</button>
|
||||||
|
|
||||||
|
<br/>
|
||||||
|
<br/>
|
||||||
|
<br/>
|
||||||
|
|
||||||
|
Remote Session Description
|
||||||
|
<br/>
|
||||||
|
<textarea id="remoteSessionDescription"></textarea>
|
||||||
|
<br/>
|
||||||
|
<button onclick="window.startSession()">Start Session</button>
|
||||||
|
<br/>
|
||||||
|
<br/>
|
||||||
|
|
||||||
|
Video
|
||||||
|
<br/>
|
||||||
|
<div id="remoteVideos"></div> <br />
|
||||||
|
|
||||||
|
Logs
|
||||||
|
<br/>
|
||||||
|
<div id="div"></div>
|
1
internal/web/demo/readme.txt
Normal file
1
internal/web/demo/readme.txt
Normal file
@@ -0,0 +1 @@
|
|||||||
|
Initially copied from https://github.com/pion/webrtc/tree/master/examples/play-from-disk/jsfiddle
|
@@ -35,21 +35,31 @@ func NewSignalingHandler(
|
|||||||
|
|
||||||
func (h *SignalingHandler) ServeHTTP(w http.ResponseWriter, r *http.Request) {
|
func (h *SignalingHandler) ServeHTTP(w http.ResponseWriter, r *http.Request) {
|
||||||
if r.Method != http.MethodPost {
|
if r.Method != http.MethodPost {
|
||||||
|
h.l.Sugar().Errorw("unexpected method")
|
||||||
SetError(w, entities.ErrHTTPPostOnly)
|
SetError(w, entities.ErrHTTPPostOnly)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
params := entities.RequestParams{}
|
params := entities.RequestParams{}
|
||||||
if err := json.NewDecoder(r.Body).Decode(¶ms); err != nil {
|
if err := json.NewDecoder(r.Body).Decode(¶ms); err != nil {
|
||||||
|
h.l.Sugar().Errorw("error while decoding request params json",
|
||||||
|
"error", err,
|
||||||
|
)
|
||||||
SetError(w, err)
|
SetError(w, err)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
if err := params.Valid(); err != nil {
|
if err := params.Valid(); err != nil {
|
||||||
|
h.l.Sugar().Errorw("invalid params",
|
||||||
|
"error", err,
|
||||||
|
)
|
||||||
SetError(w, err)
|
SetError(w, err)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
if err := h.webRTCController.SetupPeerConnection(); err != nil {
|
if err := h.webRTCController.SetupPeerConnection(); err != nil {
|
||||||
|
h.l.Sugar().Errorw("error while setting up web rtc connection",
|
||||||
|
"error", err,
|
||||||
|
)
|
||||||
SetError(w, err)
|
SetError(w, err)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
@@ -62,34 +72,52 @@ func (h *SignalingHandler) ServeHTTP(w http.ResponseWriter, r *http.Request) {
|
|||||||
}, "video", params.SRTStreamID,
|
}, "video", params.SRTStreamID,
|
||||||
)
|
)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
h.l.Sugar().Errorw("error while creating a web rtc track",
|
||||||
|
"error", err,
|
||||||
|
)
|
||||||
SetError(w, err)
|
SetError(w, err)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
metadataSender, err := h.webRTCController.CreateDataChannel(entities.MetadataChannelID)
|
metadataSender, err := h.webRTCController.CreateDataChannel(entities.MetadataChannelID)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
h.l.Sugar().Errorw("error while createing a web rtc data channel",
|
||||||
|
"error", err,
|
||||||
|
)
|
||||||
SetError(w, err)
|
SetError(w, err)
|
||||||
}
|
}
|
||||||
|
|
||||||
if err = h.webRTCController.SetRemoteDescription(params.Offer); err != nil {
|
if err = h.webRTCController.SetRemoteDescription(params.Offer); err != nil {
|
||||||
|
h.l.Sugar().Errorw("error while setting a remote web rtc description",
|
||||||
|
"error", err,
|
||||||
|
)
|
||||||
SetError(w, err)
|
SetError(w, err)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
localDescription, err := h.webRTCController.GatheringWebRTC()
|
localDescription, err := h.webRTCController.GatheringWebRTC()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
h.l.Sugar().Errorw("error while preparing a local web rtc description",
|
||||||
|
"error", err,
|
||||||
|
)
|
||||||
SetError(w, err)
|
SetError(w, err)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
localOfferDescription, err := json.Marshal(*localDescription)
|
localOfferDescription, err := json.Marshal(*localDescription)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
h.l.Sugar().Errorw("error while encoding a local web rtc description",
|
||||||
|
"error", err,
|
||||||
|
)
|
||||||
SetError(w, err)
|
SetError(w, err)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
srtConnection, err := h.srtController.Connect(¶ms)
|
srtConnection, err := h.srtController.Connect(¶ms)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
h.l.Sugar().Errorw("error while connecting to an srt server",
|
||||||
|
"error", err,
|
||||||
|
)
|
||||||
SetError(w, err)
|
SetError(w, err)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
@@ -97,6 +125,9 @@ func (h *SignalingHandler) ServeHTTP(w http.ResponseWriter, r *http.Request) {
|
|||||||
go h.streamingController.Stream(srtConnection, videoTrack, metadataSender)
|
go h.streamingController.Stream(srtConnection, videoTrack, metadataSender)
|
||||||
|
|
||||||
if _, err := w.Write(localOfferDescription); err != nil {
|
if _, err := w.Write(localOfferDescription); err != nil {
|
||||||
|
h.l.Sugar().Errorw("error responding the local web rtc offer description",
|
||||||
|
"error", err,
|
||||||
|
)
|
||||||
SetError(w, err)
|
SetError(w, err)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
@@ -15,6 +15,7 @@ func NewServeMux(
|
|||||||
|
|
||||||
mux.Handle("/", index)
|
mux.Handle("/", index)
|
||||||
mux.Handle("/doSignaling", setCors(signaling))
|
mux.Handle("/doSignaling", setCors(signaling))
|
||||||
|
mux.Handle("/demo", http.FileServer(http.Dir("./demo")))
|
||||||
|
|
||||||
return mux
|
return mux
|
||||||
}
|
}
|
||||||
|
@@ -3,5 +3,5 @@ ffmpeg -hide_banner -loglevel verbose \
|
|||||||
-f lavfi -i "sine=frequency=1000:sample_rate=44100" \
|
-f lavfi -i "sine=frequency=1000:sample_rate=44100" \
|
||||||
-c:v libx264 -preset veryfast -tune zerolatency -profile:v baseline \
|
-c:v libx264 -preset veryfast -tune zerolatency -profile:v baseline \
|
||||||
-b:v 1000k -bufsize 2000k -x264opts keyint=30:min-keyint=30:scenecut=-1 \
|
-b:v 1000k -bufsize 2000k -x264opts keyint=30:min-keyint=30:scenecut=-1 \
|
||||||
-f mpegts "srt://${SRT_LISTENING_HOST}:${SRT_LISTENING_PORT}?mode=listener&latency=${SRT_LISTENING_LATENCY_US}"
|
-f mpegts "srt://${SRT_LISTENING_HOST}:${SRT_LISTENING_PORT}?mode=listener&latency=${SRT_LISTENING_LATENCY_US}&smoother=live&transtype=live"
|
||||||
|
|
||||||
|
Reference in New Issue
Block a user