Browse Source

增加播放功能

v4
langhuihui 4 years ago
parent
commit
854907f332
  1. 3
      go.mod
  2. 2
      go.sum
  3. 153
      main.go
  4. 328
      ui/dist/plugin-webrtc.common.js
  5. 2
      ui/dist/plugin-webrtc.common.js.map
  6. 2
      ui/dist/plugin-webrtc.css
  7. 328
      ui/dist/plugin-webrtc.umd.js
  8. 2
      ui/dist/plugin-webrtc.umd.js.map
  9. 2
      ui/dist/plugin-webrtc.umd.min.js
  10. 2
      ui/dist/plugin-webrtc.umd.min.js.map
  11. 118
      ui/src/App.vue
  12. 82
      ui/src/components/Player.vue

3
go.mod

@ -3,9 +3,8 @@ module github.com/Monibuca/plugin-webrtc
go 1.13
require (
github.com/Monibuca/engine/v2 v2.1.0
github.com/Monibuca/engine/v2 v2.1.4
github.com/Monibuca/plugin-rtp v0.0.0-20200531020026-1b12ef72f221
github.com/pion/rtcp v1.2.1
github.com/pion/rtp v1.5.4
github.com/pion/webrtc/v2 v2.2.14
)

2
go.sum

@ -2,6 +2,8 @@ github.com/BurntSushi/toml v0.3.1 h1:WXkYYl6Yr3qBf1K79EBnL4mak0OimBfB0XUf9Vl28OQ
github.com/BurntSushi/toml v0.3.1/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03qcyfWMU=
github.com/Monibuca/engine/v2 v2.1.0 h1:pHeDCEFDusKFsZLpconYj8U5LCaWApnjd+yQRHYgQsQ=
github.com/Monibuca/engine/v2 v2.1.0/go.mod h1:34EYjjV15G6myuHOKaJkO7y5tJ1Arq/NfC9Weacr2mc=
github.com/Monibuca/engine/v2 v2.1.4 h1:TZK6o/8giu4Yzd9sqntAHZkirqxMahaak/TMiMCSAKg=
github.com/Monibuca/engine/v2 v2.1.4/go.mod h1:34EYjjV15G6myuHOKaJkO7y5tJ1Arq/NfC9Weacr2mc=
github.com/Monibuca/plugin-rtp v0.0.0-20200531020026-1b12ef72f221 h1:WBC0eLB7J3PXWZiu4cr9kdcNAkR/74jf0+7zkYDzwZQ=
github.com/Monibuca/plugin-rtp v0.0.0-20200531020026-1b12ef72f221/go.mod h1:62NoacApn7++z5wQnr9ktSfn+vVZL0eSvbD/EqoSHoM=
github.com/StackExchange/wmi v0.0.0-20190523213315-cbe66965904d h1:G0m3OIz70MZUWq3EgK3CesDbo8upS2Vm9/P3FtgI+Jk=

153
main.go

