jswebrtc 拉流 webrtc://xxx

1、下载 jswebrtc.min.js 文件( / dist / jswebrtc.min.js ):

JSWebrtc – 支持 SRS 的 Webrtc 播放器

var JSWebrtc = {
  Player: null,
  VideoElement: null,
  CreateVideoElements: function() {
    var elements = document.querySelectorAll(".jswebrtc");
    for (var i = 0; i < elements.length; i++) {
      new JSWebrtc.VideoElement(elements[i]);
    }
  },
  FillQuery: function(query_string, obj) {
    obj.user_query = {};
    if (query_string.length == 0) return;
    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 query = queries[i].split("=");
      obj[query[0]] = query[1];
      obj.user_query[query[0]] = query[1];
    }
    if (obj.domain) obj.vhost = obj.domain;
  },
  ParseUrl: function(rtmp_url) {
    var a = document.createElement("a");
    a.href = rtmp_url
      .replace("rtmp://", "http://")
      .replace("webrtc://", "http://")
      .replace("rtc://", "http://");
    var vhost = a.hostname;
    var app = a.pathname.substr(1, a.pathname.lastIndexOf("/") - 1);
    var stream = a.pathname.substr(a.pathname.lastIndexOf("/") + 1);
    app = app.replace("...vhost...", "?vhost=");
    if (app.indexOf("?") >= 0) {
      var params = app.substr(app.indexOf("?"));
      app = app.substr(0, app.indexOf("?"));
      if (params.indexOf("vhost=") > 0) {
        vhost = params.substr(params.indexOf("vhost=") + "vhost=".length);
        if (vhost.indexOf("&") > 0) {
          vhost = vhost.substr(0, vhost.indexOf("&"));
        }
      }
    }
    if (a.hostname == vhost) {
      var re = /^(\d+)\.(\d+)\.(\d+)\.(\d+)$/;
      if (re.test(a.hostname)) vhost = "__defaultVhost__";
    }
    var schema = "rtmp";
    if (rtmp_url.indexOf("://") > 0)
      schema = rtmp_url.substr(0, rtmp_url.indexOf("://"));
    var port = a.port;
    if (!port) {
      if (schema === "http") {
        port = 80;
      } else if (schema === "https") {
        port = 443;
      } else if (schema === "rtmp") {
        port = 1935;
      } else if (schema === "webrtc" || schema === "rtc") {
        port = 1985;
      }
    }
    var ret = {
      url: rtmp_url,
      schema: schema,
      server: a.hostname,
      port: port,
      vhost: vhost,
      app: app,
      stream: stream
    };
    JSWebrtc.FillQuery(a.search, ret);
    return ret;
  },
  HttpPost: function(url, data) {
    return new Promise(function(resolve, reject) {
      var xhr = new XMLHttpRequest();
      xhr.onreadystatechange = function() {
        if (xhr.readyState === 4 && (xhr.status >= 200 && xhr.status < 300)) {
          var respone = JSON.parse(xhr.responseText);
          xhr.onreadystatechange = new Function();
          xhr = null;
          resolve(respone);
        }
      };
      xhr.open("POST", url, true);
      xhr.timeout = 5e3;
      xhr.responseType = "text";
      xhr.setRequestHeader("Content-Type", "application/json");
      xhr.send(data);
    });
  }
};
if (document.readyState === "complete") {
  JSWebrtc.CreateVideoElements();
} else {
  document.addEventListener("DOMContentLoaded", JSWebrtc.CreateVideoElements);
}
JSWebrtc.VideoElement = (function() {
  "use strict";
  var VideoElement = function(element) {
    var url = element.dataset.url;
    if (!url) {
      throw "VideoElement has no `data-url` attribute";
    }
    var addStyles = function(element, styles) {
      for (var name in styles) {
        element.style[name] = styles[name];
      }
    };
    this.container = element;
    addStyles(this.container, {
      display: "inline-block",
      position: "relative",
      minWidth: "80px",
      minHeight: "80px"
    });
    this.video = document.createElement("video");
    this.video.width = 960;
    this.video.height = 540;
    addStyles(this.video, { display: "block", width: "100%" });
    this.container.appendChild(this.video);
    this.playButton = document.createElement("div");
    this.playButton.innerHTML = VideoElement.PLAY_BUTTON;
    addStyles(this.playButton, {
      zIndex: 2,
      position: "absolute",
      top: "0",
      bottom: "0",
      left: "0",
      right: "0",
      maxWidth: "75px",
      maxHeight: "75px",
      margin: "auto",
      opacity: "0.7",
      cursor: "pointer"
    });
    this.container.appendChild(this.playButton);
    var options = { video: this.video };
    for (var option in element.dataset) {
      try {
        options[option] = JSON.parse(element.dataset[option]);
      } catch (err) {
        options[option] = element.dataset[option];
      }
    }
    this.player = new JSWebrtc.Player(url, options);
    element.playerInstance = this.player;
    if (options.poster && !options.autoplay) {
      options.decodeFirstFrame = false;
      this.poster = new Image();
      this.poster.src = options.poster;
      this.poster.addEventListener("load", this.posterLoaded);
      addStyles(this.poster, {
        display: "block",
        zIndex: 1,
        position: "absolute",
        top: 0,
        left: 0,
        bottom: 0,
        right: 0
      });
      this.container.appendChild(this.poster);
    }
    if (!this.player.options.streaming) {
      this.container.addEventListener("click", this.onClick.bind(this));
    }
    if (options.autoplay) {
      this.playButton.style.display = "none";
    }
    if (this.player.audioOut && !this.player.audioOut.unlocked) {
      var unlockAudioElement = this.container;
      if (options.autoplay) {
        this.unmuteButton = document.createElement("div");
        this.unmuteButton.innerHTML = VideoElement.UNMUTE_BUTTON;
        addStyles(this.unmuteButton, {
          zIndex: 2,
          position: "absolute",
          bottom: "10px",
          right: "20px",
          width: "75px",
          height: "75px",
          margin: "auto",
          opacity: "0.7",
          cursor: "pointer"
        });
        this.container.appendChild(this.unmuteButton);
        unlockAudioElement = this.unmuteButton;
      }
      this.unlockAudioBound = this.onUnlockAudio.bind(this, unlockAudioElement);
      unlockAudioElement.addEventListener(
        "touchstart",
        this.unlockAudioBound,
        false
      );
      unlockAudioElement.addEventListener("click", this.unlockAudioBound, true);
    }
  };
  VideoElement.prototype.onUnlockAudio = function(element, ev) {
    if (this.unmuteButton) {
      ev.preventDefault();
      ev.stopPropagation();
    }
    this.player.audioOut.unlock(
      function() {
        if (this.unmuteButton) {
          this.unmuteButton.style.display = "none";
        }
        element.removeEventListener("touchstart", this.unlockAudioBound);
        element.removeEventListener("click", this.unlockAudioBound);
      }.bind(this)
    );
  };
  VideoElement.prototype.onClick = function(ev) {
    if (this.player.isPlaying) {
      this.player.pause();
      this.playButton.style.display = "block";
    } else {
      this.player.play();
      this.playButton.style.display = "none";
      if (this.poster) {
        this.poster.style.display = "none";
      }
    }
  };
  VideoElement.PLAY_BUTTON =
    '<svg style="max-width: 75px; max-height: 75px;" ' +
    'viewBox="0 0 200 200" alt="Play video">' +
    '<circle cx="100" cy="100" r="90" fill="none" ' +
    'stroke-width="15" stroke="#fff"/>' +
    '<polygon points="70, 55 70, 145 145, 100" fill="#fff"/>' +
    "</svg>";
  VideoElement.UNMUTE_BUTTON =
    '<svg style="max-width: 75px; max-height: 75px;" viewBox="0 0 75 75">' +
    '<polygon class="audio-speaker" stroke="none" fill="#fff" ' +
    'points="39,13 22,28 6,28 6,47 21,47 39,62 39,13"/>' +
    '<g stroke="#fff" stroke-width="5">' +
    '<path d="M 49,50 69,26"/>' +
    '<path d="M 69,50 49,26"/>' +
    "</g>" +
    "</svg>";
  return VideoElement;
})();
JSWebrtc.Player = (function() {
  "use strict";
  var Player = function(url, options) {
    this.options = options || {};
    if (!url.match(/^webrtc?:\/\//)) {
      throw "JSWebrtc just work with webrtc";
    }
    if (!this.options.video) {
      throw "VideoElement is null";
    }
    this.urlParams = JSWebrtc.ParseUrl(url);
    this.pc = null;
    this.autoplay = !!options.autoplay || false;
    this.paused = true;
    if (this.autoplay) this.options.video.muted = true;
    this.startLoading();
  };
  Player.prototype.startLoading = function() {
    var _self = this;
    if (_self.pc) {
      _self.pc.close();
    }
    _self.pc = new RTCPeerConnection(null);
    _self.pc.ontrack = function(event) {
      _self.options.video["srcObject"] = event.streams[0];
    };
    _self.pc.addTransceiver("audio", { direction: "recvonly" });
    _self.pc.addTransceiver("video", { direction: "recvonly" });
    _self.pc
      .createOffer()
      .then(function(offer) {
        return _self.pc.setLocalDescription(offer).then(function() {
          return offer;
        });
      })
      .then(function(offer) {
        return new Promise(function(resolve, reject) {
          var port = _self.urlParams.port || 1985;
          var api = _self.urlParams.user_query.play || "/rtc/v1/play/";
          if (api.lastIndexOf("/") != api.length - 1) {
            api += "/";
          }
          var url = "http://" + _self.urlParams.server + ":" + port + api;
          let isFirst = true;
          for (var key in _self.urlParams.user_query) {
            if (key != "api" && key != "play") {
              if (isFirst) {
                url += "?" + key + "=" + _self.urlParams.user_query[key];
                isFirst = false;
              } else {
                url += "&" + key + "=" + _self.urlParams.user_query[key];
              }
            }
          }
          var data = {
            api: url,
            streamurl: _self.urlParams.url,
            clientip: null,
            sdp: offer.sdp
          };
          JSWebrtc.HttpPost(url, JSON.stringify(data)).then(
            function(res) {
              resolve(res.sdp);
            },
            function(rej) {
              reject(rej);
            }
          );
        });
      })
      .then(function(answer) {
        return _self.pc.setRemoteDescription(
          new RTCSessionDescription({ type: "answer", sdp: answer })
        );
      })
      .catch(function(reason) {
        throw reason;
      });
    if (this.autoplay) {
      this.play();
    }
  };
  Player.prototype.play = function(ev) {
    if (this.animationId) {
      return;
    }
    this.animationId = requestAnimationFrame(this.update.bind(this));
    this.paused = false;
  };
  Player.prototype.pause = function(ev) {
    if (this.paused) {
      return;
    }
    cancelAnimationFrame(this.animationId);
    this.animationId = null;
    this.isPlaying = false;
    this.paused = true;
    this.options.video.pause();
    if (this.options.onPause) {
      this.options.onPause(this);
    }
  };
  Player.prototype.stop = function(ev) {
    this.pause();
  };
  Player.prototype.destroy = function() {
    this.pause();
    this.pc && this.pc.close() && this.pc.destroy();
    this.audioOut && this.audioOut.destroy();
  };
  Player.prototype.update = function() {
    this.animationId = requestAnimationFrame(this.update.bind(this));
    if (this.options.video.readyState < 4) {
      return;
    }
    if (!this.isPlaying) {
      this.isPlaying = true;
      this.options.video.play();
      if (this.options.onPlay) {
        this.options.onPlay(this);
      }
    }
  };
  return Player;
})();

2、放在 vue 项目 static 文件夹,在 index.html 中引入:

<script src="static/jswebrtc.min.js"></script>

3、完整代码:

<template>
  <div>
    <video id="webrtc" ref="webrtc" style="width:100%;"></video>
  </div>
</template>

<script>
export default {
  data() {
    return {
      player: null
    };
  },
  beforeDestroy() {
    if (this.player) {
      this.player.destroy();
      this.player = null;
    }
  },
  mounted() {
    this.$nextTick(() => {
      this.initPlayer();
    });
  },
  methods: {
    initPlayer() {
      let url = "webrtc://" + window.location.hostname + "xxx";
      let videoDom = document.getElementById('webrtc');
      // url 是一个 webrtc 开头的地址 webrtc://xxx
      this.player = new JSWebrtc.Player(url, {
        video: videoDom,// 用于播放视频的 HTML Video 元素
        autoplay: true,// 是否自动播放,默认 false
        onPlay: () => {// onPlay(player),播放后回调
          videoDom.addEventListener('canplay', function () {
            // .play() – 开始   .pause() – 暂停   .stop() – 停止
            // .destroy() – 停止播放并清理相关的播放资源  .paused – 只读,是否暂停播放
            videoDom.play();
          })
        }
        // onPause(player),暂停后回调
      })
    }
  },
};
</script>
  • 0
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值