From becbe45bcdc0f4fe19ce2ef25abdefaced0fc6d2 Mon Sep 17 00:00:00 2001 From: winlin Date: Wed, 5 May 2021 13:26:25 +0800 Subject: [PATCH] SquashSRS4: Add demo for RTC --- README.md | 2 + trunk/3rdparty/copy_to_gits.sh | 22 ++ trunk/3rdparty/httpx-static/README.md | 21 +- trunk/3rdparty/signaling/Dockerfile | 24 ++ trunk/3rdparty/signaling/README.md | 48 +++- trunk/3rdparty/signaling/auto/release.sh | 70 ++++++ trunk/3rdparty/signaling/main.go | 43 +++- trunk/3rdparty/signaling/www/demos/index.html | 16 +- .../signaling/www/demos/js/srs.sdk.js | 6 +- .../signaling/www/demos/js/srs.sig.js | 36 ++- .../3rdparty/signaling/www/demos/one2one.html | 166 ++++++++++++-- trunk/3rdparty/signaling/www/demos/room.html | 212 ++++++++++++++++++ trunk/3rdparty/srs-bench/auto/sync_vnet.sh | 2 +- .../srs-bench/vnet/udpproxy_direct.go | 3 +- .../srs-bench/vnet/udpproxy_direct_test.go | 171 +++++++++++++- trunk/configure | 5 +- trunk/research/console/en_index.html | 2 +- trunk/research/console/ng_index.html | 2 +- trunk/research/players/index.html | 2 +- trunk/research/players/js/srs.sdk.js | 22 +- trunk/research/players/rtc_player.html | 2 +- trunk/research/players/rtc_publisher.html | 2 +- trunk/research/players/srs_bwt.html | 2 +- trunk/research/players/srs_chat.html | 2 +- trunk/research/players/srs_gb28181.html | 2 +- trunk/research/players/srs_player.html | 16 +- .../players/srs_player_deprecated.html | 2 +- trunk/research/players/srs_publisher.html | 2 +- .../research/players/srs_publisher_flash.html | 4 +- trunk/research/players/vlc.html | 2 +- trunk/scripts/git.commit.sh | 2 +- trunk/scripts/package.sh | 2 - trunk/src/app/srs_app_rtc_conn.cpp | 4 + trunk/src/core/srs_core_version4.hpp | 2 +- 34 files changed, 836 insertions(+), 85 deletions(-) create mode 100755 trunk/3rdparty/copy_to_gits.sh create mode 100644 trunk/3rdparty/signaling/Dockerfile create mode 100755 trunk/3rdparty/signaling/auto/release.sh create mode 100644 trunk/3rdparty/signaling/www/demos/room.html diff --git a/README.md b/README.md index 4bc506ea4..36647a90c 100755 --- a/README.md +++ b/README.md @@ -182,6 +182,8 @@ The ports used by SRS: ## V4 changes +* v4.0, 2021-05-04, Add video room demo. 4.0.98 +* v4.0, 2021-05-03, Add RTC stream merging demo by FFmpeg. 4.0.97 * v4.0, 2021-05-02, Add one to one demo. 4.0.96 * v4.0, 2021-04-20, Support RTC2RTMP bridger and shared FastTimer. 4.0.95 * v4.0, 2021-04-20, Refine transcoder to support aac2opus and opus2aac. 4.0.94 diff --git a/trunk/3rdparty/copy_to_gits.sh b/trunk/3rdparty/copy_to_gits.sh new file mode 100755 index 000000000..d92d3a2ba --- /dev/null +++ b/trunk/3rdparty/copy_to_gits.sh @@ -0,0 +1,22 @@ +#!/bin/bash + +if [[ ! -d signaling ]]; then + cd 3rdparty +fi +if [[ ! -d signaling ]]; then + echo "no 3rdparty" + exit -1 +fi +if [[ ! -d ~/git/signaling ]]; then + echo "no signaling" + exit -1 +fi + +echo "Copy signaling" +cp -R signaling/* ~/git/signaling/ && (cd ~/git/signaling && git st) + +echo "Copy httpx-static" +cp -R httpx-static/* ~/git/go-oryx/httpx-static/ && (cd ~/git/go-oryx && git st) + +echo "Copy srs-bench" +cp -R srs-bench/* ~/git/srs-bench/ && (cd ~/git/srs-bench && git st) diff --git a/trunk/3rdparty/httpx-static/README.md b/trunk/3rdparty/httpx-static/README.md index 3b6259475..d82b7b7a6 100644 --- a/trunk/3rdparty/httpx-static/README.md +++ b/trunk/3rdparty/httpx-static/README.md @@ -29,7 +29,7 @@ $GOPATH/bin/httpx-static -https 8443 -root `pwd`/html Open https://localhost:8443/ in browser. -> Remark: Click `ADVANCED` => `Proceed to localhost (unsafe)`. +> Remark: Click `ADVANCED` => `Proceed to localhost (unsafe)`, or type `thisisunsafe` in page. *HTTPS proxy*: Proxy http as https @@ -44,6 +44,25 @@ $GOPATH/bin/httpx-static -https 8443 -root `pwd`/html -proxy http://ossrs.net:19 Open https://localhost:8443/api/v1/summaries in browser. +## Docker + +Run httpx-static in docker: + +```bash +docker run --rm -p 80:80 -p 443:443 registry.cn-hangzhou.aliyuncs.com/ossrs/httpx:v1.0.2 +``` + +> Note: More images and version is [here](https://cr.console.aliyun.com/repository/cn-hangzhou/ossrs/httpx/images). + +To proxy to other dockers, in macOS: + +```bash +CANDIDATE=$(ifconfig en0 inet| grep 'inet '|awk '{print $2}') && +docker run --rm -p 80:80 -p 443:443 registry.cn-hangzhou.aliyuncs.com/ossrs/httpx:v1.0.5 \ + ./bin/httpx-static -http 80 -https 443 -ssk ./etc/server.key -ssc ./etc/server.crt \ + -proxy http://$CANDIDATE:8080/ +``` + ## History * v0.0.3, 2017-11-03, Support multiple proxy HTTP to HTTPS. diff --git a/trunk/3rdparty/signaling/Dockerfile b/trunk/3rdparty/signaling/Dockerfile new file mode 100644 index 000000000..393e57004 --- /dev/null +++ b/trunk/3rdparty/signaling/Dockerfile @@ -0,0 +1,24 @@ + +############################################################ +# build +############################################################ +FROM registry.cn-hangzhou.aliyuncs.com/ossrs/srs:dev AS build + +COPY . /tmp/signaling +RUN cd /tmp/signaling && make +RUN cp /tmp/signaling/objs/signaling /usr/local/bin/signaling +RUN cp -R /tmp/signaling/www /usr/local/ + +############################################################ +# dist +############################################################ +FROM centos:7 AS dist + +# HTTP/1989 +EXPOSE 1989 +# SRS binary, config files and srs-console. +COPY --from=build /usr/local/bin/signaling /usr/local/bin/ +COPY --from=build /usr/local/www /usr/local/www +# Default workdir and command. +WORKDIR /usr/local +CMD ["./bin/signaling"] diff --git a/trunk/3rdparty/signaling/README.md b/trunk/3rdparty/signaling/README.md index d786896a9..f20c724f9 100644 --- a/trunk/3rdparty/signaling/README.md +++ b/trunk/3rdparty/signaling/README.md @@ -4,21 +4,59 @@ WebRTC signaling for https://github.com/ossrs/srs ## Usage -Build and [run SRS](https://github.com/ossrs/srs/tree/4.0release#usage): +[Run SRS](https://github.com/ossrs/srs/tree/4.0release#usage) in docker: ```bash -git clone -b 4.0release https://gitee.com/ossrs/srs.git srs && -cd srs/trunk && ./configure && make && ./objs/srs -c conf/rtc.conf +docker run --rm --env CANDIDATE=$(ifconfig en0 inet| grep 'inet '|awk '{print $2}') \ + -p 1935:1935 -p 8080:8080 -p 1985:1985 -p 8000:8000/udp \ + registry.cn-hangzhou.aliyuncs.com/ossrs/srs:v4.0.95 \ + objs/srs -c conf/rtc.conf ``` -Build and run signaling: +> Note: More images and version is [here](https://cr.console.aliyun.com/repository/cn-hangzhou/ossrs/srs/images). + +Run signaling in docker: ```bash -cd srs/trunk/3rdparty/signaling && make && ./objs/signaling +docker run --rm -p 1989:1989 registry.cn-hangzhou.aliyuncs.com/ossrs/signaling:v1.0.4 ``` +> Note: More images and version is [here](https://cr.console.aliyun.com/repository/cn-hangzhou/ossrs/signaling/images). + Open the H5 demos: * [WebRTC: One to One over SFU(SRS)](http://localhost:1989/demos/one2one.html?autostart=true) +## Build from source + +Build and [run SRS](https://github.com/ossrs/srs/tree/4.0release#usage): + +```bash +cd ~/git && git clone -b 4.0release https://gitee.com/ossrs/srs.git srs && +cd ~/git/srs/trunk && ./configure && make && ./objs/srs -c conf/rtc.conf +``` + +Build and run signaling: + +```bash +cd ~/git/srs/trunk/3rdparty/signaling && make && ./objs/signaling +``` + +Open demos by localhost: http://localhost:1989/demos + +Build and run httpx-static for HTTPS/WSS: + +```bash +cd ~/git/srs/trunk/3rdparty/httpx-static && make && +./objs/httpx-static -http 80 -https 443 -ssk server.key -ssc server.crt \ + -proxy http://127.0.0.1:1989/sig -proxy http://127.0.0.1:1985/rtc \ + -proxy http://127.0.0.1:8080/ +``` + +Open demos by HTTPS or IP: + +* http://localhost/demos/ +* https://localhost/demos/ +* https://192.168.3.6/demos/ + Winlin 2021.05 diff --git a/trunk/3rdparty/signaling/auto/release.sh b/trunk/3rdparty/signaling/auto/release.sh new file mode 100755 index 000000000..c63c9e7b7 --- /dev/null +++ b/trunk/3rdparty/signaling/auto/release.sh @@ -0,0 +1,70 @@ +#!/bin/bash + +SRS_GIT=$HOME/git/signaling +SRS_TAG= + +# linux shell color support. +RED="\\033[31m" +GREEN="\\033[32m" +YELLOW="\\033[33m" +BLACK="\\033[0m" + +function NICE() { + echo -e "${GREEN}$@${BLACK}" +} + +function TRACE() { + echo -e "${BLACK}$@${BLACK}" +} + +function WARN() { + echo -e "${YELLOW}$@${BLACK}" +} + +function ERROR() { + echo -e "${RED}$@${BLACK}" +} + +################################################################################## +################################################################################## +################################################################################## +if [[ -z $SRS_TAG ]]; then + SRS_TAG=`(cd $SRS_GIT && git describe --tags --abbrev=0 --exclude release-* 2>/dev/null)` + if [[ $? -ne 0 ]]; then + echo "Invalid tag $SRS_TAG of $SRS_FILTER in $SRS_GIT" + exit -1 + fi +fi + +NICE "Build docker for $SRS_GIT, tag is $SRS_TAG" + +git ci -am "Release $SRS_TAG" + +# For aliyun hub. +NICE "aliyun hub release-v$SRS_TAG" + +echo "git push aliyun" +git push aliyun + +git tag -d release-v$SRS_TAG 2>/dev/null +echo "Cleanup tag $SRS_TAG for aliyun" + +git tag release-v$SRS_TAG; git push -f aliyun release-v$SRS_TAG +echo "Create new tag $SRS_TAG for aliyun" +echo "" + +NICE "aliyun hub release-vlatest" +git tag -d release-vlatest 2>/dev/null +echo "Cleanup tag latest for aliyun" + +git tag release-vlatest; git push -f aliyun release-vlatest +echo "Create new tag latest for aliyun" + +# For github.com +echo "git push origin" +git push origin + +echo "git push origin $SRS_TAG" +git push origin $SRS_TAG + +NICE "Update github ok" diff --git a/trunk/3rdparty/signaling/main.go b/trunk/3rdparty/signaling/main.go index 3338c08c8..e91ec43fc 100644 --- a/trunk/3rdparty/signaling/main.go +++ b/trunk/3rdparty/signaling/main.go @@ -96,7 +96,7 @@ func (v *Room) Remove(p *Participant) { } } -func (v *Room) Notify(ctx context.Context, peer *Participant, event string) { +func (v *Room) Notify(ctx context.Context, peer *Participant, event, param, data string) { var participants []*Participant func() { v.lock.RLock() @@ -112,12 +112,15 @@ func (v *Room) Notify(ctx context.Context, peer *Participant, event string) { res := struct { Action string `json:"action"` Event string `json:"event"` + Param string `json:"param,omitempty"` + Data string `json:"data,omitempty"` Room string `json:"room"` Self *Participant `json:"self"` Peer *Participant `json:"peer"` Participants []*Participant `json:"participants"` }{ - "notify", event, v.Name, r, peer, participants, + "notify", event, param, data, + v.Name, r, peer, participants, } b, err := json.Marshal(struct { @@ -187,10 +190,16 @@ func main() { var self *Participant go func() { <-ctx.Done() - if self != nil { - self.Room.Remove(self) - logger.Tf(ctx, "Remove client %v", self) + if self == nil { + return } + + // Notify other peers that we're quiting. + // @remark The ctx(of self) is done, so we must use a new context. + go self.Room.Notify(context.Background(), self, "leave", "", "") + + self.Room.Remove(self) + logger.Tf(ctx, "Remove client %v", self) }() inMessages := make(chan []byte, 0) @@ -228,7 +237,6 @@ func main() { } var res interface{} - var p *Participant if action.Message.Action == "join" { obj := struct { Message struct { @@ -241,7 +249,7 @@ func main() { } r, _ := rooms.LoadOrStore(obj.Message.Room, &Room{Name: obj.Message.Room}) - p = &Participant{Room: r.(*Room), Display: obj.Message.Display, Out: outMessages} + p := &Participant{Room: r.(*Room), Display: obj.Message.Display, Out: outMessages} if err := r.(*Room).Add(p); err != nil { return errors.Wrapf(err, "join") } @@ -258,7 +266,7 @@ func main() { action.Message.Action, obj.Message.Room, p, r.(*Room).Participants, } - go r.(*Room).Notify(ctx, p, action.Message.Action) + go r.(*Room).Notify(ctx, p, action.Message.Action, "", "") } else if action.Message.Action == "publish" { obj := struct { Message struct { @@ -276,7 +284,24 @@ func main() { // Now, the peer is publishing. p.Publishing = true - go r.(*Room).Notify(ctx, p, action.Message.Action) + go r.(*Room).Notify(ctx, p, action.Message.Action, "", "") + } else if action.Message.Action == "control" { + obj := struct { + Message struct { + Room string `json:"room"` + Display string `json:"display"` + Call string `json:"call"` + Data string `json:"data"` + } `json:"msg"` + }{} + if err := json.Unmarshal(m, &obj); err != nil { + return errors.Wrapf(err, "Unmarshal %s", m) + } + + r, _ := rooms.LoadOrStore(obj.Message.Room, &Room{Name: obj.Message.Room}) + p := r.(*Room).Get(obj.Message.Display) + + go r.(*Room).Notify(ctx, p, action.Message.Action, obj.Message.Call, obj.Message.Data) } else { return errors.Errorf("Invalid message %s", m) } diff --git a/trunk/3rdparty/signaling/www/demos/index.html b/trunk/3rdparty/signaling/www/demos/index.html index ed3b6e03a..7774d6844 100644 --- a/trunk/3rdparty/signaling/www/demos/index.html +++ b/trunk/3rdparty/signaling/www/demos/index.html @@ -7,7 +7,19 @@