@ -1,12 +1,10 @@
package webrtc
import (
"bytes"
"encoding/json"
"fmt"
"io/ioutil"
"net/http"
"os"
"sync"
"time"
@ -15,8 +13,6 @@ import (
"github.com/Monibuca/engine/v2/util"
. "github.com/Monibuca/plugin-rtp"
"github.com/pion/rtcp"
"github.com/pion/rtp"
"github.com/pion/rtp/codecs"
. "github.com/pion/webrtc/v2"
"github.com/pion/webrtc/v2/pkg/media"
)
@ -60,7 +56,13 @@ var ssrcLock sync.Mutex
var playWaitList sync.Map
func init() {
m.RegisterCodec(NewRTPH264Codec(DefaultPayloadTypeH264, 90000))
m.RegisterCodec(NewRTPCodec(RTPCodecTypeVideo,
H264,
90000,
0,
"level-asymmetry-allowed=1;packetization-mode=1;profile-level-id=42001f",
DefaultPayloadTypeH264,
new(avformat.H264)))
//m.RegisterCodec(NewRTPPCMUCodec(DefaultPayloadTypePCMU, 8000))
api = NewAPI(WithMediaEngine(m))
InstallPlugin(&PluginConfig{
@ -76,26 +78,8 @@ type WebRTC struct {
*PeerConnection
RemoteAddr string
videoTrack *Track
sequence uint16
codecs.H264Packet
*os.File
}
func (rtc *WebRTC) WriteVideo(ts uint32, marker bool, payload []byte) error {
rtc.sequence++
// bb, _ := rtc.Unmarshal(payload)
// rtc.Write(bb)
return rtc.videoTrack.WriteRTP(&rtp.Packet{
Header: rtp.Header{
Version: 2,
SSRC: SSRC,
PayloadType: DefaultPayloadTypeH264,
SequenceNumber: rtc.sequence,
Timestamp: ts,
Marker: marker,
},
Payload: payload,
})
// codecs.H264Packet
// *os.File
}
func (rtc *WebRTC) Play(streamPath string) bool {
@ -108,138 +92,43 @@ func (rtc *WebRTC) Play(streamPath string) bool {
}
case ICEConnectionStateConnected:
var sub Subscriber
var sps []byte
var pps []byte
sub.ID = rtc.RemoteAddr
sub.Type = "WebRTC"
var lastTimeStamp uint32
var dataBuilder bytes.Buffer
sub.OnData = func(packet *avformat.SendPacket) error {
if packet.Type == avformat.FLV_TAG_TYPE_AUDIO {
return nil
}
if packet.IsSequence {
payload := packet.Payload[11:]
spsLen := int(payload[0])<<8 + int(payload[1])
payload = payload[2:]
sps = payload[:spsLen]
payload = payload[1+spsLen:]
ppsLen := int(payload[0])<<8 + int(payload[1])
payload = payload[2:]
pps = payload[:ppsLen]
} else {
var s uint32
if lastTimeStamp > 0 {
s = packet.Timestamp - lastTimeStamp
}
if packet.IsKeyFrame {
dataBuilder.Write(avformat.NALU_Delimiter2)
dataBuilder.Write(sps)
dataBuilder.Write(avformat.NALU_Delimiter2)
dataBuilder.Write(pps)
rtc.videoTrack.WriteSample(media.Sample{
Data: sub.SPS,
Samples: 0,
})
rtc.videoTrack.WriteSample(media.Sample{
Data: sub.PPS,
Samples: 0,
})
}
payload := packet.Payload[5:]
for {
for payload := packet.Payload[5:]; len(payload) > 4; {
var naulLen = int(util.BigEndian.Uint32(payload))
payload = payload[4:]
dataBuilder.Write(avformat.NALU_Delimiter2)
dataBuilder.Write(payload[:naulLen])
rtc.videoTrack.WriteSample(media.Sample{
Data: dataBuilder.Bytes(),
Data: payload[:naulLen],
Samples: s * 90,
})
dataBuilder.Reset()
if len(payload) < naulLen+4 {
break
}
s = 0
payload = payload[naulLen:]
}
}
lastTimeStamp = packet.Timestamp
return nil
}
// stapA := func(naul ...[]byte) []byte {
// var buffer bytes.Buffer
// buffer.WriteByte((naul[0][0] & 224) | 24)
// for _, n := range naul {
// l := len(n)
// buffer.WriteByte(byte(l >> 8))
// buffer.WriteByte(byte(l))
// buffer.Write(n)
// }
// return buffer.Bytes()
// }
// //rtc.File, _ = os.OpenFile("webrtc.h264", os.O_CREATE|os.O_WRONLY|os.O_TRUNC, 0666)
// aud := []byte{0x09, 0x30}
// sub.OnData = func(packet *avformat.SendPacket) error {
// if packet.Type == avformat.FLV_TAG_TYPE_AUDIO {
// return nil
// }
// if packet.IsSequence {
// payload := packet.Payload[11:]
// spsLen := int(payload[0])<<8 + int(payload[1])
// sps = payload[2:spsLen]
// payload = payload[3+spsLen:]
// ppsLen := int(payload[0])<<8 + int(payload[1])
// pps = payload[2:ppsLen]
// } else {
// if packet.IsKeyFrame {
// if err := rtc.WriteVideo(packet.Timestamp*90, true, stapA([]byte{0x9, 0x10}, sps, pps)); err != nil {
// return err
// }
// } else {
// if err := rtc.WriteVideo(packet.Timestamp*90, true, aud); err != nil {
// return err
// }
// }
// payload := packet.Payload[5:]
// for {
// var naulLen = int(util.BigEndian.Uint32(payload))
// payload = payload[4:]
// _payload := payload[:naulLen]
// if naulLen > 1000 {
// indicator := (_payload[0] & 224) | 28
// nalutype := _payload[0] & 31
// header := 128 | nalutype
// part := _payload[1:1000]
// marker := false
// for {
// if err := rtc.WriteVideo(packet.Timestamp*90, marker, append([]byte{indicator, header}, part...)); err != nil {
// return err
// }
// if _payload == nil {
// break
// }
// _payload = _payload[1000:]
// if len(_payload) <= 1000 {
// header = 64 | nalutype
// part = _payload
// _payload = nil
// marker = true
// } else {
// header = nalutype
// part = _payload[:1000]
// }
// }
// } else {
// if err := rtc.WriteVideo(packet.Timestamp*90, true, _payload); err != nil {
// return err
// }
// }
// if len(payload) < naulLen+4 {
// break
// }
// payload = payload[naulLen:]
// }
// // if err := videoTrack.WriteRTP(&rtp.Packet{
// // Header: nextHeader(packet.Timestamp * 90),
// // Payload: aud,
// // }); err != nil {
// // return err
// // }
// }
// return nil
// }
go sub.Subscribe(streamPath)
}
})
@ -299,7 +188,7 @@ func (rtc *WebRTC) Publish(streamPath string) bool {
if err = pack.Unmarshal(b[:i]); err != nil {
return
}
rtc.Unmarshal(pack.Payload)
// rtc.Unmarshal(pack.Payload)
// f.Write(bytes)
}
})

328
ui/dist/plugin-webrtc.common.js

@ -87,18 +87,7 @@ module.exports =
/************************************************************************/
/******/ ({
/***/ "11a1":
/***/ (function(module, __webpack_exports__, __webpack_require__) {
"use strict";
/* harmony import */ var _node_modules_mini_css_extract_plugin_dist_loader_js_ref_6_oneOf_1_0_node_modules_css_loader_dist_cjs_js_ref_6_oneOf_1_1_node_modules_vue_loader_lib_loaders_stylePostLoader_js_node_modules_postcss_loader_src_index_js_ref_6_oneOf_1_2_node_modules_cache_loader_dist_cjs_js_ref_0_0_node_modules_vue_loader_lib_index_js_vue_loader_options_App_vue_vue_type_style_index_0_id_09aaef78_scoped_true_lang_css___WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__("30b5");
/* harmony import */ var _node_modules_mini_css_extract_plugin_dist_loader_js_ref_6_oneOf_1_0_node_modules_css_loader_dist_cjs_js_ref_6_oneOf_1_1_node_modules_vue_loader_lib_loaders_stylePostLoader_js_node_modules_postcss_loader_src_index_js_ref_6_oneOf_1_2_node_modules_cache_loader_dist_cjs_js_ref_0_0_node_modules_vue_loader_lib_index_js_vue_loader_options_App_vue_vue_type_style_index_0_id_09aaef78_scoped_true_lang_css___WEBPACK_IMPORTED_MODULE_0___default = /*#__PURE__*/__webpack_require__.n(_node_modules_mini_css_extract_plugin_dist_loader_js_ref_6_oneOf_1_0_node_modules_css_loader_dist_cjs_js_ref_6_oneOf_1_1_node_modules_vue_loader_lib_loaders_stylePostLoader_js_node_modules_postcss_loader_src_index_js_ref_6_oneOf_1_2_node_modules_cache_loader_dist_cjs_js_ref_0_0_node_modules_vue_loader_lib_index_js_vue_loader_options_App_vue_vue_type_style_index_0_id_09aaef78_scoped_true_lang_css___WEBPACK_IMPORTED_MODULE_0__);
/* unused harmony reexport * */
/* unused harmony default export */ var _unused_webpack_default_export = (_node_modules_mini_css_extract_plugin_dist_loader_js_ref_6_oneOf_1_0_node_modules_css_loader_dist_cjs_js_ref_6_oneOf_1_1_node_modules_vue_loader_lib_loaders_stylePostLoader_js_node_modules_postcss_loader_src_index_js_ref_6_oneOf_1_2_node_modules_cache_loader_dist_cjs_js_ref_0_0_node_modules_vue_loader_lib_index_js_vue_loader_options_App_vue_vue_type_style_index_0_id_09aaef78_scoped_true_lang_css___WEBPACK_IMPORTED_MODULE_0___default.a);
/***/ }),
/***/ "30b5":
/***/ "3f2c":
/***/ (function(module, exports, __webpack_require__) {
// extracted by mini-css-extract-plugin
@ -181,6 +170,17 @@ var __WEBPACK_AMD_DEFINE_FACTORY__, __WEBPACK_AMD_DEFINE_ARRAY__, __WEBPACK_AMD_
}));
/***/ }),
/***/ "b2e7":
/***/ (function(module, __webpack_exports__, __webpack_require__) {
"use strict";
/* harmony import */ var _node_modules_mini_css_extract_plugin_dist_loader_js_ref_6_oneOf_1_0_node_modules_css_loader_dist_cjs_js_ref_6_oneOf_1_1_node_modules_vue_loader_lib_loaders_stylePostLoader_js_node_modules_postcss_loader_src_index_js_ref_6_oneOf_1_2_node_modules_cache_loader_dist_cjs_js_ref_0_0_node_modules_vue_loader_lib_index_js_vue_loader_options_App_vue_vue_type_style_index_0_id_b8166bc0_scoped_true_lang_css___WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__("3f2c");
/* harmony import */ var _node_modules_mini_css_extract_plugin_dist_loader_js_ref_6_oneOf_1_0_node_modules_css_loader_dist_cjs_js_ref_6_oneOf_1_1_node_modules_vue_loader_lib_loaders_stylePostLoader_js_node_modules_postcss_loader_src_index_js_ref_6_oneOf_1_2_node_modules_cache_loader_dist_cjs_js_ref_0_0_node_modules_vue_loader_lib_index_js_vue_loader_options_App_vue_vue_type_style_index_0_id_b8166bc0_scoped_true_lang_css___WEBPACK_IMPORTED_MODULE_0___default = /*#__PURE__*/__webpack_require__.n(_node_modules_mini_css_extract_plugin_dist_loader_js_ref_6_oneOf_1_0_node_modules_css_loader_dist_cjs_js_ref_6_oneOf_1_1_node_modules_vue_loader_lib_loaders_stylePostLoader_js_node_modules_postcss_loader_src_index_js_ref_6_oneOf_1_2_node_modules_cache_loader_dist_cjs_js_ref_0_0_node_modules_vue_loader_lib_index_js_vue_loader_options_App_vue_vue_type_style_index_0_id_b8166bc0_scoped_true_lang_css___WEBPACK_IMPORTED_MODULE_0__);
/* unused harmony reexport * */
/* unused harmony default export */ var _unused_webpack_default_export = (_node_modules_mini_css_extract_plugin_dist_loader_js_ref_6_oneOf_1_0_node_modules_css_loader_dist_cjs_js_ref_6_oneOf_1_1_node_modules_vue_loader_lib_loaders_stylePostLoader_js_node_modules_postcss_loader_src_index_js_ref_6_oneOf_1_2_node_modules_cache_loader_dist_cjs_js_ref_0_0_node_modules_vue_loader_lib_index_js_vue_loader_options_App_vue_vue_type_style_index_0_id_b8166bc0_scoped_true_lang_css___WEBPACK_IMPORTED_MODULE_0___default.a);
/***/ }),
/***/ "fb15":
@ -214,15 +214,21 @@ if (typeof window !== 'undefined') {
// Indicate to webpack that this file can be concatenated
/* harmony default export */ var setPublicPath = (null);
// CONCATENATED MODULE: ./node_modules/cache-loader/dist/cjs.js?{"cacheDirectory":"node_modules/.cache/vue-loader","cacheIdentifier":"7d106341-vue-loader-template"}!./node_modules/vue-loader/lib/loaders/templateLoader.js??vue-loader-options!./node_modules/cache-loader/dist/cjs.js??ref--0-0!./node_modules/vue-loader/lib??vue-loader-options!./src/App.vue?vue&type=template&id=09aaef78&scoped=true&
var render = function () {var _vm=this;var _h=_vm.$createElement;var _c=_vm._self._c||_h;return _c('div',[(_vm.$parent.titleTabActive == 1)?_c('pre',[_vm._v(_vm._s(_vm.localSDP))]):(_vm.$parent.titleTabActive == 2)?_c('pre',[_vm._v(_vm._s(_vm.remoteSDP))]):_c('div',[_c('mu-text-field',{attrs:{"label":"streamPath"},model:{value:(_vm.streamPath),callback:function ($$v) {_vm.streamPath=$$v},expression:"streamPath"}}),(!_vm.localSDP || _vm.ask)?_c('span',{staticClass:"blink"},[_vm._v("Connecting")]):_vm._e(),[_c('m-button',{on:{"click":function($event){return _vm.startSession('publish')}}},[_vm._v("Publish")]),_c('m-button',{on:{"click":function($event){return _vm.startSession('play')}}},[_vm._v("Play")])],_c('m-button',{on:{"click":_vm.stopSession}},[_vm._v("Stop")]),_c('br'),_c('video',{ref:"video1",attrs:{"width":"640","height":"480","autoplay":"","muted":""},domProps:{"srcObject":_vm.stream,"muted":true}})],2)])}
// CONCATENATED MODULE: ./node_modules/cache-loader/dist/cjs.js?{"cacheDirectory":"node_modules/.cache/vue-loader","cacheIdentifier":"7d106341-vue-loader-template"}!./node_modules/vue-loader/lib/loaders/templateLoader.js??vue-loader-options!./node_modules/cache-loader/dist/cjs.js??ref--0-0!./node_modules/vue-loader/lib??vue-loader-options!./src/App.vue?vue&type=template&id=b8166bc0&scoped=true&
var render = function () {var _vm=this;var _h=_vm.$createElement;var _c=_vm._self._c||_h;return _c('div',[(_vm.$parent.titleTabActive == 0)?_c('div',[_c('mu-text-field',{attrs:{"label":"streamPath"},model:{value:(_vm.streamPath),callback:function ($$v) {_vm.streamPath=$$v},expression:"streamPath"}}),(!_vm.remoteSDP)?_c('m-button',{on:{"click":_vm.publish}},[_vm._v("Publish")]):_c('m-button',{on:{"click":_vm.stopSession}},[_vm._v("Stop")]),(_vm.remoteSDP)?_c('a',{attrs:{"href":_vm.remoteSDPURL,"download":"remoteSDP.txt"}},[_vm._v("remoteSDP")]):_vm._e(),_c('span'),(_vm.localSDP)?_c('a',{attrs:{"href":_vm.localSDPURL,"download":"localSDP.txt"}},[_vm._v("localSDP")]):_vm._e(),_c('br'),_c('video',{ref:"video1",attrs:{"width":"640","height":"480","autoplay":"","muted":""},domProps:{"srcObject":_vm.stream,"muted":true}})],1):(_vm.$parent.titleTabActive == 1)?_c('stream-table',{scopedSlots:_vm._u([{key:"default",fn:function(scope){return [_c('m-button',{on:{"click":function($event){return _vm.preview(scope)}}},[_vm._v("Play")]),void 0]}}])}):(_vm.$parent.titleTabActive == 2)?_c('pre',[_vm._v(_vm._s(_vm.localSDP))]):(_vm.$parent.titleTabActive == 3)?_c('pre',[_vm._v(_vm._s(_vm.remoteSDP))]):_vm._e(),_c('webrtc-player',{ref:"player",model:{value:(_vm.previewStreamPath),callback:function ($$v) {_vm.previewStreamPath=$$v},expression:"previewStreamPath"}})],1)}
var staticRenderFns = []
// CONCATENATED MODULE: ./src/App.vue?vue&type=template&id=09aaef78&scoped=true&
// CONCATENATED MODULE: ./src/App.vue?vue&type=template&id=b8166bc0&scoped=true&
// CONCATENATED MODULE: ./node_modules/cache-loader/dist/cjs.js??ref--0-0!./node_modules/vue-loader/lib??vue-loader-options!./src/App.vue?vue&type=script&lang=js&
//
// CONCATENATED MODULE: ./node_modules/cache-loader/dist/cjs.js?{"cacheDirectory":"node_modules/.cache/vue-loader","cacheIdentifier":"7d106341-vue-loader-template"}!./node_modules/vue-loader/lib/loaders/templateLoader.js??vue-loader-options!./node_modules/cache-loader/dist/cjs.js??ref--0-0!./node_modules/vue-loader/lib??vue-loader-options!./src/components/Player.vue?vue&type=template&id=213e71c4&
var Playervue_type_template_id_213e71c4_render = function () {var _vm=this;var _h=_vm.$createElement;var _c=_vm._self._c||_h;return _c('Modal',_vm._g(_vm._b({attrs:{"draggable":"","title":_vm.streamPath},on:{"on-ok":_vm.onClosePreview,"on-cancel":_vm.onClosePreview}},'Modal',_vm.$attrs,false),_vm.$listeners),[_c('video',{ref:"webrtc",attrs:{"width":"488","height":"275","autoplay":"","muted":"","controls":""},domProps:{"srcObject":_vm.stream,"muted":true}}),_c('div',{attrs:{"slot":"footer"},slot:"footer"},[(_vm.remoteSDP)?_c('a',{attrs:{"href":_vm.remoteSDPURL,"download":"remoteSDP.txt"}},[_vm._v("remoteSDP")]):_vm._e(),_c('span'),(_vm.localSDP)?_c('a',{attrs:{"href":_vm.localSDPURL,"download":"localSDP.txt"}},[_vm._v("localSDP")]):_vm._e()])])}
var Playervue_type_template_id_213e71c4_staticRenderFns = []
// CONCATENATED MODULE: ./src/components/Player.vue?vue&type=template&id=213e71c4&
// CONCATENATED MODULE: ./node_modules/cache-loader/dist/cjs.js??ref--0-0!./node_modules/vue-loader/lib??vue-loader-options!./src/components/Player.vue?vue&type=script&lang=js&
//
//
//
@ -241,135 +247,72 @@ var staticRenderFns = []
//
//
const config = {
iceServers: [
// {
// urls:[
// "stun:stun.ekiga.net",
// "stun:stun.ideasip.com",
// "stun:stun.schlund.de",
// "stun:stun.stunprotocol.org:3478",
// "stun:stun.voiparound.com",
// "stun:stun.voipbuster.com",
// "stun:stun.voipstunt.com",
// "stun:stun.voxgratia.org",
// "stun:stun.services.mozilla.com",
// "stun:stun.xten.com",
// "stun:stun.softjoys.com",
// "stun:stunserver.org",
// "stun:stun.schlund.de",
// "stun:stun.rixtelecom.se",
// "stun:stun.iptel.org",
// "stun:stun.ideasip.com",
// "stun:stun.fwdnet.net",
// "stun:stun.ekiga.net",
// "stun:stun01.sipphone.com",
// ]
// }
]
};
let pc = new RTCPeerConnection(config);
var stream = null;
var streamPath = "live/rtc";
/* harmony default export */ var Appvue_type_script_lang_js_ = ({
let pc = null
/* harmony default export */ var Playervue_type_script_lang_js_ = ({
data() {
return {
localSDP: pc && pc.localDescription && pc.localDescription.sdp,
remoteSDP: pc && pc.remoteDescription && pc.remoteDescription.sdp,
streamPath,
iceConnectionState: pc && pc.iceConnectionState,
stream,
type: "",
ask: false
stream: null,
localSDP: "",
remoteSDP: "",
remoteSDPURL: "",
localSDPURL: "",
streamPath: ""
};
},
methods: {
async startSession(type) {
this.type = type;
this.ask = true;
if (type == "play") {
const result = await this.ajax({
url: "/webrtc/preparePlay?streamPath=" + this.streamPath,
dataType: "json"
});
if (result.errmsg) {
this.$toast.error(result.errmsg);
return;
} else {
streamPath = this.streamPath;
this.remoteSDP = result.sdp;
}
pc.ontrack = event => {
console.log(event)
if (event.streams[0].id == "monibuca")
this.stream = stream = event.streams[0];
};
await pc.setRemoteDescription(
new RTCSessionDescription(result)
);
await pc.setLocalDescription(await pc.createAnswer());
this.localSDP = pc.localDescription.sdp;
async play(streamPath) {
pc = new RTCPeerConnection();
this.streamPath = streamPath;
pc.onsignalingstatechange = e => {
console.log(e);
};
pc.oniceconnectionstatechange = e => {
this.$toast.info(pc.iceConnectionState);
this.iceConnectionState = pc.iceConnectionState;
};
pc.onicecandidate = event => {};
const result = await this.ajax({
url: "/webrtc/preparePlay?streamPath=" + this.streamPath,
dataType: "json"
});
if (result.errmsg) {
this.$toast.error(result.errmsg);
return;
} else {
pc.addStream(stream);
await pc.setLocalDescription(await pc.createOffer());
this.localSDP = pc.localDescription.sdp;
this.remoteSDP = result.sdp;
this.remoteSDPURL = URL.createObjectURL(new Blob([this.remoteSDP], { type: "text/plain" }));
}
const result = await this.ajax({
pc.ontrack = event => {
console.log(event);
if (event.streams[0].id == "monibuca")
this.stream = event.streams[0];
};
await pc.setRemoteDescription(new RTCSessionDescription(result));
await pc.setLocalDescription(await pc.createAnswer());
this.localSDP = pc.localDescription.sdp;
this.localSDPURL = URL.createObjectURL(
new Blob([this.localSDP], { type: "text/plain" })
);
result = await this.ajax({
type: "POST",
processData: false,
data: JSON.stringify(pc.localDescription),
url: "/webrtc/" + type + "?streamPath=" + this.streamPath,
url: "/webrtc/play?streamPath=" + this.streamPath,
dataType: "json"
});
this.ask = false;
if (result!="success") {
this.$toast.error(result.errmsg||result);
return;
} else {
streamPath = this.streamPath;
}
if (type == "play") {
} else {
this.remoteSDP = result.sdp;
pc.setRemoteDescription(new RTCSessionDescription(result));
if (result != "success") {
this.$toast.error(result.errmsg || result);
}
},
stopSession() {
onClosePreview() {
pc.close();
pc = new RTCPeerConnection(config);
this.remoteSDP = "";
this.localSDP = "";
this.type = "";
// this.connectICE().catch(err => this.$toast.error(err.message));
}
},
async mounted() {
pc.onsignalingstatechange = e => {
console.log(e);
};
pc.oniceconnectionstatechange = e => {
this.$toast.info(pc.iceConnectionState);
this.iceConnectionState = pc.iceConnectionState;
};
pc.onicecandidate = event => {};
this.$parent.titleTabs = ["摄像头", "localSDP", "remoteSDP"];
try {
if (!this.stream)
this.stream = stream = await navigator.mediaDevices.getUserMedia(
{ video: true, audio: true }
);
} catch (err) {
this.$toast.error(err.message);
}
}
});
// CONCATENATED MODULE: ./src/App.vue?vue&type=script&lang=js&
/* harmony default export */ var src_Appvue_type_script_lang_js_ = (Appvue_type_script_lang_js_);
// EXTERNAL MODULE: ./src/App.vue?vue&type=style&index=0&id=09aaef78&scoped=true&lang=css&
var Appvue_type_style_index_0_id_09aaef78_scoped_true_lang_css_ = __webpack_require__("11a1");
// CONCATENATED MODULE: ./src/components/Player.vue?vue&type=script&lang=js&
/* harmony default export */ var components_Playervue_type_script_lang_js_ = (Playervue_type_script_lang_js_);
// CONCATENATED MODULE: ./node_modules/vue-loader/lib/runtime/componentNormalizer.js
/* globals __VUE_SSR_CONTEXT__ */
@ -470,6 +413,133 @@ function normalizeComponent (
}
}
// CONCATENATED MODULE: ./src/components/Player.vue
/* normalize component */
var component = normalizeComponent(
components_Playervue_type_script_lang_js_,
Playervue_type_template_id_213e71c4_render,
Playervue_type_template_id_213e71c4_staticRenderFns,
false,
null,
null,
null
)
/* harmony default export */ var Player = (component.exports);
// CONCATENATED MODULE: ./node_modules/cache-loader/dist/cjs.js??ref--0-0!./node_modules/vue-loader/lib??vue-loader-options!./src/App.vue?vue&type=script&lang=js&
//
//
//
//
//
//
//
//
//
//
//
//
//
//
//
//
//
//
//
//
//
//
//
const config = { iceServers: []};
let Appvue_type_script_lang_js_pc = new RTCPeerConnection(config);
var stream = null
var streamPath = "live/rtc";
/* harmony default export */ var Appvue_type_script_lang_js_ = ({
components:{
WebrtcPlayer: Player
},
data() {
return {
localSDP: Appvue_type_script_lang_js_pc && Appvue_type_script_lang_js_pc.localDescription && Appvue_type_script_lang_js_pc.localDescription.sdp,
remoteSDP: Appvue_type_script_lang_js_pc && Appvue_type_script_lang_js_pc.remoteDescription && Appvue_type_script_lang_js_pc.remoteDescription.sdp,
streamPath,
iceConnectionState: Appvue_type_script_lang_js_pc && Appvue_type_script_lang_js_pc.iceConnectionState,
stream,
previewStreamPath:false,
localSDPURL:"",
remoteSDPURL:""
};
},
methods: {
async publish() {
Appvue_type_script_lang_js_pc.addStream(stream);
await Appvue_type_script_lang_js_pc.setLocalDescription(await Appvue_type_script_lang_js_pc.createOffer());
this.localSDP = Appvue_type_script_lang_js_pc.localDescription.sdp;
this.localSDPURL = URL.createObjectURL(new Blob([ this.localSDP ],{type:'text/plain'}))
const result = await this.ajax({
type: "POST",
processData: false,
data: JSON.stringify(Appvue_type_script_lang_js_pc.localDescription),
url: "/webrtc/publish?streamPath=" + this.streamPath,
dataType: "json"
});
if (result!="success") {
this.$toast.error(result.errmsg||result);
return;
} else {
streamPath = this.streamPath;
}
this.remoteSDP = result.sdp;
this.remoteSDPURL = URL.createObjectURL(new Blob([ this.remoteSDP ],{type:'text/plain'}))
Appvue_type_script_lang_js_pc.setRemoteDescription(new RTCSessionDescription(result));
},
stopSession() {
Appvue_type_script_lang_js_pc.close();
Appvue_type_script_lang_js_pc = new RTCPeerConnection(config);
this.remoteSDP = "";
this.localSDP = "";
// this.connectICE().catch(err => this.$toast.error(err.message));
},
preview({row}) {
this.previewStreamPath = true
this.$nextTick(() =>this.$refs.player.play(row.StreamPath));
},
},
async mounted() {
Appvue_type_script_lang_js_pc.onsignalingstatechange = e => {
console.log(e);
};
Appvue_type_script_lang_js_pc.oniceconnectionstatechange = e => {
this.$toast.info(Appvue_type_script_lang_js_pc.iceConnectionState);
this.iceConnectionState = Appvue_type_script_lang_js_pc.iceConnectionState;
};
Appvue_type_script_lang_js_pc.onicecandidate = event => {};
this.$parent.titleTabs = ["publish","play"];
try {
if (!this.stream)
this.stream = stream = await navigator.mediaDevices.getUserMedia(
{ video: true, audio: true }
);
} catch (err) {
this.$toast.error(err.message);
}
}
});
// CONCATENATED MODULE: ./src/App.vue?vue&type=script&lang=js&
/* harmony default export */ var src_Appvue_type_script_lang_js_ = (Appvue_type_script_lang_js_);
// EXTERNAL MODULE: ./src/App.vue?vue&type=style&index=0&id=b8166bc0&scoped=true&lang=css&
var Appvue_type_style_index_0_id_b8166bc0_scoped_true_lang_css_ = __webpack_require__("b2e7");
// CONCATENATED MODULE: ./src/App.vue
@ -479,18 +549,18 @@ function normalizeComponent (
/* normalize component */
var component = normalizeComponent(
var App_component = normalizeComponent(
src_Appvue_type_script_lang_js_,
render,
staticRenderFns,
false,
null,
"09aaef78",
"b8166bc0",
null
)
/* harmony default export */ var App = (component.exports);
/* harmony default export */ var App = (App_component.exports);
// CONCATENATED MODULE: ./node_modules/@vue/cli-service/lib/commands/build/entry-lib.js

2
ui/dist/plugin-webrtc.common.js.map

File diff suppressed because one or more lines are too long

2
ui/dist/plugin-webrtc.css

@ -1 +1 @@
@-webkit-keyframes blink-data-v-09aaef78{0%{opacity:.2}50%{opacity:1}to{opacity:.2}}@keyframes blink-data-v-09aaef78{0%{opacity:.2}50%{opacity:1}to{opacity:.2}}.blink[data-v-09aaef78]{-webkit-animation:blink-data-v-09aaef78 1s infinite;animation:blink-data-v-09aaef78 1s infinite}
@-webkit-keyframes blink-data-v-b8166bc0{0%{opacity:.2}50%{opacity:1}to{opacity:.2}}@keyframes blink-data-v-b8166bc0{0%{opacity:.2}50%{opacity:1}to{opacity:.2}}.blink[data-v-b8166bc0]{-webkit-animation:blink-data-v-b8166bc0 1s infinite;animation:blink-data-v-b8166bc0 1s infinite}

328
ui/dist/plugin-webrtc.umd.js

@ -96,18 +96,7 @@ return /******/ (function(modules) { // webpackBootstrap
/************************************************************************/
/******/ ({
/***/ "11a1":
/***/ (function(module, __webpack_exports__, __webpack_require__) {
"use strict";
/* harmony import */ var _node_modules_mini_css_extract_plugin_dist_loader_js_ref_6_oneOf_1_0_node_modules_css_loader_dist_cjs_js_ref_6_oneOf_1_1_node_modules_vue_loader_lib_loaders_stylePostLoader_js_node_modules_postcss_loader_src_index_js_ref_6_oneOf_1_2_node_modules_cache_loader_dist_cjs_js_ref_0_0_node_modules_vue_loader_lib_index_js_vue_loader_options_App_vue_vue_type_style_index_0_id_09aaef78_scoped_true_lang_css___WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__("30b5");
/* harmony import */ var _node_modules_mini_css_extract_plugin_dist_loader_js_ref_6_oneOf_1_0_node_modules_css_loader_dist_cjs_js_ref_6_oneOf_1_1_node_modules_vue_loader_lib_loaders_stylePostLoader_js_node_modules_postcss_loader_src_index_js_ref_6_oneOf_1_2_node_modules_cache_loader_dist_cjs_js_ref_0_0_node_modules_vue_loader_lib_index_js_vue_loader_options_App_vue_vue_type_style_index_0_id_09aaef78_scoped_true_lang_css___WEBPACK_IMPORTED_MODULE_0___default = /*#__PURE__*/__webpack_require__.n(_node_modules_mini_css_extract_plugin_dist_loader_js_ref_6_oneOf_1_0_node_modules_css_loader_dist_cjs_js_ref_6_oneOf_1_1_node_modules_vue_loader_lib_loaders_stylePostLoader_js_node_modules_postcss_loader_src_index_js_ref_6_oneOf_1_2_node_modules_cache_loader_dist_cjs_js_ref_0_0_node_modules_vue_loader_lib_index_js_vue_loader_options_App_vue_vue_type_style_index_0_id_09aaef78_scoped_true_lang_css___WEBPACK_IMPORTED_MODULE_0__);
/* unused harmony reexport * */
/* unused harmony default export */ var _unused_webpack_default_export = (_node_modules_mini_css_extract_plugin_dist_loader_js_ref_6_oneOf_1_0_node_modules_css_loader_dist_cjs_js_ref_6_oneOf_1_1_node_modules_vue_loader_lib_loaders_stylePostLoader_js_node_modules_postcss_loader_src_index_js_ref_6_oneOf_1_2_node_modules_cache_loader_dist_cjs_js_ref_0_0_node_modules_vue_loader_lib_index_js_vue_loader_options_App_vue_vue_type_style_index_0_id_09aaef78_scoped_true_lang_css___WEBPACK_IMPORTED_MODULE_0___default.a);
/***/ }),
/***/ "30b5":
/***/ "3f2c":
/***/ (function(module, exports, __webpack_require__) {
// extracted by mini-css-extract-plugin
@ -190,6 +179,17 @@ var __WEBPACK_AMD_DEFINE_FACTORY__, __WEBPACK_AMD_DEFINE_ARRAY__, __WEBPACK_AMD_
}));
/***/ }),
/***/ "b2e7":
/***/ (function(module, __webpack_exports__, __webpack_require__) {
"use strict";
/* harmony import */ var _node_modules_mini_css_extract_plugin_dist_loader_js_ref_6_oneOf_1_0_node_modules_css_loader_dist_cjs_js_ref_6_oneOf_1_1_node_modules_vue_loader_lib_loaders_stylePostLoader_js_node_modules_postcss_loader_src_index_js_ref_6_oneOf_1_2_node_modules_cache_loader_dist_cjs_js_ref_0_0_node_modules_vue_loader_lib_index_js_vue_loader_options_App_vue_vue_type_style_index_0_id_b8166bc0_scoped_true_lang_css___WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__("3f2c");
/* harmony import */ var _node_modules_mini_css_extract_plugin_dist_loader_js_ref_6_oneOf_1_0_node_modules_css_loader_dist_cjs_js_ref_6_oneOf_1_1_node_modules_vue_loader_lib_loaders_stylePostLoader_js_node_modules_postcss_loader_src_index_js_ref_6_oneOf_1_2_node_modules_cache_loader_dist_cjs_js_ref_0_0_node_modules_vue_loader_lib_index_js_vue_loader_options_App_vue_vue_type_style_index_0_id_b8166bc0_scoped_true_lang_css___WEBPACK_IMPORTED_MODULE_0___default = /*#__PURE__*/__webpack_require__.n(_node_modules_mini_css_extract_plugin_dist_loader_js_ref_6_oneOf_1_0_node_modules_css_loader_dist_cjs_js_ref_6_oneOf_1_1_node_modules_vue_loader_lib_loaders_stylePostLoader_js_node_modules_postcss_loader_src_index_js_ref_6_oneOf_1_2_node_modules_cache_loader_dist_cjs_js_ref_0_0_node_modules_vue_loader_lib_index_js_vue_loader_options_App_vue_vue_type_style_index_0_id_b8166bc0_scoped_true_lang_css___WEBPACK_IMPORTED_MODULE_0__);
/* unused harmony reexport * */
/* unused harmony default export */ var _unused_webpack_default_export = (_node_modules_mini_css_extract_plugin_dist_loader_js_ref_6_oneOf_1_0_node_modules_css_loader_dist_cjs_js_ref_6_oneOf_1_1_node_modules_vue_loader_lib_loaders_stylePostLoader_js_node_modules_postcss_loader_src_index_js_ref_6_oneOf_1_2_node_modules_cache_loader_dist_cjs_js_ref_0_0_node_modules_vue_loader_lib_index_js_vue_loader_options_App_vue_vue_type_style_index_0_id_b8166bc0_scoped_true_lang_css___WEBPACK_IMPORTED_MODULE_0___default.a);
/***/ }),
/***/ "fb15":
@ -223,15 +223,21 @@ if (typeof window !== 'undefined') {
// Indicate to webpack that this file can be concatenated
/* harmony default export */ var setPublicPath = (null);
// CONCATENATED MODULE: ./node_modules/cache-loader/dist/cjs.js?{"cacheDirectory":"node_modules/.cache/vue-loader","cacheIdentifier":"7d106341-vue-loader-template"}!./node_modules/vue-loader/lib/loaders/templateLoader.js??vue-loader-options!./node_modules/cache-loader/dist/cjs.js??ref--0-0!./node_modules/vue-loader/lib??vue-loader-options!./src/App.vue?vue&type=template&id=09aaef78&scoped=true&
var render = function () {var _vm=this;var _h=_vm.$createElement;var _c=_vm._self._c||_h;return _c('div',[(_vm.$parent.titleTabActive == 1)?_c('pre',[_vm._v(_vm._s(_vm.localSDP))]):(_vm.$parent.titleTabActive == 2)?_c('pre',[_vm._v(_vm._s(_vm.remoteSDP))]):_c('div',[_c('mu-text-field',{attrs:{"label":"streamPath"},model:{value:(_vm.streamPath),callback:function ($$v) {_vm.streamPath=$$v},expression:"streamPath"}}),(!_vm.localSDP || _vm.ask)?_c('span',{staticClass:"blink"},[_vm._v("Connecting")]):_vm._e(),[_c('m-button',{on:{"click":function($event){return _vm.startSession('publish')}}},[_vm._v("Publish")]),_c('m-button',{on:{"click":function($event){return _vm.startSession('play')}}},[_vm._v("Play")])],_c('m-button',{on:{"click":_vm.stopSession}},[_vm._v("Stop")]),_c('br'),_c('video',{ref:"video1",attrs:{"width":"640","height":"480","autoplay":"","muted":""},domProps:{"srcObject":_vm.stream,"muted":true}})],2)])}
// CONCATENATED MODULE: ./node_modules/cache-loader/dist/cjs.js?{"cacheDirectory":"node_modules/.cache/vue-loader","cacheIdentifier":"7d106341-vue-loader-template"}!./node_modules/vue-loader/lib/loaders/templateLoader.js??vue-loader-options!./node_modules/cache-loader/dist/cjs.js??ref--0-0!./node_modules/vue-loader/lib??vue-loader-options!./src/App.vue?vue&type=template&id=b8166bc0&scoped=true&
var render = function () {var _vm=this;var _h=_vm.$createElement;var _c=_vm._self._c||_h;return _c('div',[(_vm.$parent.titleTabActive == 0)?_c('div',[_c('mu-text-field',{attrs:{"label":"streamPath"},model:{value:(_vm.streamPath),callback:function ($$v) {_vm.streamPath=$$v},expression:"streamPath"}}),(!_vm.remoteSDP)?_c('m-button',{on:{"click":_vm.publish}},[_vm._v("Publish")]):_c('m-button',{on:{"click":_vm.stopSession}},[_vm._v("Stop")]),(_vm.remoteSDP)?_c('a',{attrs:{"href":_vm.remoteSDPURL,"download":"remoteSDP.txt"}},[_vm._v("remoteSDP")]):_vm._e(),_c('span'),(_vm.localSDP)?_c('a',{attrs:{"href":_vm.localSDPURL,"download":"localSDP.txt"}},[_vm._v("localSDP")]):_vm._e(),_c('br'),_c('video',{ref:"video1",attrs:{"width":"640","height":"480","autoplay":"","muted":""},domProps:{"srcObject":_vm.stream,"muted":true}})],1):(_vm.$parent.titleTabActive == 1)?_c('stream-table',{scopedSlots:_vm._u([{key:"default",fn:function(scope){return [_c('m-button',{on:{"click":function($event){return _vm.preview(scope)}}},[_vm._v("Play")]),void 0]}}])}):(_vm.$parent.titleTabActive == 2)?_c('pre',[_vm._v(_vm._s(_vm.localSDP))]):(_vm.$parent.titleTabActive == 3)?_c('pre',[_vm._v(_vm._s(_vm.remoteSDP))]):_vm._e(),_c('webrtc-player',{ref:"player",model:{value:(_vm.previewStreamPath),callback:function ($$v) {_vm.previewStreamPath=$$v},expression:"previewStreamPath"}})],1)}
var staticRenderFns = []
// CONCATENATED MODULE: ./src/App.vue?vue&type=template&id=09aaef78&scoped=true&
// CONCATENATED MODULE: ./src/App.vue?vue&type=template&id=b8166bc0&scoped=true&
// CONCATENATED MODULE: ./node_modules/cache-loader/dist/cjs.js??ref--0-0!./node_modules/vue-loader/lib??vue-loader-options!./src/App.vue?vue&type=script&lang=js&
//
// CONCATENATED MODULE: ./node_modules/cache-loader/dist/cjs.js?{"cacheDirectory":"node_modules/.cache/vue-loader","cacheIdentifier":"7d106341-vue-loader-template"}!./node_modules/vue-loader/lib/loaders/templateLoader.js??vue-loader-options!./node_modules/cache-loader/dist/cjs.js??ref--0-0!./node_modules/vue-loader/lib??vue-loader-options!./src/components/Player.vue?vue&type=template&id=213e71c4&
var Playervue_type_template_id_213e71c4_render = function () {var _vm=this;var _h=_vm.$createElement;var _c=_vm._self._c||_h;return _c('Modal',_vm._g(_vm._b({attrs:{"draggable":"","title":_vm.streamPath},on:{"on-ok":_vm.onClosePreview,"on-cancel":_vm.onClosePreview}},'Modal',_vm.$attrs,false),_vm.$listeners),[_c('video',{ref:"webrtc",attrs:{"width":"488","height":"275","autoplay":"","muted":"","controls":""},domProps:{"srcObject":_vm.stream,"muted":true}}),_c('div',{attrs:{"slot":"footer"},slot:"footer"},[(_vm.remoteSDP)?_c('a',{attrs:{"href":_vm.remoteSDPURL,"download":"remoteSDP.txt"}},[_vm._v("remoteSDP")]):_vm._e(),_c('span'),(_vm.localSDP)?_c('a',{attrs:{"href":_vm.localSDPURL,"download":"localSDP.txt"}},[_vm._v("localSDP")]):_vm._e()])])}
var Playervue_type_template_id_213e71c4_staticRenderFns = []
// CONCATENATED MODULE: ./src/components/Player.vue?vue&type=template&id=213e71c4&
// CONCATENATED MODULE: ./node_modules/cache-loader/dist/cjs.js??ref--0-0!./node_modules/vue-loader/lib??vue-loader-options!./src/components/Player.vue?vue&type=script&lang=js&
//
//
//
@ -250,135 +256,72 @@ var staticRenderFns = []
//
//
const config = {
iceServers: [
// {
// urls:[
// "stun:stun.ekiga.net",
// "stun:stun.ideasip.com",
// "stun:stun.schlund.de",
// "stun:stun.stunprotocol.org:3478",
// "stun:stun.voiparound.com",
// "stun:stun.voipbuster.com",
// "stun:stun.voipstunt.com",
// "stun:stun.voxgratia.org",
// "stun:stun.services.mozilla.com",
// "stun:stun.xten.com",
// "stun:stun.softjoys.com",
// "stun:stunserver.org",
// "stun:stun.schlund.de",
// "stun:stun.rixtelecom.se",
// "stun:stun.iptel.org",
// "stun:stun.ideasip.com",
// "stun:stun.fwdnet.net",
// "stun:stun.ekiga.net",
// "stun:stun01.sipphone.com",
// ]
// }
]
};
let pc = new RTCPeerConnection(config);
var stream = null;
var streamPath = "live/rtc";
/* harmony default export */ var Appvue_type_script_lang_js_ = ({
let pc = null
/* harmony default export */ var Playervue_type_script_lang_js_ = ({
data() {
return {
localSDP: pc && pc.localDescription && pc.localDescription.sdp,
remoteSDP: pc && pc.remoteDescription && pc.remoteDescription.sdp,
streamPath,
iceConnectionState: pc && pc.iceConnectionState,
stream,
type: "",
ask: false
stream: null,
localSDP: "",
remoteSDP: "",
remoteSDPURL: "",
localSDPURL: "",
streamPath: ""
};
},
methods: {
async startSession(type) {
this.type = type;
this.ask = true;
if (type == "play") {
const result = await this.ajax({
url: "/webrtc/preparePlay?streamPath=" + this.streamPath,
dataType: "json"
});
if (result.errmsg) {
this.$toast.error(result.errmsg);
return;
} else {
streamPath = this.streamPath;
this.remoteSDP = result.sdp;
}
pc.ontrack = event => {
console.log(event)
if (event.streams[0].id == "monibuca")
this.stream = stream = event.streams[0];
};
await pc.setRemoteDescription(
new RTCSessionDescription(result)
);
await pc.setLocalDescription(await pc.createAnswer());
this.localSDP = pc.localDescription.sdp;
async play(streamPath) {
pc = new RTCPeerConnection();
this.streamPath = streamPath;
pc.onsignalingstatechange = e => {
console.log(e);
};
pc.oniceconnectionstatechange = e => {
this.$toast.info(pc.iceConnectionState);
this.iceConnectionState = pc.iceConnectionState;
};
pc.onicecandidate = event => {};
const result = await this.ajax({
url: "/webrtc/preparePlay?streamPath=" + this.streamPath,
dataType: "json"
});
if (result.errmsg) {
this.$toast.error(result.errmsg);
return;
} else {
pc.addStream(stream);
await pc.setLocalDescription(await pc.createOffer());
this.localSDP = pc.localDescription.sdp;
this.remoteSDP = result.sdp;
this.remoteSDPURL = URL.createObjectURL(new Blob([this.remoteSDP], { type: "text/plain" }));
}
const result = await this.ajax({
pc.ontrack = event => {
console.log(event);
if (event.streams[0].id == "monibuca")
this.stream = event.streams[0];
};
await pc.setRemoteDescription(new RTCSessionDescription(result));
await pc.setLocalDescription(await pc.createAnswer());
this.localSDP = pc.localDescription.sdp;
this.localSDPURL = URL.createObjectURL(
new Blob([this.localSDP], { type: "text/plain" })
);
result = await this.ajax({
type: "POST",
processData: false,
data: JSON.stringify(pc.localDescription),
url: "/webrtc/" + type + "?streamPath=" + this.streamPath,
url: "/webrtc/play?streamPath=" + this.streamPath,
dataType: "json"
});
this.ask = false;
if (result!="success") {
this.$toast.error(result.errmsg||result);
return;
} else {
streamPath = this.streamPath;
}
if (type == "play") {
} else {
this.remoteSDP = result.sdp;
pc.setRemoteDescription(new RTCSessionDescription(result));
if (result != "success") {
this.$toast.error(result.errmsg || result);
}
},
stopSession() {
onClosePreview() {
pc.close();
pc = new RTCPeerConnection(config);
this.remoteSDP = "";
this.localSDP = "";
this.type = "";
// this.connectICE().catch(err => this.$toast.error(err.message));
}
},
async mounted() {
pc.onsignalingstatechange = e => {
console.log(e);
};
pc.oniceconnectionstatechange = e => {
this.$toast.info(pc.iceConnectionState);
this.iceConnectionState = pc.iceConnectionState;
};
pc.onicecandidate = event => {};
this.$parent.titleTabs = ["摄像头", "localSDP", "remoteSDP"];
try {
if (!this.stream)
this.stream = stream = await navigator.mediaDevices.getUserMedia(
{ video: true, audio: true }
);
} catch (err) {
this.$toast.error(err.message);
}
}
});
// CONCATENATED MODULE: ./src/App.vue?vue&type=script&lang=js&
/* harmony default export */ var src_Appvue_type_script_lang_js_ = (Appvue_type_script_lang_js_);
// EXTERNAL MODULE: ./src/App.vue?vue&type=style&index=0&id=09aaef78&scoped=true&lang=css&
var Appvue_type_style_index_0_id_09aaef78_scoped_true_lang_css_ = __webpack_require__("11a1");
// CONCATENATED MODULE: ./src/components/Player.vue?vue&type=script&lang=js&
/* harmony default export */ var components_Playervue_type_script_lang_js_ = (Playervue_type_script_lang_js_);
// CONCATENATED MODULE: ./node_modules/vue-loader/lib/runtime/componentNormalizer.js
/* globals __VUE_SSR_CONTEXT__ */
@ -479,6 +422,133 @@ function normalizeComponent (
}
}
// CONCATENATED MODULE: ./src/components/Player.vue
/* normalize component */
var component = normalizeComponent(
components_Playervue_type_script_lang_js_,
Playervue_type_template_id_213e71c4_render,
Playervue_type_template_id_213e71c4_staticRenderFns,
false,
null,
null,
null
)
/* harmony default export */ var Player = (component.exports);
// CONCATENATED MODULE: ./node_modules/cache-loader/dist/cjs.js??ref--0-0!./node_modules/vue-loader/lib??vue-loader-options!./src/App.vue?vue&type=script&lang=js&
//
//
//
//
//
//
//
//
//
//
//
//
//
//
//
//
//
//
//
//
//
//
//
const config = { iceServers: []};
let Appvue_type_script_lang_js_pc = new RTCPeerConnection(config);
var stream = null
var streamPath = "live/rtc";
/* harmony default export */ var Appvue_type_script_lang_js_ = ({
components:{
WebrtcPlayer: Player
},
data() {
return {
localSDP: Appvue_type_script_lang_js_pc && Appvue_type_script_lang_js_pc.localDescription && Appvue_type_script_lang_js_pc.localDescription.sdp,
remoteSDP: Appvue_type_script_lang_js_pc && Appvue_type_script_lang_js_pc.remoteDescription && Appvue_type_script_lang_js_pc.remoteDescription.sdp,
streamPath,
iceConnectionState: Appvue_type_script_lang_js_pc && Appvue_type_script_lang_js_pc.iceConnectionState,
stream,
previewStreamPath:false,
localSDPURL:"",
remoteSDPURL:""
};
},
methods: {
async publish() {
Appvue_type_script_lang_js_pc.addStream(stream);
await Appvue_type_script_lang_js_pc.setLocalDescription(await Appvue_type_script_lang_js_pc.createOffer());
this.localSDP = Appvue_type_script_lang_js_pc.localDescription.sdp;
this.localSDPURL = URL.createObjectURL(new Blob([ this.localSDP ],{type:'text/plain'}))
const result = await this.ajax({
type: "POST",
processData: false,
data: JSON.stringify(Appvue_type_script_lang_js_pc.localDescription),
url: "/webrtc/publish?streamPath=" + this.streamPath,
dataType: "json"
});
if (result!="success") {
this.$toast.error(result.errmsg||result);
return;
} else {
streamPath = this.streamPath;
}
this.remoteSDP = result.sdp;
this.remoteSDPURL = URL.createObjectURL(new Blob([ this.remoteSDP ],{type:'text/plain'}))
Appvue_type_script_lang_js_pc.setRemoteDescription(new RTCSessionDescription(result));
},
stopSession() {
Appvue_type_script_lang_js_pc.close();
Appvue_type_script_lang_js_pc = new RTCPeerConnection(config);
this.remoteSDP = "";
this.localSDP = "";
// this.connectICE().catch(err => this.$toast.error(err.message));
},
preview({row}) {
this.previewStreamPath = true
this.$nextTick(() =>this.$refs.player.play(row.StreamPath));
},
},
async mounted() {
Appvue_type_script_lang_js_pc.onsignalingstatechange = e => {
console.log(e);
};
Appvue_type_script_lang_js_pc.oniceconnectionstatechange = e => {
this.$toast.info(Appvue_type_script_lang_js_pc.iceConnectionState);
this.iceConnectionState = Appvue_type_script_lang_js_pc.iceConnectionState;
};
Appvue_type_script_lang_js_pc.onicecandidate = event => {};
this.$parent.titleTabs = ["publish","play"];
try {
if (!this.stream)
this.stream = stream = await navigator.mediaDevices.getUserMedia(
{ video: true, audio: true }
);
} catch (err) {
this.$toast.error(err.message);
}
}
});
// CONCATENATED MODULE: ./src/App.vue?vue&type=script&lang=js&
/* harmony default export */ var src_Appvue_type_script_lang_js_ = (Appvue_type_script_lang_js_);
// EXTERNAL MODULE: ./src/App.vue?vue&type=style&index=0&id=b8166bc0&scoped=true&lang=css&
var Appvue_type_style_index_0_id_b8166bc0_scoped_true_lang_css_ = __webpack_require__("b2e7");
// CONCATENATED MODULE: ./src/App.vue
@ -488,18 +558,18 @@ function normalizeComponent (
/* normalize component */
var component = normalizeComponent(
var App_component = normalizeComponent(
src_Appvue_type_script_lang_js_,
render,
staticRenderFns,
false,
null,
"09aaef78",
"b8166bc0",
null
)
/* harmony default export */ var App = (component.exports);
/* harmony default export */ var App = (App_component.exports);
// CONCATENATED MODULE: ./node_modules/@vue/cli-service/lib/commands/build/entry-lib.js

2
ui/dist/plugin-webrtc.umd.js.map

File diff suppressed because one or more lines are too long

2
ui/dist/plugin-webrtc.umd.min.js

File diff suppressed because one or more lines are too long

2
ui/dist/plugin-webrtc.umd.min.js.map

File diff suppressed because one or more lines are too long

118
ui/src/App.vue

@ -1,53 +1,36 @@
<template>
<div>
<pre v-if="$parent.titleTabActive == 1">{{localSDP}}</pre>
<pre v-else-if="$parent.titleTabActive == 2">{{remoteSDP}}</pre>
<div v-else>
<div v-if="$parent.titleTabActive == 0">
<mu-text-field v-model="streamPath" label="streamPath"></mu-text-field>
<span class="blink" v-if="!localSDP || ask">Connecting</span>
<template>
<m-button @click="startSession('publish')">Publish</m-button>
<m-button @click="startSession('play')">Play</m-button>
</template>
<m-button @click="stopSession">Stop</m-button>
<m-button @click="publish" v-if="!remoteSDP">Publish</m-button>
<m-button @click="stopSession" v-else>Stop</m-button>
<a v-if="remoteSDP" :href="remoteSDPURL" download="remoteSDP.txt">remoteSDP</a>
<span>&nbsp;&nbsp;</span>
<a v-if="localSDP" :href="localSDPURL" download="localSDP.txt">localSDP</a>
<br />
<video ref="video1" :srcObject.prop="stream" width="640" height="480" autoplay muted></video>
</div>
<stream-table v-else-if="$parent.titleTabActive == 1">
<template v-slot="scope">
<m-button @click="preview(scope)">Play</m-button>
<template>
</stream-table>
<pre v-else-if="$parent.titleTabActive == 2">{{localSDP}}</pre>
<pre v-else-if="$parent.titleTabActive == 3">{{remoteSDP}}</pre>
<webrtc-player ref="player" v-model="previewStreamPath"></webrtc-player>
</div>
</template>
<script>
const config = {
iceServers: [
// {
// urls:[
// "stun:stun.ekiga.net",
// "stun:stun.ideasip.com",
// "stun:stun.schlund.de",
// "stun:stun.stunprotocol.org:3478",
// "stun:stun.voiparound.com",
// "stun:stun.voipbuster.com",
// "stun:stun.voipstunt.com",
// "stun:stun.voxgratia.org",
// "stun:stun.services.mozilla.com",
// "stun:stun.xten.com",
// "stun:stun.softjoys.com",
// "stun:stunserver.org",
// "stun:stun.schlund.de",
// "stun:stun.rixtelecom.se",
// "stun:stun.iptel.org",
// "stun:stun.ideasip.com",
// "stun:stun.fwdnet.net",
// "stun:stun.ekiga.net",
// "stun:stun01.sipphone.com",
// ]
// }
]
};
import WebrtcPlayer from "./components/Player"
const config = { iceServers: []};
let pc = new RTCPeerConnection(config);
var stream = null;
var stream = null
var streamPath = "live/rtc";
export default {
components:{
WebrtcPlayer
},
data() {
return {
localSDP: pc && pc.localDescription && pc.localDescription.sdp,
@ -55,70 +38,45 @@ export default {
streamPath,
iceConnectionState: pc && pc.iceConnectionState,
stream,
type: "",
ask: false
previewStreamPath:false,
localSDPURL:"",
remoteSDPURL:""
};
},
methods: {
async startSession(type) {
this.type = type;
this.ask = true;
if (type == "play") {
const result = await this.ajax({
url: "/webrtc/preparePlay?streamPath=" + this.streamPath,
dataType: "json"
});
if (result.errmsg) {
this.$toast.error(result.errmsg);
return;
} else {
streamPath = this.streamPath;
this.remoteSDP = result.sdp;
}
pc.ontrack = event => {
console.log(event)
if (event.streams[0].id == "monibuca")
this.stream = stream = event.streams[0];
};
await pc.setRemoteDescription(
new RTCSessionDescription(result)
);
await pc.setLocalDescription(await pc.createAnswer());
this.localSDP = pc.localDescription.sdp;
} else {
pc.addStream(stream);
await pc.setLocalDescription(await pc.createOffer());
this.localSDP = pc.localDescription.sdp;
}
async publish() {
pc.addStream(stream);
await pc.setLocalDescription(await pc.createOffer());
this.localSDP = pc.localDescription.sdp;
this.localSDPURL = URL.createObjectURL(new Blob([ this.localSDP ],{type:'text/plain'}))
const result = await this.ajax({
type: "POST",
processData: false,
data: JSON.stringify(pc.localDescription),
url: "/webrtc/" + type + "?streamPath=" + this.streamPath,
url: "/webrtc/publish?streamPath=" + this.streamPath,
dataType: "json"
});
this.ask = false;
if (result!="success") {
this.$toast.error(result.errmsg||result);
return;
} else {
streamPath = this.streamPath;
}
if (type == "play") {
} else {
this.remoteSDP = result.sdp;
pc.setRemoteDescription(new RTCSessionDescription(result));
}
this.remoteSDP = result.sdp;
this.remoteSDPURL = URL.createObjectURL(new Blob([ this.remoteSDP ],{type:'text/plain'}))
pc.setRemoteDescription(new RTCSessionDescription(result));
},
stopSession() {
pc.close();
pc = new RTCPeerConnection(config);
this.remoteSDP = "";
this.localSDP = "";
this.type = "";
// this.connectICE().catch(err => this.$toast.error(err.message));
}
},
preview({row}) {
this.previewStreamPath = true
this.$nextTick(() =>this.$refs.player.play(row.StreamPath));
},
},
async mounted() {
pc.onsignalingstatechange = e => {
@ -129,7 +87,7 @@ export default {
this.iceConnectionState = pc.iceConnectionState;
};
pc.onicecandidate = event => {};
this.$parent.titleTabs = ["摄像头", "localSDP", "remoteSDP"];
this.$parent.titleTabs = ["publish","play"];
try {
if (!this.stream)
this.stream = stream = await navigator.mediaDevices.getUserMedia(

82
ui/src/components/Player.vue

@ -0,0 +1,82 @@
<template>
<Modal
v-bind="$attrs"
draggable
v-on="$listeners"
:title="streamPath"
@on-ok="onClosePreview"
@on-cancel="onClosePreview"
>
<video ref="webrtc" :srcObject.prop="stream" width="488" height="275" autoplay muted controls></video>
<div slot="footer">
<a v-if="remoteSDP" :href="remoteSDPURL" download="remoteSDP.txt">remoteSDP</a>
<span>&nbsp;&nbsp;</span>
<a v-if="localSDP" :href="localSDPURL" download="localSDP.txt">localSDP</a>
</div>
</Modal>
</template>
<script>
let pc = null
export default {
data() {
return {
iceConnectionState: pc && pc.iceConnectionState,
stream: null,
localSDP: "",
remoteSDP: "",
remoteSDPURL: "",
localSDPURL: "",
streamPath: ""
};
},
methods: {
async play(streamPath) {
pc = new RTCPeerConnection();
this.streamPath = streamPath;
pc.onsignalingstatechange = e => {
console.log(e);
};
pc.oniceconnectionstatechange = e => {
this.$toast.info(pc.iceConnectionState);
this.iceConnectionState = pc.iceConnectionState;
};
pc.onicecandidate = event => {};
const result = await this.ajax({
url: "/webrtc/preparePlay?streamPath=" + this.streamPath,
dataType: "json"
});
if (result.errmsg) {
this.$toast.error(result.errmsg);
return;
} else {
this.remoteSDP = result.sdp;
this.remoteSDPURL = URL.createObjectURL(new Blob([this.remoteSDP], { type: "text/plain" }));
}
pc.ontrack = event => {
console.log(event);
if (event.streams[0].id == "monibuca")
this.stream = event.streams[0];
};
await pc.setRemoteDescription(new RTCSessionDescription(result));
await pc.setLocalDescription(await pc.createAnswer());
this.localSDP = pc.localDescription.sdp;
this.localSDPURL = URL.createObjectURL(
new Blob([this.localSDP], { type: "text/plain" })
);
result = await this.ajax({
type: "POST",
processData: false,
data: JSON.stringify(pc.localDescription),
url: "/webrtc/play?streamPath=" + this.streamPath,
dataType: "json"
});
if (result != "success") {
this.$toast.error(result.errmsg || result);
}
},
onClosePreview() {
pc.close();
}
}
};
</script>
Loading…
Cancel
Save