• webrtc限制发送速率


    webrtc官方的代码示例:

    /*
     *  Copyright (c) 2016 The WebRTC project authors. All Rights Reserved.
     *
     *  Use of this source code is governed by a BSD-style license
     *  that can be found in the LICENSE file in the root of the source
     *  tree.
     */
    /* global TimelineDataSeries, TimelineGraphView */
    
    'use strict';
    
    const remoteVideo = document.querySelector('video#remoteVideo');
    const localVideo = document.querySelector('video#localVideo');
    const callButton = document.querySelector('button#callButton');
    const hangupButton = document.querySelector('button#hangupButton');
    const bandwidthSelector = document.querySelector('select#bandwidth');
    hangupButton.disabled = true;
    callButton.onclick = call;
    hangupButton.onclick = hangup;
    
    let pc1;
    let pc2;
    let localStream;
    
    // Can be set in the console before making a call to test this keeps
    // within the envelope set by the SDP. In kbps.
    const maxBandwidth = 0;
    
    let bitrateGraph;
    let bitrateSeries;
    
    let packetGraph;
    let packetSeries;
    
    let lastResult;
    
    const offerOptions = {
      offerToReceiveAudio: 0,
      offerToReceiveVideo: 1
    };
    
    function gotStream(stream) {
      hangupButton.disabled = false;
      console.log('Received local stream');
      localStream = stream;
      localVideo.srcObject = stream;
      localStream.getTracks().forEach(track => pc1.addTrack(track, localStream));
      console.log('Adding Local Stream to peer connection');
    
      pc1.createOffer(
          offerOptions
      ).then(
          gotDescription1,
          onCreateSessionDescriptionError
      );
    
      bitrateSeries = new TimelineDataSeries();
      bitrateGraph = new TimelineGraphView('bitrateGraph', 'bitrateCanvas');
      bitrateGraph.updateEndDate();
    
      packetSeries = new TimelineDataSeries();
      packetGraph = new TimelineGraphView('packetGraph', 'packetCanvas');
      packetGraph.updateEndDate();
    }
    
    function onCreateSessionDescriptionError(error) {
      console.log('Failed to create session description: ' + error.toString());
    }
    
    function call() {
      callButton.disabled = true;
      bandwidthSelector.disabled = false;
      console.log('Starting call');
      const servers = null;
      pc1 = new RTCPeerConnection(servers);
      console.log('Created local peer connection object pc1');
      pc1.onicecandidate = onIceCandidate.bind(pc1);
    
      pc2 = new RTCPeerConnection(servers);
      console.log('Created remote peer connection object pc2');
      pc2.onicecandidate = onIceCandidate.bind(pc2);
      pc2.ontrack = gotRemoteStream;
    
      console.log('Requesting local stream');
      navigator.mediaDevices.getUserMedia({video: true})
          .then(gotStream)
          .catch(e => alert('getUserMedia() error: ' + e.name));
    }
    
    function gotDescription1(desc) {
      console.log('Offer from pc1 
    ' + desc.sdp);
      pc1.setLocalDescription(desc).then(
          () => {
            pc2.setRemoteDescription(desc)
                .then(() => pc2.createAnswer().then(gotDescription2, onCreateSessionDescriptionError),
                    onSetSessionDescriptionError);
          }, onSetSessionDescriptionError
      );
    }
    
    function gotDescription2(desc) {
      pc2.setLocalDescription(desc).then(
          () => {
            console.log('Answer from pc2 
    ' + desc.sdp);
            let p;
            if (maxBandwidth) {
              p = pc1.setRemoteDescription({
                type: desc.type,
                sdp: updateBandwidthRestriction(desc.sdp, maxBandwidth)
              });
            } else {
              p = pc1.setRemoteDescription(desc);
            }
            p.then(() => {}, onSetSessionDescriptionError);
          },
          onSetSessionDescriptionError
      );
    }
    
    function hangup() {
      console.log('Ending call');
      localStream.getTracks().forEach(track => track.stop());
      pc1.close();
      pc2.close();
      pc1 = null;
      pc2 = null;
      hangupButton.disabled = true;
      callButton.disabled = false;
      bandwidthSelector.disabled = true;
    }
    
    function gotRemoteStream(e) {
      if (remoteVideo.srcObject !== e.streams[0]) {
        remoteVideo.srcObject = e.streams[0];
        console.log('Received remote stream');
      }
    }
    
    function getOtherPc(pc) {
      return pc === pc1 ? pc2 : pc1;
    }
    
    function getName(pc) {
      return pc === pc1 ? 'pc1' : 'pc2';
    }
    
    function onIceCandidate(event) {
      getOtherPc(this)
          .addIceCandidate(event.candidate)
          .then(onAddIceCandidateSuccess)
          .catch(onAddIceCandidateError);
    
      console.log(`${getName(this)} ICE candidate:
    ${event.candidate ? event.candidate.candidate : '(null)'}`);
    }
    
    function onAddIceCandidateSuccess() {
      console.log('AddIceCandidate success.');
    }
    
    function onAddIceCandidateError(error) {
      console.log('Failed to add ICE Candidate: ' + error.toString());
    }
    
    function onSetSessionDescriptionError(error) {
      console.log('Failed to set session description: ' + error.toString());
    }
    
    // renegotiate bandwidth on the fly.
    bandwidthSelector.onchange = () => {
      bandwidthSelector.disabled = true;
      const bandwidth = bandwidthSelector.options[bandwidthSelector.selectedIndex].value;
    
      // In Chrome, use RTCRtpSender.setParameters to change bandwidth without
      // (local) renegotiation. Note that this will be within the envelope of
      // the initial maximum bandwidth negotiated via SDP.
      //在chrome中,使用RTCRtpSender.setParameters方法来改变带宽而不使用(本地)重新协商,
      //注意,这个带宽大小只能在最初的媒体协商的最大带宽之内。
      if ((adapter.browserDetails.browser === 'chrome' ||
           (adapter.browserDetails.browser === 'firefox' &&
            adapter.browserDetails.version >= 64)) &&
          'RTCRtpSender' in window &&
          'setParameters' in window.RTCRtpSender.prototype) {
        const sender = pc1.getSenders()[0];
        const parameters = sender.getParameters();
        if (!parameters.encodings) {
          parameters.encodings = [{}];
        }
        if (bandwidth === 'unlimited') {
          delete parameters.encodings[0].maxBitrate;
        } else {
          parameters.encodings[0].maxBitrate = bandwidth * 1000;
        }
        sender.setParameters(parameters)
            .then(() => {
              bandwidthSelector.disabled = false;
            })
            .catch(e => console.error(e));
        return;
      }
      // Fallback to the SDP munging with local renegotiation way of limiting the bandwidth.
      //回退到SDP,用本地重新协商的方式限制带宽。
      console.log("Fallback to the SDP munging with local renegotiation way of limiting");
      pc1.createOffer()
          .then(offer => pc1.setLocalDescription(offer))
          .then(() => {
            const desc = {
              type: pc1.remoteDescription.type,
              sdp: bandwidth === 'unlimited' ?
              removeBandwidthRestriction(pc1.remoteDescription.sdp) :
              updateBandwidthRestriction(pc1.remoteDescription.sdp, bandwidth)
            };
            console.log('Applying bandwidth restriction to setRemoteDescription:
    ' +
            desc.sdp);
            return pc1.setRemoteDescription(desc);
          })
          .then(() => {
            bandwidthSelector.disabled = false;
          })
          .catch(onSetSessionDescriptionError);
    };
    
    function updateBandwidthRestriction(sdp, bandwidth) {
      let modifier = 'AS';
      if (adapter.browserDetails.browser === 'firefox') {
          //>>>无符号右移,大于0的数值位运算后结果不变,任何非数值变量做此运算都会变为0
        bandwidth = (bandwidth >>> 0) * 1000;
        modifier = 'TIAS';
      }
      if (sdp.indexOf('b=' + modifier + ':') === -1) {
        // insert b= after c= line.
        sdp = sdp.replace(/c=IN (.*)
    /, 'c=IN $1
    b=' + modifier + ':' + bandwidth + '
    ');
      } else {
        sdp = sdp.replace(new RegExp('b=' + modifier + ':.*
    '), 'b=' + modifier + ':' + bandwidth + '
    ');
      }
      return sdp;
    }
    
    function removeBandwidthRestriction(sdp) {
      return sdp.replace(/b=AS:.*
    /, '').replace(/b=TIAS:.*
    /, '');
    }
    
    // query getStats every second
    //每秒获取Senders状态
    window.setInterval(() => {
      if (!pc1) {
        return;
      }
      const sender = pc1.getSenders()[0];
      if (!sender) {
        return;
      }
      sender.getStats().then(res => {
        res.forEach(report => {
          let bytes;
          let packets;
          if (report.type === 'outbound-rtp') {
            if (report.isRemote) {
              return;
            }
            const now = report.timestamp;
            bytes = report.bytesSent;
            packets = report.packetsSent;
            if (lastResult && lastResult.has(report.id)) {
              // calculate bitrate
              const bitrate = 8 * (bytes - lastResult.get(report.id).bytesSent) /
                (now - lastResult.get(report.id).timestamp);
    
              // append to chart
              bitrateSeries.addPoint(now, bitrate);
              bitrateGraph.setDataSeries([bitrateSeries]);
              bitrateGraph.updateEndDate();
    
              // calculate number of packets and append to chart
              packetSeries.addPoint(now, packets -
                lastResult.get(report.id).packetsSent);
              packetGraph.setDataSeries([packetSeries]);
              packetGraph.updateEndDate();
            }
          }
        });
        lastResult = res;
      });
    }, 1000);
  • 相关阅读:
    收藏本站
    JS动态生成ID+JS绑定数据
    CSS样式a:link
    C#绑定gridview
    jQuery checkbox 全选、全取消
    JS打开新窗口
    中用图片代替浏览按钮
    给button端添加客户端方法
    jQuery操作 checkbox 的全选、反选 , radio, select 功能
    C#弹出对话框
  • 原文地址:https://www.cnblogs.com/dch0/p/12197866.html
Copyright © 2020-2023  润新知