开发播放功能

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

260
main.go
View File

@@ -111,118 +111,123 @@ func (rtc *WebRTC) Play(streamPath string) bool {
Println(err) Println(err)
return false return false
} }
peerConnection.OnICEConnectionStateChange(func(connectionState ICEConnectionState) { var sequence uint16
Printf("%s Connection State has changed %s ", streamPath, connectionState.String()) var sub Subscriber
switch connectionState { var sps []byte
case ICEConnectionStateDisconnected: var pps []byte
if rtc.Stream != nil { sub.ID = rtc.RemoteAddr
rtc.Stream.Close() sub.Type = "WebRTC"
} nextHeader := func(ts uint32, marker bool) rtp.Header {
case ICEConnectionStateConnected: sequence++
var sequence uint16 return rtp.Header{
var sub Subscriber Version: 2,
sub.ID = rtc.RemoteAddr SSRC: ssrc,
sub.Type = "WebRTC" PayloadType: DefaultPayloadTypeH264,
nextHeader := func(ts uint32, marker bool) rtp.Header { SequenceNumber: sequence,
sequence++ Timestamp: ts,
return rtp.Header{ Marker: marker,
Version: 2, }
SSRC: ssrc, }
PayloadType: DefaultPayloadTypeH264, stapA := func(naul ...[]byte) []byte {
SequenceNumber: sequence, var buffer bytes.Buffer
Timestamp: ts, buffer.WriteByte(24)
Marker: marker, for _, n := range naul {
} l := len(n)
} buffer.WriteByte(byte(l >> 8))
stapA := func(naul ...[]byte) []byte { buffer.WriteByte(byte(l))
var buffer bytes.Buffer buffer.Write(n)
buffer.WriteByte(24) }
for _, n := range naul { return buffer.Bytes()
l := len(n) }
buffer.WriteByte(byte(l >> 8))
buffer.WriteByte(byte(l))
buffer.Write(n)
}
return buffer.Bytes()
}
// aud := []byte{0x09, 0x30} // aud := []byte{0x09, 0x30}
sub.OnData = func(packet *avformat.SendPacket) error { sub.OnData = func(packet *avformat.SendPacket) error {
if packet.Type == avformat.FLV_TAG_TYPE_AUDIO { if packet.Type == avformat.FLV_TAG_TYPE_AUDIO {
return nil 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 := videoTrack.WriteRTP(&rtp.Packet{
Header: nextHeader(0, true),
Payload: stapA(sps, pps),
}); err != nil {
return err
} }
if packet.IsSequence { }
payload := packet.Payload[11:] payload := packet.Payload[5:]
spsLen := int(payload[0])<<8 + int(payload[1]) for {
sps := payload[2:spsLen] var naulLen = int(util.BigEndian.Uint32(payload))
payload = payload[3+spsLen:] payload = payload[4:]
ppsLen := int(payload[0])<<8 + int(payload[1]) _payload := payload[:naulLen]
pps := payload[2:ppsLen] if naulLen > 1000 {
part := _payload[:1000]
indicator := ((part[0] >> 5) << 5) | 28
nalutype := part[0] & 31
header := 128 | nalutype
part = part[1:]
marker := false
for {
if err := videoTrack.WriteRTP(&rtp.Packet{
Header: nextHeader(packet.Timestamp*90, marker),
Payload: append([]byte{indicator, header}, part...),
}); err != nil {
return err
}
if _payload == nil {
break
}
if len(_payload[1000:]) <= 1000 {
header = 64 | nalutype
part = _payload[1000:]
_payload = nil
marker = true
} else {
header = nalutype
part = _payload[1000:]
_payload = part
}
}
} else {
if err := videoTrack.WriteRTP(&rtp.Packet{ if err := videoTrack.WriteRTP(&rtp.Packet{
Header: nextHeader(0, false), Header: nextHeader(packet.Timestamp*90, true),
Payload: stapA(sps, pps), Payload: _payload,
}); err != nil { }); err != nil {
return err return err
} }
} else {
payload := packet.Payload[5:]
for {
var naulLen = int(util.BigEndian.Uint32(payload))
payload = payload[4:]
_payload := payload[:naulLen]
if naulLen > 1000 {
part := _payload[:1000]
indicator := ((part[0] >> 5) << 5) | 28
nalutype := part[0] & 31
header := 128 | nalutype
part = part[1:]
marker := false
for {
if err := videoTrack.WriteRTP(&rtp.Packet{
Header: nextHeader(packet.Timestamp*90, marker),
Payload: append([]byte{indicator, header}, part...),
}); err != nil {
return err
}
marker = true
if _payload == nil {
break
}
if len(_payload[1000:]) <= 1000 {
header = 64 | nalutype
part = _payload[1000:]
_payload = nil
} else {
header = nalutype
part = _payload[1000:]
_payload = part
}
}
} else {
if err := videoTrack.WriteRTP(&rtp.Packet{
Header: nextHeader(packet.Timestamp*90, false),
Payload: _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 if len(payload) < naulLen+4 {
break
}
payload = payload[naulLen:]
} }
sub.Subscribe(streamPath) // if err := videoTrack.WriteRTP(&rtp.Packet{
// Header: nextHeader(packet.Timestamp * 90),
// Payload: aud,
// }); err != nil {
// return err
// }
} }
}) return nil
}
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 { // if err != nil {
Println(err) // Println(err)
return // return
} // }
rtc := new(WebRTC) rtc := new(WebRTC)
rtc.RemoteAddr = r.RemoteAddr rtc.RemoteAddr = r.RemoteAddr
if rtc.Play(streamPath) { if rtc.Play(streamPath) {
if bytes, err = rtc.GetAnswer(offer); err == nil { offer, err := rtc.CreateOffer(nil)
if err != nil {
Println(err)
return
}
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&
// //
@@ -242,112 +242,123 @@ var staticRenderFns = []
// //
const config = { const config = {
iceServers:[ iceServers: [
// { // {
// urls:[ // urls:[
// "stun:stun.ekiga.net", // "stun:stun.ekiga.net",
// "stun:stun.ideasip.com", // "stun:stun.ideasip.com",
// "stun:stun.schlund.de", // "stun:stun.schlund.de",
// "stun:stun.stunprotocol.org:3478", // "stun:stun.stunprotocol.org:3478",
// "stun:stun.voiparound.com", // "stun:stun.voiparound.com",
// "stun:stun.voipbuster.com", // "stun:stun.voipbuster.com",
// "stun:stun.voipstunt.com", // "stun:stun.voipstunt.com",
// "stun:stun.voxgratia.org", // "stun:stun.voxgratia.org",
// "stun:stun.services.mozilla.com", // "stun:stun.services.mozilla.com",
// "stun:stun.xten.com", // "stun:stun.xten.com",
// "stun:stun.softjoys.com", // "stun:stun.softjoys.com",
// "stun:stunserver.org", // "stun:stunserver.org",
// "stun:stun.schlund.de", // "stun:stun.schlund.de",
// "stun:stun.rixtelecom.se", // "stun:stun.rixtelecom.se",
// "stun:stun.iptel.org", // "stun:stun.iptel.org",
// "stun:stun.ideasip.com", // "stun:stun.ideasip.com",
// "stun:stun.fwdnet.net", // "stun:stun.fwdnet.net",
// "stun:stun.ekiga.net", // "stun:stun.ekiga.net",
// "stun:stun01.sipphone.com", // "stun:stun01.sipphone.com",
// ] // ]
// } // }
] ]
} };
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 {
localSDP: pc&&pc.localDescription&&pc.localDescription.sdp, localSDP: pc && pc.localDescription && pc.localDescription.sdp,
remoteSDP: pc&&pc.remoteDescription&&pc.remoteDescription.sdp, remoteSDP: pc && pc.remoteDescription && pc.remoteDescription.sdp,
streamPath, streamPath,
iceConnectionState:pc&&pc.iceConnectionState, iceConnectionState: pc && pc.iceConnectionState,
stream, stream,
type:"", type: "",
ask:false ask: false
}; };
},
methods: {
startSession(type) {
this.type = type
this.ask = true
this.ajax({type: 'POST',processData:false,data: JSON.stringify(pc.localDescription),url:"/webrtc/"+type+"?streamPath="+this.streamPath,dataType:"json"}).then(result => {
this.ask = false
if (result.errmsg){
this.$toast.error(result.errmsg)
}else{
streamPath = this.streamPath
this.remoteSDP = result.sdp;
this.$parent.titleTabs = ["摄像头", "localSDP","remoteSDP"];
pc.setRemoteDescription(new RTCSessionDescription(result));
}
});
}, },
stopSession(){ methods: {
pc.close() async startSession(type) {
pc = new RTCPeerConnection(config) this.type = type;
this.remoteSDP = "" this.ask = true;
this.localSDP = "" const result = await this.ajax({
this.connectICE().catch(err=> this.$toast.error(err.message)) type: "POST",
processData: false,
data: JSON.stringify(pc.localDescription),
url: "/webrtc/" + type + "?streamPath=" + this.streamPath,
dataType: "json"
});
this.ask = false;
if (result.errmsg) {
this.$toast.error(result.errmsg);
} else {
streamPath = this.streamPath;
this.remoteSDP = result.sdp;
this.$parent.titleTabs = ["摄像头", "localSDP", "remoteSDP"];
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() {
pc.close();
pc = new RTCPeerConnection(config);
this.remoteSDP = "";
this.localSDP = "";
this.type = "";
// this.connectICE().catch(err => this.$toast.error(err.message));
}
}, },
async connectICE(){ async mounted() {
pc.addStream(stream); pc.onsignalingstatechange = e => {
await pc.setLocalDescription(await pc.createOffer()) console.log(e);
pc.oniceconnectionstatechange = e => { };
this.$toast.info(pc.iceConnectionState) pc.oniceconnectionstatechange = e => {
this.iceConnectionState = pc.iceConnectionState this.$toast.info(pc.iceConnectionState);
}; this.iceConnectionState = pc.iceConnectionState;
pc.onicecandidate = event => { };
if (event.candidate === null) { pc.onicecandidate = event => {
this.localSDP = pc.localDescription.sdp; if (event.candidate === null) {
this.$parent.titleTabs = ["摄像头", "localSDP"]; this.$parent.titleTabs = ["摄像头", "localSDP"];
}
};
if (this.localSDP) {
let tabs = ["摄像头"];
if (this.localSDP) tabs.push("localSDP");
if (this.remoteSDP) tabs.push("remoteSDP");
this.$parent.titleTabs = tabs;
} else {
try {
if (!this.stream)
this.stream = stream = await navigator.mediaDevices.getUserMedia(
{ video: true, audio: true }
);
} catch (err) {
this.$toast.error(err.message);
}
} }
};
pc.ontrack = event=>{
if(this.type=="play" && event.streams[0]){
this.stream = stream = event.streams[0]
}
}
} }
},
async mounted() {
if (this.localSDP){
let tabs = ["摄像头"]
if(this.localSDP)tabs.push("localSDP")
if(this.remoteSDP)tabs.push("remoteSDP")
this.$parent.titleTabs = tabs;
} else {
try{
if(!this.stream)
this.stream = stream = await navigator.mediaDevices.getUserMedia({ video: true, audio: true })
await this.connectICE()
}catch(err){
this.$toast.error(err.message)
}
}
}
}); });
// 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&
// //
@@ -251,112 +251,123 @@ var staticRenderFns = []
// //
const config = { const config = {
iceServers:[ iceServers: [
// { // {
// urls:[ // urls:[
// "stun:stun.ekiga.net", // "stun:stun.ekiga.net",
// "stun:stun.ideasip.com", // "stun:stun.ideasip.com",
// "stun:stun.schlund.de", // "stun:stun.schlund.de",
// "stun:stun.stunprotocol.org:3478", // "stun:stun.stunprotocol.org:3478",
// "stun:stun.voiparound.com", // "stun:stun.voiparound.com",
// "stun:stun.voipbuster.com", // "stun:stun.voipbuster.com",
// "stun:stun.voipstunt.com", // "stun:stun.voipstunt.com",
// "stun:stun.voxgratia.org", // "stun:stun.voxgratia.org",
// "stun:stun.services.mozilla.com", // "stun:stun.services.mozilla.com",
// "stun:stun.xten.com", // "stun:stun.xten.com",
// "stun:stun.softjoys.com", // "stun:stun.softjoys.com",
// "stun:stunserver.org", // "stun:stunserver.org",
// "stun:stun.schlund.de", // "stun:stun.schlund.de",
// "stun:stun.rixtelecom.se", // "stun:stun.rixtelecom.se",
// "stun:stun.iptel.org", // "stun:stun.iptel.org",
// "stun:stun.ideasip.com", // "stun:stun.ideasip.com",
// "stun:stun.fwdnet.net", // "stun:stun.fwdnet.net",
// "stun:stun.ekiga.net", // "stun:stun.ekiga.net",
// "stun:stun01.sipphone.com", // "stun:stun01.sipphone.com",
// ] // ]
// } // }
] ]
} };
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 {
localSDP: pc&&pc.localDescription&&pc.localDescription.sdp, localSDP: pc && pc.localDescription && pc.localDescription.sdp,
remoteSDP: pc&&pc.remoteDescription&&pc.remoteDescription.sdp, remoteSDP: pc && pc.remoteDescription && pc.remoteDescription.sdp,
streamPath, streamPath,
iceConnectionState:pc&&pc.iceConnectionState, iceConnectionState: pc && pc.iceConnectionState,
stream, stream,
type:"", type: "",
ask:false ask: false
}; };
},
methods: {
startSession(type) {
this.type = type
this.ask = true
this.ajax({type: 'POST',processData:false,data: JSON.stringify(pc.localDescription),url:"/webrtc/"+type+"?streamPath="+this.streamPath,dataType:"json"}).then(result => {
this.ask = false
if (result.errmsg){
this.$toast.error(result.errmsg)
}else{
streamPath = this.streamPath
this.remoteSDP = result.sdp;
this.$parent.titleTabs = ["摄像头", "localSDP","remoteSDP"];
pc.setRemoteDescription(new RTCSessionDescription(result));
}
});
}, },
stopSession(){ methods: {
pc.close() async startSession(type) {
pc = new RTCPeerConnection(config) this.type = type;
this.remoteSDP = "" this.ask = true;
this.localSDP = "" const result = await this.ajax({
this.connectICE().catch(err=> this.$toast.error(err.message)) type: "POST",
processData: false,
data: JSON.stringify(pc.localDescription),
url: "/webrtc/" + type + "?streamPath=" + this.streamPath,
dataType: "json"
});
this.ask = false;
if (result.errmsg) {
this.$toast.error(result.errmsg);
} else {
streamPath = this.streamPath;
this.remoteSDP = result.sdp;
this.$parent.titleTabs = ["摄像头", "localSDP", "remoteSDP"];
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() {
pc.close();
pc = new RTCPeerConnection(config);
this.remoteSDP = "";
this.localSDP = "";
this.type = "";
// this.connectICE().catch(err => this.$toast.error(err.message));
}
}, },
async connectICE(){ async mounted() {
pc.addStream(stream); pc.onsignalingstatechange = e => {
await pc.setLocalDescription(await pc.createOffer()) console.log(e);
pc.oniceconnectionstatechange = e => { };
this.$toast.info(pc.iceConnectionState) pc.oniceconnectionstatechange = e => {
this.iceConnectionState = pc.iceConnectionState this.$toast.info(pc.iceConnectionState);
}; this.iceConnectionState = pc.iceConnectionState;
pc.onicecandidate = event => { };
if (event.candidate === null) { pc.onicecandidate = event => {
this.localSDP = pc.localDescription.sdp; if (event.candidate === null) {
this.$parent.titleTabs = ["摄像头", "localSDP"]; this.$parent.titleTabs = ["摄像头", "localSDP"];
}
};
if (this.localSDP) {
let tabs = ["摄像头"];
if (this.localSDP) tabs.push("localSDP");
if (this.remoteSDP) tabs.push("remoteSDP");
this.$parent.titleTabs = tabs;
} else {
try {
if (!this.stream)
this.stream = stream = await navigator.mediaDevices.getUserMedia(
{ video: true, audio: true }
);
} catch (err) {
this.$toast.error(err.message);
}
} }
};
pc.ontrack = event=>{
if(this.type=="play" && event.streams[0]){
this.stream = stream = event.streams[0]
}
}
} }
},
async mounted() {
if (this.localSDP){
let tabs = ["摄像头"]
if(this.localSDP)tabs.push("localSDP")
if(this.remoteSDP)tabs.push("remoteSDP")
this.$parent.titleTabs = tabs;
} else {
try{
if(!this.stream)
this.stream = stream = await navigator.mediaDevices.getUserMedia({ video: true, audio: true })
await this.connectICE()
}catch(err){
this.$toast.error(err.message)
}
}
}
}); });
// 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