Signaling works!

- Run demo for WebRTC: One to One over SFU(SRS)
- 点击进入SRS一对一通话演示 + Run demo for WebRTC: One to One over SFU(SRS)
+ 点击进入SRS一对一通话演示

+

+ Run demo for WebRTC: Video Room over SFU(SRS)
+ 点击进入SRS多人通话演示 +

+ diff --git a/trunk/3rdparty/signaling/www/demos/js/srs.sdk.js b/trunk/3rdparty/signaling/www/demos/js/srs.sdk.js index f872f7daa..4a80f23f0 100644 --- a/trunk/3rdparty/signaling/www/demos/js/srs.sdk.js +++ b/trunk/3rdparty/signaling/www/demos/js/srs.sdk.js @@ -57,7 +57,7 @@ function SrsRtcPublisherAsync() { self.pc.addTransceiver("video", {direction: "sendonly"}); var stream = await navigator.mediaDevices.getUserMedia( - {audio: true, video: {height: {max: 320}}} + {audio: true, video: {width: {max: 320}}} ); // @see https://developer.mozilla.org/en-US/docs/Web/API/RTCPeerConnection/addStream#Migrating_to_addTrack stream.getTracks().forEach(function (track) { @@ -144,7 +144,7 @@ function SrsRtcPublisherAsync() { return { apiUrl: apiUrl, streamUrl: streamUrl, schema: schema, urlObject: urlObject, port: port, - tid: new Date().getTime().toString(16) + tid: Number(new Date().getTime() + parseInt(String(Math.random() * 10000000000))).toString(16) }; }, parse: function (url) { @@ -361,7 +361,7 @@ function SrsRtcPlayerAsync() { return { apiUrl: apiUrl, streamUrl: streamUrl, schema: schema, urlObject: urlObject, port: port, - tid: new Date().getTime().toString(16) + tid: Number(new Date().getTime() + parseInt(String(Math.random() * 10000000000))).toString(16) }; }, parse: function (url) { diff --git a/trunk/3rdparty/signaling/www/demos/js/srs.sig.js b/trunk/3rdparty/signaling/www/demos/js/srs.sig.js index d78490d99..bae95cc42 100644 --- a/trunk/3rdparty/signaling/www/demos/js/srs.sig.js +++ b/trunk/3rdparty/signaling/www/demos/js/srs.sig.js @@ -59,7 +59,7 @@ function SrsRtcSignalingAsync() { // The message is a json object. self.send = async function (message) { return new Promise(function (resolve, reject) { - var r = {tid: new Date().getTime().toString(16), msg: message}; + var r = {tid: Number(new Date().getTime() + parseInt(String(Math.random() * 10000000000))).toString(16), msg: message}; self._internals.msgs[r.tid] = {resolve: resolve, reject: reject}; self.ws.send(JSON.stringify(r)); }); @@ -100,21 +100,49 @@ function SrsRtcSignalingParse(location) { let wsPort = location.href.split('wsp=')[1]; wsPort = wsPort? wsPort.split('&')[0] : location.host.split(':')[1]; - wsHost = wsPort? wsHost.split(':')[0] + ':' + wsPort : wsHost; let host = location.href.split('host=')[1]; host = host? host.split('&')[0] : location.hostname; let room = location.href.split('room=')[1]; + room = room? room.split('&')[0] : null; let display = location.href.split('display=')[1]; - display = display? display.split('&')[0] : new Date().getTime().toString(16).substr(3); + display = display? display.split('&')[0] : Number(new Date().getTime() + parseInt(String(Math.random() * 10000000000))).toString(16).substr(3); let autostart = location.href.split('autostart=')[1]; autostart = autostart && autostart.split('&')[0] === 'true'; + // Remove data in query. + let rawQuery = query; + if (query) { + query = query.replace('wss=' + wsSchema, ''); + query = query.replace('wsh=' + wsHost, ''); + query = query.replace('wsp=' + wsPort, ''); + query = query.replace('host=' + host, ''); + if (room) { + query = query.replace('room=' + room, ''); + } + query = query.replace('display=' + display, ''); + query = query.replace('autostart=' + autostart, ''); + + while (query.indexOf('&&') >= 0) { + query = query.replace('&&', '&'); + } + query = query.replace('?&', '?'); + if (query.lastIndexOf('?') === query.length - 1) { + query = query.substr(0, query.length - 1); + } + if (query.lastIndexOf('&') === query.length - 1) { + query = query.substr(0, query.length - 1); + } + } + + // Regenerate the host of websocket. + wsHost = wsPort? wsHost.split(':')[0] + ':' + wsPort : wsHost; + return { - query: query, wsSchema: wsSchema, wsHost: wsHost, host: host, + query: query, rawQuery: rawQuery, wsSchema: wsSchema, wsHost: wsHost, host: host, room: room, display: display, autostart: autostart, }; } diff --git a/trunk/3rdparty/signaling/www/demos/one2one.html b/trunk/3rdparty/signaling/www/demos/one2one.html index d6ab19f08..6271e0511 100644 --- a/trunk/3rdparty/signaling/www/demos/one2one.html +++ b/trunk/3rdparty/signaling/www/demos/one2one.html @@ -5,7 +5,7 @@ @@ -15,15 +15,16 @@ - +