Bladeren bron

feat(core): update

gemercheung 3 jaren geleden
bovenliggende
commit
9f15d0233f
10 gewijzigde bestanden met toevoegingen van 850 en 160 verwijderingen
  1. 15 134
      index.html
  2. 6 0
      libs/jquery-1.10.2.min.js
  3. 1 1
      live.sh
  4. 1 0
      webrtc/adapter-7.4.0.min.js
  5. 59 0
      webrtc/connection copy.js
  6. 5 25
      webrtc/connection.js
  7. 47 0
      webrtc/srs.js
  8. 543 0
      webrtc/srs.sdk.js
  9. 60 0
      webrtc/srsRtc.js
  10. 113 0
      webrtc/trtcInit.js

+ 15 - 134
index.html

@@ -27,21 +27,19 @@
       </style>
     </head>
     <body>
+      <video id="testVideoFeed" crossorigin="anonymous" playsinline autoplay muted  style="
+      position: fixed;
+      width: 600px;
+      height: 600px;
+      z-index: 10000;
+      top: 0;
+      left: 0;
+    "></video>
       <canvas id="renderCanvas"></canvas>
 
-      <div
-        id="testVideoFeed"
-        style="
-          position: fixed;
-          width: 300px;
-          height: 300px;
-          z-index: 10000;
-          top: 0;
-          left: 0;
-        "
-      >
-        <video crossorigin="anonymous" playsinline autoplay muted></video>
-      </div>
+     
+     
+
       <div id="videoTextureBox">
         <video
           id="houseTexture0"
@@ -55,6 +53,7 @@
       </div>
 
       <!-- Babylon.js -->
+      <script  src="./libs/jquery-1.10.2.min.js"></script>
       <script src="./libs/dat.gui.min.js"></script>
       <script src="./libs/ammo.js"></script>
       <script src="./libs/cannon.js"></script>
@@ -71,7 +70,8 @@
       <script src="./libs/babylon.gui.min.js"></script>
       <script src="./libs/babylon.inspector.bundle.js"></script>
       <script src="./libs/socket.2.3.js"></script>
-
+      <script src="./webrtc//adapter-7.4.0.min.js"></script>
+      <script src="./webrtc/srs.sdk.js"></script>
       <script type="module">
         import App from "./modules/index.js";
 
@@ -136,127 +136,8 @@
       <!-- worker -->
       <!-- <script src="./worker/decoderWorker.js"></script> -->
       <script src="./worker/index.js" type="module"></script>
-      <script type="module">
-        import { Connection } from "./webrtc/connection.js";
-        import { uuid } from "./webrtc/uuid.js";
-        document.addEventListener("DOMContentLoaded", async () => {
-          const connection = new Connection();
-          window.connection = connection;
-          const testConfig = {
-            userId: uuid(16, 16),
-            roomId: "22s1111ss",
-            sdkAppId: 1400653314,
-            sceneCode: "2111",
-          };
-          console.log("testConfig", testConfig);
-          connection.init(testConfig, async () => {
-            if (connection.client) {
-              await connection.client.join({ roomId: testConfig.roomId });
-              console.log("userSig", connection.userSig);
-
-              //   connection.socket.on("init-scene", {
-              //     videos: ["0/0_1_0", "1/0_2_0"],
-              //     range: [start, end],
-              //     isRotate: true,
-              //   });
-              connection.socket.emit("getPush", {
-                userId: testConfig.userId,
-                roomId: testConfig.roomId,
-                sceneCode: testConfig.sceneCode,
-                userSig: connection.userSig,
-              });
-              connection.socket.on("getPush", (data) => {
-                console.log(
-                  "getPush",
-                  `ffmpeg -loglevel info -re -stream_loop -1 -i  output.mp4 -c:v libx264 -preset fast -profile:v baseline -g 30 -sc_threshold 0 -b:v 1500k -f flv "${data}"`
-                );
-              });
-              connection.socket.emit("init-webrtc");
-              console.log("connection.client", connection.client);
-
-              connection.client.on("peer-join", (event) => {
-                console.log("peer-join", event);
-              });
-
-              connection.client.on("client-banned", () => {
-                location.reload();
-              });
-              connection.client.on("stream-added", (event) => {
-                const remoteStream = event.stream;
-                const remoteUserId = remoteStream.getUserId();
-                console.warn("stream-added", remoteStream);
-                console.warn(
-                  "received a remoteStream ID: " +
-                    remoteStream.getId() +
-                    " from user: " +
-                    remoteUserId
-                );
-                // 若需要观看该远端流,则需要订阅它
-
-                connection.client.subscribe(remoteStream);
-              });
-              // connection.client.on('network-quality', event => {
-              //         console.log(`network-quality, uplinkNetworkQuality:${event.uplinkNetworkQuality}, downlinkNetworkQuality: ${event.downlinkNetworkQuality}`)
-              //         // 自 v4.10.3 支持获取上、下行的 RTT 及丢包率
-              //         console.log(`uplink rtt:${event.uplinkRTT} loss:${event.uplinkLoss}`)
-              //         console.log(`downlink rtt:${event.downlinkRTT} loss:${event.downlinkLoss}`)
-              // })
-
-              connection.client.on("stream-subscribed", (event) => {
-                const remoteStream = event.stream;
-
-                // 远端流订阅成功,在HTML页面中创建一个<video>标签,假设该标签ID为‘remote-video-view’
-                // 播放该远端流
-                // console.log("remoteStream", remoteStream);
-                // remoteStream.resume();
-                remoteStream.play("testVideoFeed");
-                const frame = remoteStream.getVideoFrame();
-                const track = remoteStream.getVideoTrack();
-                console.warn("frame", frame, track);
-                console.warn("frame", remoteStream);
-              });
-
-              connection.client.on("error", (event) => {
-                console.log("error", event);
-              });
-
-              connection.client.on("connection-state-changed", (event) => {
-                console.warn("connection-state-changed", event);
-              });
-
-              // 监听‘stream-removed’事件
-              connection.client.on("stream-removed", (event) => {
-                const remoteStream = event.stream;
-                console.log(
-                  "remoteStream ID: " +
-                    remoteStream.getId() +
-                    " has been removed"
-                );
-                // 停止播放并删除相应<video>标签
-              });
-              // 监听‘stream-updated’事件
-              connection.client.on("stream-updated", (event) => {
-                const remoteStream = event.stream;
-                console.warn(
-                  "remoteStream ID: " +
-                    remoteStream.getId() +
-                    " was updated hasAudio: " +
-                    remoteStream.hasAudio() +
-                    " hasVideo: " +
-                    remoteStream.hasVideo()
-                );
-              });
-              // 监听‘stream-subscribed’事件
-            }
-          });
-        });
-      </script>
+      <script type="module" src="./webrtc/srs.js"></script>
     </body>
     <script src="https://web.sdk.qcloud.com/trtc/webrtc/demo/latest/dist/trtc.js"></script>
   </html>
 </html>
