开发播放功能

This commit is contained in:
langhuihui
2020-06-30 07:27:26 +08:00
parent 59788b0c84
commit bf56ea418a
9 changed files with 497 additions and 457 deletions

86
main.go
View File

@@ -111,16 +111,10 @@ func (rtc *WebRTC) Play(streamPath string) bool {
Println(err) Println(err)
return false return false
} }
peerConnection.OnICEConnectionStateChange(func(connectionState ICEConnectionState) {
Printf("%s Connection State has changed %s ", streamPath, connectionState.String())
switch connectionState {
case ICEConnectionStateDisconnected:
if rtc.Stream != nil {
rtc.Stream.Close()
}
case ICEConnectionStateConnected:
var sequence uint16 var sequence uint16
var sub Subscriber var sub Subscriber
var sps []byte
var pps []byte
sub.ID = rtc.RemoteAddr sub.ID = rtc.RemoteAddr
sub.Type = "WebRTC" sub.Type = "WebRTC"
nextHeader := func(ts uint32, marker bool) rtp.Header { nextHeader := func(ts uint32, marker bool) rtp.Header {
@@ -154,17 +148,19 @@ func (rtc *WebRTC) Play(streamPath string) bool {
if packet.IsSequence { if packet.IsSequence {
payload := packet.Payload[11:] payload := packet.Payload[11:]
spsLen := int(payload[0])<<8 + int(payload[1]) spsLen := int(payload[0])<<8 + int(payload[1])
sps := payload[2:spsLen] sps = payload[2:spsLen]
payload = payload[3+spsLen:] payload = payload[3+spsLen:]
ppsLen := int(payload[0])<<8 + int(payload[1]) ppsLen := int(payload[0])<<8 + int(payload[1])
pps := payload[2:ppsLen] pps = payload[2:ppsLen]
} else {
if packet.IsKeyFrame {
if err := videoTrack.WriteRTP(&rtp.Packet{ if err := videoTrack.WriteRTP(&rtp.Packet{
Header: nextHeader(0, false), Header: nextHeader(0, true),
Payload: stapA(sps, pps), Payload: stapA(sps, pps),
}); err != nil { }); err != nil {
return err return err
} }
} else { }
payload := packet.Payload[5:] payload := packet.Payload[5:]
for { for {
var naulLen = int(util.BigEndian.Uint32(payload)) var naulLen = int(util.BigEndian.Uint32(payload))
@@ -184,7 +180,6 @@ func (rtc *WebRTC) Play(streamPath string) bool {
}); err != nil { }); err != nil {
return err return err
} }
marker = true
if _payload == nil { if _payload == nil {
break break
} }
@@ -192,6 +187,7 @@ func (rtc *WebRTC) Play(streamPath string) bool {
header = 64 | nalutype header = 64 | nalutype
part = _payload[1000:] part = _payload[1000:]
_payload = nil _payload = nil
marker = true
} else { } else {
header = nalutype header = nalutype
part = _payload[1000:] part = _payload[1000:]
@@ -200,7 +196,7 @@ func (rtc *WebRTC) Play(streamPath string) bool {
} }
} else { } else {
if err := videoTrack.WriteRTP(&rtp.Packet{ if err := videoTrack.WriteRTP(&rtp.Packet{
Header: nextHeader(packet.Timestamp*90, false), Header: nextHeader(packet.Timestamp*90, true),
Payload: _payload, Payload: _payload,
}); err != nil { }); err != nil {
return err return err
@@ -220,9 +216,18 @@ func (rtc *WebRTC) Play(streamPath string) bool {
} }
return nil return nil
} }
sub.Subscribe(streamPath) go sub.Subscribe(streamPath)
} // peerConnection.OnICEConnectionStateChange(func(connectionState ICEConnectionState) {
}) // Printf("%s Connection State has changed %s ", streamPath, connectionState.String())
// switch connectionState {
// case ICEConnectionStateDisconnected:
// if rtc.Stream != nil {
// rtc.Stream.Close()
// }
// case ICEConnectionStateConnected:
// }
// })
return true return true
} }
func (rtc *WebRTC) Publish(streamPath string) bool { func (rtc *WebRTC) Publish(streamPath string) bool {
@@ -289,24 +294,13 @@ func (rtc *WebRTC) Publish(streamPath string) bool {
} }
return true return true
} }
func (rtc *WebRTC) GetAnswer(offer SessionDescription) ([]byte, error) { func (rtc *WebRTC) GetAnswer(localSdp SessionDescription) ([]byte, error) {
if err := rtc.SetRemoteDescription(offer); err != nil {
Println(err)
return nil, err
}
// Create answer
answer, err := rtc.CreateAnswer(nil)
if err != nil {
Println(err)
return nil, err
}
// Sets the LocalDescription, and starts our UDP listeners // Sets the LocalDescription, and starts our UDP listeners
if err = rtc.SetLocalDescription(answer); err != nil { if err := rtc.SetLocalDescription(localSdp); err != nil {
Println(err) Println(err)
return nil, err return nil, err
} }
if bytes, err := json.Marshal(answer); err != nil { if bytes, err := json.Marshal(localSdp); err != nil {
Println(err) Println(err)
return bytes, err return bytes, err
} else { } else {
@@ -316,17 +310,22 @@ func (rtc *WebRTC) GetAnswer(offer SessionDescription) ([]byte, error) {
func run() { func run() {
http.HandleFunc("/webrtc/play", func(w http.ResponseWriter, r *http.Request) { http.HandleFunc("/webrtc/play", func(w http.ResponseWriter, r *http.Request) {
streamPath := r.URL.Query().Get("streamPath") streamPath := r.URL.Query().Get("streamPath")
offer := SessionDescription{} // offer := SessionDescription{}
bytes, err := ioutil.ReadAll(r.Body) // bytes, err := ioutil.ReadAll(r.Body)
err = json.Unmarshal(bytes, &offer) // err = json.Unmarshal(bytes, &offer)
// if err != nil {
// Println(err)
// return
// }
rtc := new(WebRTC)
rtc.RemoteAddr = r.RemoteAddr
if rtc.Play(streamPath) {
offer, err := rtc.CreateOffer(nil)
if err != nil { if err != nil {
Println(err) Println(err)
return return
} }
rtc := new(WebRTC) if bytes, err := rtc.GetAnswer(offer); err == nil {
rtc.RemoteAddr = r.RemoteAddr
if rtc.Play(streamPath) {
if bytes, err = rtc.GetAnswer(offer); err == nil {
w.Write(bytes) w.Write(bytes)
} else { } else {
Println(err) Println(err)
@@ -349,7 +348,16 @@ func run() {
rtc := new(WebRTC) rtc := new(WebRTC)
rtc.RemoteAddr = r.RemoteAddr rtc.RemoteAddr = r.RemoteAddr
if rtc.Publish(streamPath) { if rtc.Publish(streamPath) {
if bytes, err = rtc.GetAnswer(offer); err == nil { if err := rtc.SetRemoteDescription(offer); err != nil {
Println(err)
return
}
answer, err := rtc.CreateAnswer(nil)
if err != nil {
Println(err)
return
}
if bytes, err = rtc.GetAnswer(answer); err == nil {
w.Write(bytes) w.Write(bytes)
} else { } else {
Println(err) Println(err)

View File

@@ -165,21 +165,21 @@ var __WEBPACK_AMD_DEFINE_FACTORY__, __WEBPACK_AMD_DEFINE_ARRAY__, __WEBPACK_AMD_
/***/ }), /***/ }),
/***/ "8dc9": /***/ "8e55":
/***/ (function(module, exports, __webpack_require__) { /***/ (function(module, exports, __webpack_require__) {
// extracted by mini-css-extract-plugin // extracted by mini-css-extract-plugin
/***/ }), /***/ }),
/***/ "c857": /***/ "e91a":
/***/ (function(module, __webpack_exports__, __webpack_require__) { /***/ (function(module, __webpack_exports__, __webpack_require__) {
"use strict"; "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_3d66f6b2_scoped_true_lang_css___WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__("8dc9"); /* 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_03ea1df8_scoped_true_lang_css___WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__("8e55");
/* 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_3d66f6b2_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_3d66f6b2_scoped_true_lang_css___WEBPACK_IMPORTED_MODULE_0__); /* 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_03ea1df8_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_03ea1df8_scoped_true_lang_css___WEBPACK_IMPORTED_MODULE_0__);
/* unused harmony reexport * */ /* 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_3d66f6b2_scoped_true_lang_css___WEBPACK_IMPORTED_MODULE_0___default.a); /* 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_03ea1df8_scoped_true_lang_css___WEBPACK_IMPORTED_MODULE_0___default.a);
/***/ }), /***/ }),
@@ -214,12 +214,12 @@ if (typeof window !== 'undefined') {
// Indicate to webpack that this file can be concatenated // Indicate to webpack that this file can be concatenated
/* harmony default export */ var setPublicPath = (null); /* 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=3d66f6b2&scoped=true& // 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=03ea1df8&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.iceConnectionState!='connected')?[_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")])]:(_vm.iceConnectionState=='connected')?_c('m-button',{on:{"click":_vm.stopSession}},[_vm._v("Stop")]):_vm._e(),_c('br'),_c('video',{ref:"video1",attrs:{"width":"640","height":"480","autoplay":"","muted":""},domProps:{"srcObject":_vm.stream,"muted":true}})],2)])} 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)])}
var staticRenderFns = [] var staticRenderFns = []
// CONCATENATED MODULE: ./src/App.vue?vue&type=template&id=3d66f6b2&scoped=true& // CONCATENATED MODULE: ./src/App.vue?vue&type=template&id=03ea1df8&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??ref--0-0!./node_modules/vue-loader/lib??vue-loader-options!./src/App.vue?vue&type=script&lang=js&
// //
@@ -267,10 +267,10 @@ const config = {
// ] // ]
// } // }
] ]
} };
let pc = new RTCPeerConnection(config); let pc = new RTCPeerConnection(config);
var stream = null var stream = null;
var streamPath = "live/rtc" var streamPath = "live/rtc";
/* harmony default export */ var Appvue_type_script_lang_js_ = ({ /* harmony default export */ var Appvue_type_script_lang_js_ = ({
data() { data() {
return { return {
@@ -284,61 +284,72 @@ var streamPath = "live/rtc"
}; };
}, },
methods: { methods: {
startSession(type) { async startSession(type) {
this.type = type this.type = type;
this.ask = true this.ask = true;
this.ajax({type: 'POST',processData:false,data: JSON.stringify(pc.localDescription),url:"/webrtc/"+type+"?streamPath="+this.streamPath,dataType:"json"}).then(result => { const result = await this.ajax({
this.ask = false type: "POST",
processData: false,
data: JSON.stringify(pc.localDescription),
url: "/webrtc/" + type + "?streamPath=" + this.streamPath,
dataType: "json"
});
this.ask = false;
if (result.errmsg) { if (result.errmsg) {
this.$toast.error(result.errmsg) this.$toast.error(result.errmsg);
} else { } else {
streamPath = this.streamPath streamPath = this.streamPath;
this.remoteSDP = result.sdp; this.remoteSDP = result.sdp;
this.$parent.titleTabs = ["摄像头", "localSDP", "remoteSDP"]; this.$parent.titleTabs = ["摄像头", "localSDP", "remoteSDP"];
pc.setRemoteDescription(new RTCSessionDescription(result)); pc.setRemoteDescription(new RTCSessionDescription(result));
} }
}); if (type == "publish") {
pc.addStream(stream);
this.localSDP = (
await pc.setLocalDescription(await pc.createOffer())
).sdp;
} else {
pc.ontrack = event => {
if(event.streams[0].id=="monibuca")
this.stream = stream = event.streams[0];
};
}
}, },
stopSession() { stopSession() {
pc.close() pc.close();
pc = new RTCPeerConnection(config) pc = new RTCPeerConnection(config);
this.remoteSDP = "" this.remoteSDP = "";
this.localSDP = "" this.localSDP = "";
this.connectICE().catch(err=> this.$toast.error(err.message)) this.type = "";
}, // this.connectICE().catch(err => this.$toast.error(err.message));
async connectICE(){
pc.addStream(stream);
await pc.setLocalDescription(await pc.createOffer())
pc.oniceconnectionstatechange = e => {
this.$toast.info(pc.iceConnectionState)
this.iceConnectionState = pc.iceConnectionState
};
pc.onicecandidate = event => {
if (event.candidate === null) {
this.localSDP = pc.localDescription.sdp;
this.$parent.titleTabs = ["摄像头", "localSDP"];
}
};
pc.ontrack = event=>{
if(this.type=="play" && event.streams[0]){
this.stream = stream = event.streams[0]
}
}
} }
}, },
async mounted() { async mounted() {
pc.onsignalingstatechange = e => {
console.log(e);
};
pc.oniceconnectionstatechange = e => {
this.$toast.info(pc.iceConnectionState);
this.iceConnectionState = pc.iceConnectionState;
};
pc.onicecandidate = event => {
if (event.candidate === null) {
this.$parent.titleTabs = ["摄像头", "localSDP"];
}
};
if (this.localSDP) { if (this.localSDP) {
let tabs = ["摄像头"] let tabs = ["摄像头"];
if(this.localSDP)tabs.push("localSDP") if (this.localSDP) tabs.push("localSDP");
if(this.remoteSDP)tabs.push("remoteSDP") if (this.remoteSDP) tabs.push("remoteSDP");
this.$parent.titleTabs = tabs; this.$parent.titleTabs = tabs;
} else { } else {
try { try {
if (!this.stream) if (!this.stream)
this.stream = stream = await navigator.mediaDevices.getUserMedia({ video: true, audio: true }) this.stream = stream = await navigator.mediaDevices.getUserMedia(
await this.connectICE() { video: true, audio: true }
);
} catch (err) { } catch (err) {
this.$toast.error(err.message) this.$toast.error(err.message);
} }
} }
} }
@@ -346,8 +357,8 @@ var streamPath = "live/rtc"
// CONCATENATED MODULE: ./src/App.vue?vue&type=script&lang=js& // 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_); /* 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=3d66f6b2&scoped=true&lang=css& // EXTERNAL MODULE: ./src/App.vue?vue&type=style&index=0&id=03ea1df8&scoped=true&lang=css&
var Appvue_type_style_index_0_id_3d66f6b2_scoped_true_lang_css_ = __webpack_require__("c857"); var Appvue_type_style_index_0_id_03ea1df8_scoped_true_lang_css_ = __webpack_require__("e91a");
// CONCATENATED MODULE: ./node_modules/vue-loader/lib/runtime/componentNormalizer.js // CONCATENATED MODULE: ./node_modules/vue-loader/lib/runtime/componentNormalizer.js
/* globals __VUE_SSR_CONTEXT__ */ /* globals __VUE_SSR_CONTEXT__ */
@@ -464,7 +475,7 @@ var component = normalizeComponent(
staticRenderFns, staticRenderFns,
false, false,
null, null,
"3d66f6b2", "03ea1df8",
null null
) )

File diff suppressed because one or more lines are too long

View File

@@ -1 +1 @@
@-webkit-keyframes blink-data-v-3d66f6b2{0%{opacity:.2}50%{opacity:1}to{opacity:.2}}@keyframes blink-data-v-3d66f6b2{0%{opacity:.2}50%{opacity:1}to{opacity:.2}}.blink[data-v-3d66f6b2]{-webkit-animation:blink-data-v-3d66f6b2 1s infinite;animation:blink-data-v-3d66f6b2 1s infinite} @-webkit-keyframes blink-data-v-03ea1df8{0%{opacity:.2}50%{opacity:1}to{opacity:.2}}@keyframes blink-data-v-03ea1df8{0%{opacity:.2}50%{opacity:1}to{opacity:.2}}.blink[data-v-03ea1df8]{-webkit-animation:blink-data-v-03ea1df8 1s infinite;animation:blink-data-v-03ea1df8 1s infinite}

View File

@@ -174,21 +174,21 @@ var __WEBPACK_AMD_DEFINE_FACTORY__, __WEBPACK_AMD_DEFINE_ARRAY__, __WEBPACK_AMD_
/***/ }), /***/ }),
/***/ "8dc9": /***/ "8e55":
/***/ (function(module, exports, __webpack_require__) { /***/ (function(module, exports, __webpack_require__) {
// extracted by mini-css-extract-plugin // extracted by mini-css-extract-plugin
/***/ }), /***/ }),
/***/ "c857": /***/ "e91a":
/***/ (function(module, __webpack_exports__, __webpack_require__) { /***/ (function(module, __webpack_exports__, __webpack_require__) {
"use strict"; "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_3d66f6b2_scoped_true_lang_css___WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__("8dc9"); /* 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_03ea1df8_scoped_true_lang_css___WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__("8e55");
/* 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_3d66f6b2_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_3d66f6b2_scoped_true_lang_css___WEBPACK_IMPORTED_MODULE_0__); /* 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_03ea1df8_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_03ea1df8_scoped_true_lang_css___WEBPACK_IMPORTED_MODULE_0__);
/* unused harmony reexport * */ /* 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_3d66f6b2_scoped_true_lang_css___WEBPACK_IMPORTED_MODULE_0___default.a); /* 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_03ea1df8_scoped_true_lang_css___WEBPACK_IMPORTED_MODULE_0___default.a);
/***/ }), /***/ }),
@@ -223,12 +223,12 @@ if (typeof window !== 'undefined') {
// Indicate to webpack that this file can be concatenated // Indicate to webpack that this file can be concatenated
/* harmony default export */ var setPublicPath = (null); /* 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=3d66f6b2&scoped=true& // 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=03ea1df8&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.iceConnectionState!='connected')?[_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")])]:(_vm.iceConnectionState=='connected')?_c('m-button',{on:{"click":_vm.stopSession}},[_vm._v("Stop")]):_vm._e(),_c('br'),_c('video',{ref:"video1",attrs:{"width":"640","height":"480","autoplay":"","muted":""},domProps:{"srcObject":_vm.stream,"muted":true}})],2)])} 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)])}
var staticRenderFns = [] var staticRenderFns = []
// CONCATENATED MODULE: ./src/App.vue?vue&type=template&id=3d66f6b2&scoped=true& // CONCATENATED MODULE: ./src/App.vue?vue&type=template&id=03ea1df8&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??ref--0-0!./node_modules/vue-loader/lib??vue-loader-options!./src/App.vue?vue&type=script&lang=js&
// //
@@ -276,10 +276,10 @@ const config = {
// ] // ]
// } // }
] ]
} };
let pc = new RTCPeerConnection(config); let pc = new RTCPeerConnection(config);
var stream = null var stream = null;
var streamPath = "live/rtc" var streamPath = "live/rtc";
/* harmony default export */ var Appvue_type_script_lang_js_ = ({ /* harmony default export */ var Appvue_type_script_lang_js_ = ({
data() { data() {
return { return {
@@ -293,61 +293,72 @@ var streamPath = "live/rtc"
}; };
}, },
methods: { methods: {
startSession(type) { async startSession(type) {
this.type = type this.type = type;
this.ask = true this.ask = true;
this.ajax({type: 'POST',processData:false,data: JSON.stringify(pc.localDescription),url:"/webrtc/"+type+"?streamPath="+this.streamPath,dataType:"json"}).then(result => { const result = await this.ajax({
this.ask = false type: "POST",
processData: false,
data: JSON.stringify(pc.localDescription),
url: "/webrtc/" + type + "?streamPath=" + this.streamPath,
dataType: "json"
});
this.ask = false;
if (result.errmsg) { if (result.errmsg) {
this.$toast.error(result.errmsg) this.$toast.error(result.errmsg);
} else { } else {
streamPath = this.streamPath streamPath = this.streamPath;
this.remoteSDP = result.sdp; this.remoteSDP = result.sdp;
this.$parent.titleTabs = ["摄像头", "localSDP", "remoteSDP"]; this.$parent.titleTabs = ["摄像头", "localSDP", "remoteSDP"];
pc.setRemoteDescription(new RTCSessionDescription(result)); pc.setRemoteDescription(new RTCSessionDescription(result));
} }
}); if (type == "publish") {
pc.addStream(stream);
this.localSDP = (
await pc.setLocalDescription(await pc.createOffer())
).sdp;
} else {
pc.ontrack = event => {
if(event.streams[0].id=="monibuca")
this.stream = stream = event.streams[0];
};
}
}, },
stopSession() { stopSession() {
pc.close() pc.close();
pc = new RTCPeerConnection(config) pc = new RTCPeerConnection(config);
this.remoteSDP = "" this.remoteSDP = "";
this.localSDP = "" this.localSDP = "";
this.connectICE().catch(err=> this.$toast.error(err.message)) this.type = "";
}, // this.connectICE().catch(err => this.$toast.error(err.message));
async connectICE(){
pc.addStream(stream);
await pc.setLocalDescription(await pc.createOffer())
pc.oniceconnectionstatechange = e => {
this.$toast.info(pc.iceConnectionState)
this.iceConnectionState = pc.iceConnectionState
};
pc.onicecandidate = event => {
if (event.candidate === null) {
this.localSDP = pc.localDescription.sdp;
this.$parent.titleTabs = ["摄像头", "localSDP"];
}
};
pc.ontrack = event=>{
if(this.type=="play" && event.streams[0]){
this.stream = stream = event.streams[0]
}
}
} }
}, },
async mounted() { async mounted() {
pc.onsignalingstatechange = e => {
console.log(e);
};
pc.oniceconnectionstatechange = e => {
this.$toast.info(pc.iceConnectionState);
this.iceConnectionState = pc.iceConnectionState;
};
pc.onicecandidate = event => {
if (event.candidate === null) {
this.$parent.titleTabs = ["摄像头", "localSDP"];
}
};
if (this.localSDP) { if (this.localSDP) {
let tabs = ["摄像头"] let tabs = ["摄像头"];
if(this.localSDP)tabs.push("localSDP") if (this.localSDP) tabs.push("localSDP");
if(this.remoteSDP)tabs.push("remoteSDP") if (this.remoteSDP) tabs.push("remoteSDP");
this.$parent.titleTabs = tabs; this.$parent.titleTabs = tabs;
} else { } else {
try { try {
if (!this.stream) if (!this.stream)
this.stream = stream = await navigator.mediaDevices.getUserMedia({ video: true, audio: true }) this.stream = stream = await navigator.mediaDevices.getUserMedia(
await this.connectICE() { video: true, audio: true }
);
} catch (err) { } catch (err) {
this.$toast.error(err.message) this.$toast.error(err.message);
} }
} }
} }
@@ -355,8 +366,8 @@ var streamPath = "live/rtc"
// CONCATENATED MODULE: ./src/App.vue?vue&type=script&lang=js& // 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_); /* 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=3d66f6b2&scoped=true&lang=css& // EXTERNAL MODULE: ./src/App.vue?vue&type=style&index=0&id=03ea1df8&scoped=true&lang=css&
var Appvue_type_style_index_0_id_3d66f6b2_scoped_true_lang_css_ = __webpack_require__("c857"); var Appvue_type_style_index_0_id_03ea1df8_scoped_true_lang_css_ = __webpack_require__("e91a");
// CONCATENATED MODULE: ./node_modules/vue-loader/lib/runtime/componentNormalizer.js // CONCATENATED MODULE: ./node_modules/vue-loader/lib/runtime/componentNormalizer.js
/* globals __VUE_SSR_CONTEXT__ */ /* globals __VUE_SSR_CONTEXT__ */
@@ -473,7 +484,7 @@ var component = normalizeComponent(
staticRenderFns, staticRenderFns,
false, false,
null, null,
"3d66f6b2", "03ea1df8",
null null
) )

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

View File

@@ -5,11 +5,11 @@
<div v-else> <div v-else>
<mu-text-field v-model="streamPath" label="streamPath"></mu-text-field> <mu-text-field v-model="streamPath" label="streamPath"></mu-text-field>
<span class="blink" v-if="!localSDP || ask">Connecting</span> <span class="blink" v-if="!localSDP || ask">Connecting</span>
<template v-else-if="iceConnectionState!='connected'"> <template>
<m-button @click="startSession('publish')">Publish</m-button> <m-button @click="startSession('publish')">Publish</m-button>
<m-button @click="startSession('play')">Play</m-button> <m-button @click="startSession('play')">Play</m-button>
</template> </template>
<m-button @click="stopSession" v-else-if="iceConnectionState=='connected'">Stop</m-button> <m-button @click="stopSession">Stop</m-button>
<br /> <br />
<video ref="video1" :srcObject.prop="stream" width="640" height="480" autoplay muted></video> <video ref="video1" :srcObject.prop="stream" width="640" height="480" autoplay muted></video>
</div> </div>
@@ -43,10 +43,10 @@ const config = {
// ] // ]
// } // }
] ]
} };
let pc = new RTCPeerConnection(config); let pc = new RTCPeerConnection(config);
var stream = null var stream = null;
var streamPath = "live/rtc" var streamPath = "live/rtc";
export default { export default {
data() { data() {
return { return {
@@ -60,61 +60,72 @@ export default {
}; };
}, },
methods: { methods: {
startSession(type) { async startSession(type) {
this.type = type this.type = type;
this.ask = true this.ask = true;
this.ajax({type: 'POST',processData:false,data: JSON.stringify(pc.localDescription),url:"/webrtc/"+type+"?streamPath="+this.streamPath,dataType:"json"}).then(result => { const result = await this.ajax({
this.ask = false type: "POST",
processData: false,
data: JSON.stringify(pc.localDescription),
url: "/webrtc/" + type + "?streamPath=" + this.streamPath,
dataType: "json"
});
this.ask = false;
if (result.errmsg) { if (result.errmsg) {
this.$toast.error(result.errmsg) this.$toast.error(result.errmsg);
} else { } else {
streamPath = this.streamPath streamPath = this.streamPath;
this.remoteSDP = result.sdp; this.remoteSDP = result.sdp;
this.$parent.titleTabs = ["摄像头", "localSDP", "remoteSDP"]; this.$parent.titleTabs = ["摄像头", "localSDP", "remoteSDP"];
pc.setRemoteDescription(new RTCSessionDescription(result)); pc.setRemoteDescription(new RTCSessionDescription(result));
} }
}); if (type == "publish") {
pc.addStream(stream);
this.localSDP = (
await pc.setLocalDescription(await pc.createOffer())
).sdp;
} else {
pc.ontrack = event => {
if(event.streams[0].id=="monibuca")
this.stream = stream = event.streams[0];
};
}
}, },
stopSession() { stopSession() {
pc.close() pc.close();
pc = new RTCPeerConnection(config) pc = new RTCPeerConnection(config);
this.remoteSDP = "" this.remoteSDP = "";
this.localSDP = "" this.localSDP = "";
this.connectICE().catch(err=> this.$toast.error(err.message)) this.type = "";
}, // this.connectICE().catch(err => this.$toast.error(err.message));
async connectICE(){
pc.addStream(stream);
await pc.setLocalDescription(await pc.createOffer())
pc.oniceconnectionstatechange = e => {
this.$toast.info(pc.iceConnectionState)
this.iceConnectionState = pc.iceConnectionState
};
pc.onicecandidate = event => {
if (event.candidate === null) {
this.localSDP = pc.localDescription.sdp;
this.$parent.titleTabs = ["摄像头", "localSDP"];
}
};
pc.ontrack = event=>{
if(this.type=="play" && event.streams[0]){
this.stream = stream = event.streams[0]
}
}
} }
}, },
async mounted() { async mounted() {
pc.onsignalingstatechange = e => {
console.log(e);
};
pc.oniceconnectionstatechange = e => {
this.$toast.info(pc.iceConnectionState);
this.iceConnectionState = pc.iceConnectionState;
};
pc.onicecandidate = event => {
if (event.candidate === null) {
this.$parent.titleTabs = ["摄像头", "localSDP"];
}
};
if (this.localSDP) { if (this.localSDP) {
let tabs = ["摄像头"] let tabs = ["摄像头"];
if(this.localSDP)tabs.push("localSDP") if (this.localSDP) tabs.push("localSDP");
if(this.remoteSDP)tabs.push("remoteSDP") if (this.remoteSDP) tabs.push("remoteSDP");
this.$parent.titleTabs = tabs; this.$parent.titleTabs = tabs;
} else { } else {
try { try {
if (!this.stream) if (!this.stream)
this.stream = stream = await navigator.mediaDevices.getUserMedia({ video: true, audio: true }) this.stream = stream = await navigator.mediaDevices.getUserMedia(
await this.connectICE() { video: true, audio: true }
);
} catch (err) { } catch (err) {
this.$toast.error(err.message) this.$toast.error(err.message);
} }
} }
} }
@@ -136,5 +147,4 @@ export default {
.blink { .blink {
animation: blink 1s infinite; animation: blink 1s infinite;
} }
</style> </style>