@@ -1,140 +1,150 @@
<template> <template>
<div> <div>
<pre v-if="$parent.titleTabActive == 1">{{localSDP}}</pre> <pre v-if="$parent.titleTabActive == 1">{{localSDP}}</pre>
<pre v-else-if="$parent.titleTabActive == 2">{{remoteSDP}}</pre> <pre v-else-if="$parent.titleTabActive == 2">{{remoteSDP}}</pre>
<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> </div>
</div>
</template> </template>
<script> <script>
const config = { const config = {
iceServers:[ iceServers: [
// { // {
// urls:[ // urls:[
// "stun:stun.ekiga.net", // "stun:stun.ekiga.net",
// "stun:stun.ideasip.com", // "stun:stun.ideasip.com",
// "stun:stun.schlund.de", // "stun:stun.schlund.de",
// "stun:stun.stunprotocol.org:3478", // "stun:stun.stunprotocol.org:3478",
// "stun:stun.voiparound.com", // "stun:stun.voiparound.com",
// "stun:stun.voipbuster.com", // "stun:stun.voipbuster.com",
// "stun:stun.voipstunt.com", // "stun:stun.voipstunt.com",
// "stun:stun.voxgratia.org", // "stun:stun.voxgratia.org",
// "stun:stun.services.mozilla.com", // "stun:stun.services.mozilla.com",
// "stun:stun.xten.com", // "stun:stun.xten.com",
// "stun:stun.softjoys.com", // "stun:stun.softjoys.com",
// "stun:stunserver.org", // "stun:stunserver.org",
// "stun:stun.schlund.de", // "stun:stun.schlund.de",
// "stun:stun.rixtelecom.se", // "stun:stun.rixtelecom.se",
// "stun:stun.iptel.org", // "stun:stun.iptel.org",
// "stun:stun.ideasip.com", // "stun:stun.ideasip.com",
// "stun:stun.fwdnet.net", // "stun:stun.fwdnet.net",
// "stun:stun.ekiga.net", // "stun:stun.ekiga.net",
// "stun:stun01.sipphone.com", // "stun:stun01.sipphone.com",
// ] // ]
// } // }
] ]
} };
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 {
localSDP: pc&&pc.localDescription&&pc.localDescription.sdp, localSDP: pc && pc.localDescription && pc.localDescription.sdp,
remoteSDP: pc&&pc.remoteDescription&&pc.remoteDescription.sdp, remoteSDP: pc && pc.remoteDescription && pc.remoteDescription.sdp,
streamPath, streamPath,
iceConnectionState:pc&&pc.iceConnectionState, iceConnectionState: pc && pc.iceConnectionState,
stream, stream,
type:"", type: "",
ask:false ask: false
}; };
},
methods: {
startSession(type) {
this.type = type
this.ask = true
this.ajax({type: 'POST',processData:false,data: JSON.stringify(pc.localDescription),url:"/webrtc/"+type+"?streamPath="+this.streamPath,dataType:"json"}).then(result => {
this.ask = false
if (result.errmsg){
this.$toast.error(result.errmsg)
}else{
streamPath = this.streamPath
this.remoteSDP = result.sdp;
this.$parent.titleTabs = ["摄像头", "localSDP","remoteSDP"];
pc.setRemoteDescription(new RTCSessionDescription(result));
}
});
}, },
stopSession(){ methods: {
pc.close() async startSession(type) {
pc = new RTCPeerConnection(config) this.type = type;
this.remoteSDP = "" this.ask = true;
this.localSDP = "" const result = await this.ajax({
this.connectICE().catch(err=> this.$toast.error(err.message)) type: "POST",
processData: false,
data: JSON.stringify(pc.localDescription),
url: "/webrtc/" + type + "?streamPath=" + this.streamPath,
dataType: "json"
});
this.ask = false;
if (result.errmsg) {
this.$toast.error(result.errmsg);
} else {
streamPath = this.streamPath;
this.remoteSDP = result.sdp;
this.$parent.titleTabs = ["摄像头", "localSDP", "remoteSDP"];
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() {
pc.close();
pc = new RTCPeerConnection(config);
this.remoteSDP = "";
this.localSDP = "";
this.type = "";
// this.connectICE().catch(err => this.$toast.error(err.message));
}
}, },
async connectICE(){ async mounted() {
pc.addStream(stream); pc.onsignalingstatechange = e => {
await pc.setLocalDescription(await pc.createOffer()) console.log(e);
pc.oniceconnectionstatechange = e => { };
this.$toast.info(pc.iceConnectionState) pc.oniceconnectionstatechange = e => {
this.iceConnectionState = pc.iceConnectionState this.$toast.info(pc.iceConnectionState);
}; this.iceConnectionState = pc.iceConnectionState;
pc.onicecandidate = event => { };
if (event.candidate === null) { pc.onicecandidate = event => {
this.localSDP = pc.localDescription.sdp; if (event.candidate === null) {
this.$parent.titleTabs = ["摄像头", "localSDP"]; this.$parent.titleTabs = ["摄像头", "localSDP"];
}
};
if (this.localSDP) {
let tabs = ["摄像头"];
if (this.localSDP) tabs.push("localSDP");
if (this.remoteSDP) tabs.push("remoteSDP");
this.$parent.titleTabs = tabs;
} else {
try {
if (!this.stream)
this.stream = stream = await navigator.mediaDevices.getUserMedia(
{ video: true, audio: true }
);
} catch (err) {
this.$toast.error(err.message);
}
} }
};
pc.ontrack = event=>{
if(this.type=="play" && event.streams[0]){
this.stream = stream = event.streams[0]
}
}
} }
},
async mounted() {
if (this.localSDP){
let tabs = ["摄像头"]
if(this.localSDP)tabs.push("localSDP")
if(this.remoteSDP)tabs.push("remoteSDP")
this.$parent.titleTabs = tabs;
} else {
try{
if(!this.stream)
this.stream = stream = await navigator.mediaDevices.getUserMedia({ video: true, audio: true })
await this.connectICE()
}catch(err){
this.$toast.error(err.message)
}
}
}
}; };
</script> </script>
<style scoped> <style scoped>
@keyframes blink { @keyframes blink {
0% { 0% {
opacity: 0.2; opacity: 0.2;
} }
50% { 50% {
opacity: 1; opacity: 1;
} }
100% { 100% {
opacity: 0.2; opacity: 0.2;
} }
} }
.blink { .blink {
animation: blink 1s infinite; animation: blink 1s infinite;
} }
</style> </style>