-ffmpeg -i 'rtmp://127.0.0.1/live?B1wrZUZQc' -i
-'http://120.24.252.95:8080/live/livestream.flv' -filter_complex overlay -c:v
-libx264 -r 30 -preset ultrafast -tune zerolatency -crf 25 -pix_fmt yuv420p -f
-flv
-"rtmp://rtmp.rtc.qq.com/push/22s1111ss?sdkappid=1400653314&userid=007E83817D55C01F&usersig=eJw1jsEKgkAURf9l1iFvnHF8CK3UaBFUaGFLYUZ5ijLaoEH074nW8p7Dgftm*SnzzMvSaFikQCLAbmWTGVnEfA-Ytp*6La0lzSIuAVQgBJebIW16RxWtAUCYokAeJkEQAz-8a6oXWVzaeh6HfO6mFl2ZNnOvlZvO13CQVWl4o*OuuD9Udrztf6GjbjnGlUQlBaL-*QLFzTO7"

File diff suppressed because it is too large
+ 6 - 0
libs/jquery-1.10.2.min.js


+ 1 - 1
live.sh

@@ -4,5 +4,5 @@ rtspUrl=$1
 videoName=$2
 # echo 'videoFilePath:'$videoFilePath
 
-ffmpeg -y -re  -stream_loop  -1 -f concat -safe 0 -i tt.txt  -c:v libx264 -preset fast -profile:v baseline -g 30 -sc_threshold 0 -b:v 1500k -f flv "$rtspUrl"
+ffmpeg -y -re  -f concat -i $videoName  -c:v libx264 -preset fast -profile:v baseline -g 30 -sc_threshold 0 -b:v 1500k -f flv "$rtspUrl"
 

File diff suppressed because it is too large
+ 1 - 0
webrtc/adapter-7.4.0.min.js


+ 59 - 0
webrtc/connection copy.js

@@ -0,0 +1,59 @@
+// import { io } from "https://cdn.socket.io/4.4.1/socket.io.esm.min.js";
+
+export class Connection {
+  constructor() {
+    socket: null;
+    client: null;
+    userSig: null;
+  }
+
+  startSocket(config) {
+    //192.168.0.52:9099/?userId=123
+    console.log("init-startSocket");
+    const { sdkAppId, roomId, userId } = config;
+    this.socket = io("wss://demo-kms.4dage.com", {
+      reconnectionDelayMax: 10000,
+      transports: ["websocket"],
+      query: {
+        userId: userId,
+        roomId: roomId,
+      },
+    });
+    this.socket.on("connect", (data) => {
+      console.log("111", data);
+    });
+    this.socket.on("connect_error", (error) => {
+      console.log("error", error);
+    });
+
+    // setTimeout(() => {
+    //   console.log("this.socket", this.socket);
+    // }, 3000);
+  }
+
+  async init(config, callback) {
+    console.log("init-trtc");
+    this.startSocket(config);
+
+    const { sdkAppId, roomId, userId, role } = config;
+    this.socket.on("getSign", async (data) => {
+      const userSig = data;
+      this.userSig = userSig;
+      try {
+        const client = TRTC.createClient({
+          mode: "rtc",
+          sdkAppId: sdkAppId,
+          userId: userId,
+          role: role,
+          useStringRoomId: true,
+          userSig,
+        });
+        this.client = client;
+        callback();
+      } catch (error) {
+        console.log("joinRoom error", error);
+        callback(error);
+      }
+    });
+  }
+}

+ 5 - 25
webrtc/connection.js

@@ -1,16 +1,17 @@
 // import { io } from "https://cdn.socket.io/4.4.1/socket.io.esm.min.js";
 
 export class Connection {
-  constructor() {
+  constructor(config) {
     socket: null;
     client: null;
     userSig: null;
+    this.init(config);
   }
 
   startSocket(config) {
     //192.168.0.52:9099/?userId=123
     console.log("init-startSocket");
-    const { sdkAppId, roomId, userId } = config;
+    const {  roomId, userId } = config;
     this.socket = io("wss://demo-kms.4dage.com", {
       reconnectionDelayMax: 10000,
       transports: ["websocket"],
@@ -31,29 +32,8 @@ export class Connection {
     // }, 3000);
   }
 
-  async init(config, callback) {
-    console.log("init-trtc");
+   init(config) {
+    console.log("init-trtc",config);
     this.startSocket(config);
-
-    const { sdkAppId, roomId, userId, role } = config;
-    this.socket.on("getSign", async (data) => {
-      const userSig = data;
-      this.userSig = userSig;
-      try {
-        const client = TRTC.createClient({
-          mode: "rtc",
-          sdkAppId: sdkAppId,
-          userId: userId,
-          role: role,
-          useStringRoomId: true,
-          userSig,
-        });
-        this.client = client;
-        callback();
-      } catch (error) {
-        console.log("joinRoom error", error);
-        callback(error);
-      }
-    });
   }
 }

+ 47 - 0
webrtc/srs.js

@@ -0,0 +1,47 @@
+
+import {SrsRTC } from './SrsRTC.js';
+import { Connection } from './connection.js';
+const sdk = new SrsRTC();
+const testConfig ={
+    userId: '11111',
+    roomId: '111',
+}
+const connection =new Connection(testConfig);
+
+console.log('sdk',sdk)
+console.log('sdk',connection)
+
+connection.socket.emit('pushVideo',{
+    videoList:['0-1-0'],
+    videoId: 'mini'
+})
+
+connection.socket.on('getVideo',(videoId)=>{
+    console.log('getVideo',videoId)
+    if(videoId){
+        const steamUrl ='webrtc://demo-kms.4dage.com/live/' + videoId
+        getVideo(steamUrl)
+    }
+})
+
+
+const getVideo =(videoUrl)=>{
+    $('#testVideoFeed').prop('srcObject', sdk.stream);
+    sdk.getVideo(videoUrl).then(function(session){
+        console.log('session',session.sessionid)
+    
+    }).catch(function (reason) {
+        console.error(reason);
+    })
+}
+
+
+
+// sdk.pc.ondatachannel = function(ev) {
+//     console.log('Data channel is created!');
+//     ev.channel.onopen = function() {
+//       console.log('Data channel is open and ready to be used.');
+//     };
+//   };
+
+

+ 543 - 0
webrtc/srs.sdk.js

@@ -0,0 +1,543 @@
+
+//
+// Copyright (c) 2013-2021 Winlin
+//
+// SPDX-License-Identifier: MIT
+//
+
+'use strict';
+
+function SrsError(name, message) {
+    this.name = name;
+    this.message = message;
+    this.stack = (new Error()).stack;
+}
+SrsError.prototype = Object.create(Error.prototype);
+SrsError.prototype.constructor = SrsError;
+
+// Depends on adapter-7.4.0.min.js from https://github.com/webrtc/adapter
+// Async-awat-prmise based SRS RTC Publisher.
+function SrsRtcPublisherAsync() {
+    var self = {};
+
+    // https://developer.mozilla.org/en-US/docs/Web/API/MediaDevices/getUserMedia
+    self.constraints = {
+        audio: true,
+        video: {
+            width: {ideal: 320, max: 576}
+        }
+    };
+
+    // @see https://github.com/rtcdn/rtcdn-draft
+    // @url The WebRTC url to play with, for example:
+    //      webrtc://r.ossrs.net/live/livestream
+    // or specifies the API port:
+    //      webrtc://r.ossrs.net:11985/live/livestream
+    // or autostart the publish:
+    //      webrtc://r.ossrs.net/live/livestream?autostart=true
+    // or change the app from live to myapp:
+    //      webrtc://r.ossrs.net:11985/myapp/livestream
+    // or change the stream from livestream to mystream:
+    //      webrtc://r.ossrs.net:11985/live/mystream
+    // or set the api server to myapi.domain.com:
+    //      webrtc://myapi.domain.com/live/livestream
+    // or set the candidate(eip) of answer:
+    //      webrtc://r.ossrs.net/live/livestream?candidate=39.107.238.185
+    // or force to access https API:
+    //      webrtc://r.ossrs.net/live/livestream?schema=https
+    // or use plaintext, without SRTP:
+    //      webrtc://r.ossrs.net/live/livestream?encrypt=false
+    // or any other information, will pass-by in the query:
+    //      webrtc://r.ossrs.net/live/livestream?vhost=xxx
+    //      webrtc://r.ossrs.net/live/livestream?token=xxx
+    self.publish = async function (url) {
+        var conf = self.__internal.prepareUrl(url);
+        self.pc.addTransceiver("audio", {direction: "sendonly"});
+        self.pc.addTransceiver("video", {direction: "sendonly"});
+
+        if (!navigator.mediaDevices && window.location.protocol === 'http:' && window.location.hostname !== 'localhost') {
+            throw new SrsError('HttpsRequiredError', `Please use HTTPS or localhost to publish, read https://github.com/ossrs/srs/issues/2762#issuecomment-983147576`);
+        }
+        var stream = await navigator.mediaDevices.getUserMedia(self.constraints);
+
+        // @see https://developer.mozilla.org/en-US/docs/Web/API/RTCPeerConnection/addStream#Migrating_to_addTrack
+        stream.getTracks().forEach(function (track) {
+            self.pc.addTrack(track);
+
+            // Notify about local track when stream is ok.
+            self.ontrack && self.ontrack({track: track});
+        });
+
+        var offer = await self.pc.createOffer();
+        await self.pc.setLocalDescription(offer);
+        var session = await new Promise(function (resolve, reject) {
+            // @see https://github.com/rtcdn/rtcdn-draft
+            var data = {
+                api: conf.apiUrl, tid: conf.tid, streamurl: conf.streamUrl,
+                clientip: null, sdp: offer.sdp
+            };
+            console.log("Generated offer: ", data);
+
+            $.ajax({
+                type: "POST", url: conf.apiUrl, data: JSON.stringify(data),
+                contentType: 'application/json', dataType: 'json'
+            }).done(function (data) {
+                console.log("Got answer: ", data);
+                if (data.code) {
+                    reject(data);
+                    return;
+                }
+
+                resolve(data);
+            }).fail(function (reason) {
+                reject(reason);
+            });
+        });
+        await self.pc.setRemoteDescription(
+            new RTCSessionDescription({type: 'answer', sdp: session.sdp})
+        );
+        session.simulator = conf.schema + '//' + conf.urlObject.server + ':' + conf.port + '/rtc/v1/nack/';
+
+        return session;
+    };
+
+    // Close the publisher.
+    self.close = function () {
+        self.pc && self.pc.close();
+        self.pc = null;
+    };
+
+    // The callback when got local stream.
+    // @see https://developer.mozilla.org/en-US/docs/Web/API/RTCPeerConnection/addStream#Migrating_to_addTrack
+    self.ontrack = function (event) {
+        // Add track to stream of SDK.
+        self.stream.addTrack(event.track);
+    };
+
+    // Internal APIs.
+    self.__internal = {
+        defaultPath: '/rtc/v1/publish/',
+        prepareUrl: function (webrtcUrl) {
+            var urlObject = self.__internal.parse(webrtcUrl);
+
+            // If user specifies the schema, use it as API schema.
+            var schema = urlObject.user_query.schema;
+            schema = schema ? schema + ':' : window.location.protocol;
+
+            var port = urlObject.port || 1985;
+            if (schema === 'https:') {
+                port = urlObject.port || 443;
+            }
+
+            // @see https://github.com/rtcdn/rtcdn-draft
+            var api = urlObject.user_query.play || self.__internal.defaultPath;
+            if (api.lastIndexOf('/') !== api.length - 1) {
+                api += '/';
+            }
+
+            apiUrl = schema + '//' + urlObject.server + ':' + port + api;
+            for (var key in urlObject.user_query) {
+                if (key !== 'api' && key !== 'play') {
+                    apiUrl += '&' + key + '=' + urlObject.user_query[key];
+                }
+            }
+            // Replace /rtc/v1/play/&k=v to /rtc/v1/play/?k=v
+            var apiUrl = apiUrl.replace(api + '&', api + '?');
+
+            var streamUrl = urlObject.url;
+
+            return {
+                apiUrl: apiUrl, streamUrl: streamUrl, schema: schema, urlObject: urlObject, port: port,
+                tid: Number(parseInt(new Date().getTime()*Math.random()*100)).toString(16).slice(0, 7)
+            };
+        },
+        parse: function (url) {
+            // @see: http://stackoverflow.com/questions/10469575/how-to-use-location-object-to-parse-url-without-redirecting-the-page-in-javascri
+            var a = document.createElement("a");
+            a.href = url.replace("rtmp://", "http://")
+                .replace("webrtc://", "http://")
+                .replace("rtc://", "http://");
+
+            var vhost = a.hostname;
+            var app = a.pathname.substring(1, a.pathname.lastIndexOf("/"));
+            var stream = a.pathname.slice(a.pathname.lastIndexOf("/") + 1);
+
+            // parse the vhost in the params of app, that srs supports.
+            app = app.replace("...vhost...", "?vhost=");
+            if (app.indexOf("?") >= 0) {
+                var params = app.slice(app.indexOf("?"));
+                app = app.slice(0, app.indexOf("?"));
+
+                if (params.indexOf("vhost=") > 0) {
+                    vhost = params.slice(params.indexOf("vhost=") + "vhost=".length);
+                    if (vhost.indexOf("&") > 0) {
+                        vhost = vhost.slice(0, vhost.indexOf("&"));
+                    }
+                }
+            }
+
+            // when vhost equals to server, and server is ip,
+            // the vhost is __defaultVhost__
+            if (a.hostname === vhost) {
+                var re = /^(\d+)\.(\d+)\.(\d+)\.(\d+)$/;
+                if (re.test(a.hostname)) {
+                    vhost = "__defaultVhost__";
+                }
+            }
+
+            // parse the schema
+            var schema = "rtmp";
+            if (url.indexOf("://") > 0) {
+                schema = url.slice(0, url.indexOf("://"));
+            }
+
+            var port = a.port;
+            if (!port) {
+                // Finger out by webrtc url, if contains http or https port, to overwrite default 1985.
+                if (schema === 'webrtc' && url.indexOf(`webrtc://${a.host}:`) === 0) {
+                    port = (url.indexOf(`webrtc://${a.host}:80`) === 0) ? 80 : 443;
+                }
+
+                // Guess by schema.
+                if (schema === 'http') {
+                    port = 80;
+                } else if (schema === 'https') {
+                    port = 443;
+                } else if (schema === 'rtmp') {
+                    port = 1935;
+                }
+            }
+
+            var ret = {
+                url: url,
+                schema: schema,
+                server: a.hostname, port: port,
+                vhost: vhost, app: app, stream: stream
+            };
+            self.__internal.fill_query(a.search, ret);
+
+            // For webrtc API, we use 443 if page is https, or schema specified it.
+            if (!ret.port) {
+                if (schema === 'webrtc' || schema === 'rtc') {
+                    if (ret.user_query.schema === 'https') {
+                        ret.port = 443;
+                    } else if (window.location.href.indexOf('https://') === 0) {
+                        ret.port = 443;
+                    } else {
+                        // For WebRTC, SRS use 1985 as default API port.
+                        ret.port = 1985;
+                    }
+                }
+            }
+
+            return ret;
+        },
+        fill_query: function (query_string, obj) {
+            // pure user query object.
+            obj.user_query = {};
+
+            if (query_string.length === 0) {
+                return;
+            }
+
+            // split again for angularjs.
+            if (query_string.indexOf("?") >= 0) {
+                query_string = query_string.split("?")[1];
+            }
+
+            var queries = query_string.split("&");
+            for (var i = 0; i < queries.length; i++) {
+                var elem = queries[i];
+
+                var query = elem.split("=");
+                obj[query[0]] = query[1];
+                obj.user_query[query[0]] = query[1];
+            }
+
+            // alias domain for vhost.
+            if (obj.domain) {
+                obj.vhost = obj.domain;
+            }
+        }
+    };
+
+    self.pc = new RTCPeerConnection(null);
+
+    // To keep api consistent between player and publisher.
+    // @see https://developer.mozilla.org/en-US/docs/Web/API/RTCPeerConnection/addStream#Migrating_to_addTrack
+    // @see https://webrtc.org/getting-started/media-devices
+    self.stream = new MediaStream();
+
+    return self;
+}
+
+// Depends on adapter-7.4.0.min.js from https://github.com/webrtc/adapter
+// Async-await-promise based SRS RTC Player.
+function SrsRtcPlayerAsync() {
+    var self = {};
+
+    // @see https://github.com/rtcdn/rtcdn-draft
+    // @url The WebRTC url to play with, for example:
+    //      webrtc://r.ossrs.net/live/livestream
+    // or specifies the API port:
+    //      webrtc://r.ossrs.net:11985/live/livestream
+    //      webrtc://r.ossrs.net:80/live/livestream
+    // or autostart the play:
+    //      webrtc://r.ossrs.net/live/livestream?autostart=true
+    // or change the app from live to myapp:
+    //      webrtc://r.ossrs.net:11985/myapp/livestream
+    // or change the stream from livestream to mystream:
+    //      webrtc://r.ossrs.net:11985/live/mystream
+    // or set the api server to myapi.domain.com:
+    //      webrtc://myapi.domain.com/live/livestream
+    // or set the candidate(eip) of answer:
+    //      webrtc://r.ossrs.net/live/livestream?candidate=39.107.238.185
+    // or force to access https API:
+    //      webrtc://r.ossrs.net/live/livestream?schema=https
+    // or use plaintext, without SRTP:
+    //      webrtc://r.ossrs.net/live/livestream?encrypt=false
+    // or any other information, will pass-by in the query:
+    //      webrtc://r.ossrs.net/live/livestream?vhost=xxx
+    //      webrtc://r.ossrs.net/live/livestream?token=xxx
+    self.play = async function(url) {
+        var conf = self.__internal.prepareUrl(url);
+        self.pc.addTransceiver("audio", {direction: "recvonly"});
+        self.pc.addTransceiver("video", {direction: "recvonly"});
+
+        var offer = await self.pc.createOffer();
+        await self.pc.setLocalDescription(offer);
+        var session = await new Promise(function(resolve, reject) {
+            // @see https://github.com/rtcdn/rtcdn-draft
+            var data = {
+                api: conf.apiUrl, tid: conf.tid, streamurl: conf.streamUrl,
+                clientip: null, sdp: offer.sdp
+            };
+            console.log("Generated offer: ", data);
+
+            $.ajax({
+                type: "POST", url: conf.apiUrl, data: JSON.stringify(data),
+                contentType:'application/json', dataType: 'json'
+            }).done(function(data) {
+                console.log("Got answer: ", data);
+                if (data.code) {
+                    reject(data); return;
+                }
+
+                resolve(data);
+            }).fail(function(reason){
+                reject(reason);
+            });
+        });
+        await self.pc.setRemoteDescription(
+            new RTCSessionDescription({type: 'answer', sdp: session.sdp})
+        );
+        session.simulator = conf.schema + '//' + conf.urlObject.server + ':' + conf.port + '/rtc/v1/nack/';
+
+        return session;
+    };
+
+    // Close the player.
+    self.close = function() {
+        self.pc && self.pc.close();
+        self.pc = null;
+    };
+
+    // The callback when got remote track.
+    // Note that the onaddstream is deprecated, @see https://developer.mozilla.org/en-US/docs/Web/API/RTCPeerConnection/onaddstream
+    self.ontrack = function (event) {
+        // https://webrtc.org/getting-started/remote-streams
+        self.stream.addTrack(event.track);
+    };
+
+    // Internal APIs.
+    self.__internal = {
+        defaultPath: '/rtc/v1/play/',
+        prepareUrl: function (webrtcUrl) {
+            var urlObject = self.__internal.parse(webrtcUrl);
+
+            // If user specifies the schema, use it as API schema.
+            var schema = urlObject.user_query.schema;
+            schema = schema ? schema + ':' : window.location.protocol;
+
+            var port = urlObject.port || 1985;
+            if (schema === 'https:') {
+                port = urlObject.port || 443;
+            }
+
+            // @see https://github.com/rtcdn/rtcdn-draft
+            var api = urlObject.user_query.play || self.__internal.defaultPath;
+            if (api.lastIndexOf('/') !== api.length - 1) {
+                api += '/';
+            }
+
+            apiUrl = schema + '//' + urlObject.server + ':' + port + api;
+            for (var key in urlObject.user_query) {
+                if (key !== 'api' && key !== 'play') {
+                    apiUrl += '&' + key + '=' + urlObject.user_query[key];
+                }
+            }
+            // Replace /rtc/v1/play/&k=v to /rtc/v1/play/?k=v
+            var apiUrl = apiUrl.replace(api + '&', api + '?');
+
+            var streamUrl = urlObject.url;
+
+            return {
+                apiUrl: apiUrl, streamUrl: streamUrl, schema: schema, urlObject: urlObject, port: port,
+                tid: Number(parseInt(new Date().getTime()*Math.random()*100)).toString(16).slice(0, 7)
+            };
+        },
+        parse: function (url) {
+            // @see: http://stackoverflow.com/questions/10469575/how-to-use-location-object-to-parse-url-without-redirecting-the-page-in-javascri
+            var a = document.createElement("a");
+            a.href = url.replace("rtmp://", "http://")
+                .replace("webrtc://", "http://")
+                .replace("rtc://", "http://");
+
+            var vhost = a.hostname;
+            var app = a.pathname.substring(1, a.pathname.lastIndexOf("/"));
+            var stream = a.pathname.slice(a.pathname.lastIndexOf("/") + 1);
+
+            // parse the vhost in the params of app, that srs supports.
+            app = app.replace("...vhost...", "?vhost=");
+            if (app.indexOf("?") >= 0) {
+                var params = app.slice(app.indexOf("?"));
+                app = app.slice(0, app.indexOf("?"));
+
+                if (params.indexOf("vhost=") > 0) {
+                    vhost = params.slice(params.indexOf("vhost=") + "vhost=".length);
+                    if (vhost.indexOf("&") > 0) {
+                        vhost = vhost.slice(0, vhost.indexOf("&"));
+                    }
+                }
+            }
+
+            // when vhost equals to server, and server is ip,
+            // the vhost is __defaultVhost__
+            if (a.hostname === vhost) {
+                var re = /^(\d+)\.(\d+)\.(\d+)\.(\d+)$/;
+                if (re.test(a.hostname)) {
+                    vhost = "__defaultVhost__";
+                }
+            }
+
+            // parse the schema
+            var schema = "rtmp";
+            if (url.indexOf("://") > 0) {
+                schema = url.slice(0, url.indexOf("://"));
+            }
+
+            var port = a.port;
+            if (!port) {
+                // Finger out by webrtc url, if contains http or https port, to overwrite default 1985.
+                if (schema === 'webrtc' && url.indexOf(`webrtc://${a.host}:`) === 0) {
+                    port = (url.indexOf(`webrtc://${a.host}:80`) === 0) ? 80 : 443;
+                }
+
+                // Guess by schema.
+                if (schema === 'http') {
+                    port = 80;
+                } else if (schema === 'https') {
+                    port = 443;
+                } else if (schema === 'rtmp') {
+                    port = 1935;
+                }
+            }
+
+            var ret = {
+                url: url,
+                schema: schema,
+                server: a.hostname, port: port,
+                vhost: vhost, app: app, stream: stream
+            };
+            self.__internal.fill_query(a.search, ret);
+
+            // For webrtc API, we use 443 if page is https, or schema specified it.
+            if (!ret.port) {
+                if (schema === 'webrtc' || schema === 'rtc') {
+                    if (ret.user_query.schema === 'https') {
+                        ret.port = 443;
+                    } else if (window.location.href.indexOf('https://') === 0) {
+                        ret.port = 443;
+                    } else {
+                        // For WebRTC, SRS use 1985 as default API port.
+                        ret.port = 1985;
+                    }
+                }
+            }
+
+            return ret;
+        },
+        fill_query: function (query_string, obj) {
+            // pure user query object.
+            obj.user_query = {};
+
+            if (query_string.length === 0) {
+                return;
+            }
+
+            // split again for angularjs.
+            if (query_string.indexOf("?") >= 0) {
+                query_string = query_string.split("?")[1];
+            }
+
+            var queries = query_string.split("&");
+            for (var i = 0; i < queries.length; i++) {
+                var elem = queries[i];
+
+                var query = elem.split("=");
+                obj[query[0]] = query[1];
+                obj.user_query[query[0]] = query[1];
+            }
+
+            // alias domain for vhost.
+            if (obj.domain) {
+                obj.vhost = obj.domain;
+            }
+        }
+    };
+
+    self.pc = new RTCPeerConnection(null);
+
+    // Create a stream to add track to the stream, @see https://webrtc.org/getting-started/remote-streams
+    self.stream = new MediaStream();
+
+    // https://developer.mozilla.org/en-US/docs/Web/API/RTCPeerConnection/ontrack
+    self.pc.ontrack = function(event) {
+        if (self.ontrack) {
+            self.ontrack(event);
+        }
+    };
+
+    return self;
+}
+
+// Format the codec of RTCRtpSender, kind(audio/video) is optional filter.
+// https://developer.mozilla.org/en-US/docs/Web/Media/Formats/WebRTC_codecs#getting_the_supported_codecs
+function SrsRtcFormatSenders(senders, kind) {
+    var codecs = [];
+    senders.forEach(function (sender) {
+        var params = sender.getParameters();
+        params && params.codecs && params.codecs.forEach(function(c) {
+            if (kind && sender.track.kind !== kind) {
+                return;
+            }
+
+            if (c.mimeType.indexOf('/red') > 0 || c.mimeType.indexOf('/rtx') > 0 || c.mimeType.indexOf('/fec') > 0) {
+                return;
+            }
+
+            var s = '';
+
+            s += c.mimeType.replace('audio/', '').replace('video/', '');
+            s += ', ' + c.clockRate + 'HZ';
+            if (sender.track.kind === "audio") {
+                s += ', channels: ' + c.channels;
+            }
+            s += ', pt: ' + c.payloadType;
+
+            codecs.push(s);
+        });
+    });
+    return codecs.join(", ");
+}
+

+ 60 - 0
webrtc/srsRtc.js

@@ -0,0 +1,60 @@
+
+export class SrsRTC {
+    constructor(url){
+        this.pc = new RTCPeerConnection(null);
+        this.stream = new MediaStream();
+        this.url = url;
+        this.pc.ontrack =  (event) => {
+            // https://webrtc.org/getting-started/remote-streams
+            console.log('event',event.track)
+            if(this.stream){
+                this.stream.addTrack(event.track);
+            }
+     
+       
+        };
+
+    }
+ 
+    async getVideo(clipUrl){
+        this.pc.addTransceiver("video", {direction: "recvonly"});
+
+        const serverApi ='https://demo-kms.4dage.com:443/rtc/v1/play/';
+        const tid = Number(parseInt(new Date().getTime()*Math.random()*100)).toString(16).slice(0, 7);
+        var offer = await this.pc.createOffer();
+        await this.pc.setLocalDescription(offer);
+        const session = await new Promise(function(resolve, reject) {
+            // @see https://github.com/rtcdn/rtcdn-draft
+            var data = {
+                api: serverApi,
+                tid: tid,
+                streamurl: clipUrl,
+                clientip: null, 
+                sdp: offer.sdp
+            };
+
+            console.log("Generated offer: ", data);
+
+            $.ajax({
+                type: "POST", url: serverApi, data: JSON.stringify(data),
+                contentType:'application/json', dataType: 'json'
+            }).done(function(data) {
+                console.log("Got answer: ", data);
+                if (data.code) {
+                    reject(data); return;
+                }
+
+                resolve(data);
+            }).fail(function(reason){
+                reject(reason);
+            });
+        });
+        await this.pc.setRemoteDescription(
+            new RTCSessionDescription({type: 'answer', sdp: session.sdp})
+        );
+        
+    
+        return session;
+        
+    }
+}

+ 113 - 0
webrtc/trtcInit.js

@@ -0,0 +1,113 @@
+import { Connection } from "./webrtc/connection.js";
+import { uuid } from "./webrtc/uuid.js";
+document.addEventListener("DOMContentLoaded", async () => {
+  const connection = new Connection();
+  window.connection = connection;
+  const testConfig = {
+    userId: uuid(16, 16),
+    roomId: "22s1111ss",
+    sdkAppId: 1400653314,
+    sceneCode: "2111",
+  };
+  console.log("testConfig", testConfig);
+  connection.init(testConfig, async () => {
+    if (connection.client) {
+      await connection.client.join({ roomId: testConfig.roomId });
+      console.log("userSig", connection.userSig);
+
+      //   connection.socket.on("init-scene", {
+      //     videos: ["0/0_1_0", "1/0_2_0"],
+      //     range: [start, end],
+      //     isRotate: true,
+      //   });
+      connection.socket.emit("getPush", {
+        userId: testConfig.userId,
+        roomId: testConfig.roomId,
+        sceneCode: testConfig.sceneCode,
+        userSig: connection.userSig,
+      });
+      connection.socket.on("getPush", (data) => {
+        console.log(
+          "getPush",
+          `ffmpeg -loglevel info -re -stream_loop -1 -i  output.mp4 -c:v libx264 -preset fast -profile:v baseline -g 30 -sc_threshold 0 -b:v 1500k -f flv "${data}"`
+        );
+      });
+      connection.socket.emit("init-webrtc");
+      console.log("connection.client", connection.client);
+
+      connection.client.on("peer-join", (event) => {
+        console.log("peer-join", event);
+      });
+
+      connection.client.on("client-banned", () => {
+        location.reload();
+      });
+      connection.client.on("stream-added", (event) => {
+        const remoteStream = event.stream;
+        const remoteUserId = remoteStream.getUserId();
+        console.warn("stream-added", remoteStream);
+        console.warn(
+          "received a remoteStream ID: " +
+            remoteStream.getId() +
+            " from user: " +
+            remoteUserId
+        );
+        // 若需要观看该远端流,则需要订阅它
+
+        connection.client.subscribe(remoteStream);
+      });
+      // connection.client.on('network-quality', event => {
+      //         console.log(`network-quality, uplinkNetworkQuality:${event.uplinkNetworkQuality}, downlinkNetworkQuality: ${event.downlinkNetworkQuality}`)
+      //         // 自 v4.10.3 支持获取上、下行的 RTT 及丢包率
+      //         console.log(`uplink rtt:${event.uplinkRTT} loss:${event.uplinkLoss}`)
+      //         console.log(`downlink rtt:${event.downlinkRTT} loss:${event.downlinkLoss}`)
+      // })
+
+      connection.client.on("stream-subscribed", (event) => {
+        const remoteStream = event.stream;
+
+        // 远端流订阅成功,在HTML页面中创建一个<video>标签,假设该标签ID为‘remote-video-view’
+        // 播放该远端流
+        // console.log("remoteStream", remoteStream);
+        // remoteStream.resume();
+        remoteStream.play("testVideoFeed");
+        const frame = remoteStream.getVideoFrame();
+        const track = remoteStream.getVideoTrack();
+        console.warn("frame", frame, track);
+        console.warn("frame", remoteStream);
+      });
+
+      connection.client.on("error", (event) => {
+        console.log("error", event);
+      });
+
+      connection.client.on("connection-state-changed", (event) => {
+        console.warn("connection-state-changed", event);
+      });
+
+      // 监听‘stream-removed’事件
+      connection.client.on("stream-removed", (event) => {
+        const remoteStream = event.stream;
+        console.log(
+          "remoteStream ID: " +
+            remoteStream.getId() +
+            " has been removed"
+        );
+        // 停止播放并删除相应<video>标签
+      });
+      // 监听‘stream-updated’事件
+      connection.client.on("stream-updated", (event) => {
+        const remoteStream = event.stream;
+        console.warn(
+          "remoteStream ID: " +
+            remoteStream.getId() +
+            " was updated hasAudio: " +
+            remoteStream.hasAudio() +
+            " hasVideo: " +
+            remoteStream.hasVideo()
+        );
+      });
+      // 监听‘stream-subscribed’事件
+    }
+  });
+});