开发播放功能

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)
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 sub Subscriber
sub.ID = rtc.RemoteAddr
sub.Type = "WebRTC"
nextHeader := func(ts uint32, marker bool) rtp.Header {
sequence++
return rtp.Header{
Version: 2,
SSRC: ssrc,
PayloadType: DefaultPayloadTypeH264,
SequenceNumber: sequence,
Timestamp: ts,
Marker: marker,
}
}
stapA := func(naul ...[]byte) []byte {
var buffer bytes.Buffer
buffer.WriteByte(24)
for _, n := range naul {
l := len(n)
buffer.WriteByte(byte(l >> 8))
buffer.WriteByte(byte(l))
buffer.Write(n)
}
return buffer.Bytes()
}
var sequence uint16
var sub Subscriber
var sps []byte
var pps []byte
sub.ID = rtc.RemoteAddr
sub.Type = "WebRTC"
nextHeader := func(ts uint32, marker bool) rtp.Header {
sequence++
return rtp.Header{
Version: 2,
SSRC: ssrc,
PayloadType: DefaultPayloadTypeH264,
SequenceNumber: sequence,
Timestamp: ts,
Marker: marker,
}
}
stapA := func(naul ...[]byte) []byte {
var buffer bytes.Buffer
buffer.WriteByte(24)
for _, n := range naul {
l := len(n)
buffer.WriteByte(byte(l >> 8))
buffer.WriteByte(byte(l))
buffer.Write(n)
}
return buffer.Bytes()
}
// aud := []byte{0x09, 0x30}
sub.OnData = func(packet *avformat.SendPacket) error {
if packet.Type == avformat.FLV_TAG_TYPE_AUDIO {
return nil
// 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 := videoTrack.WriteRTP(&rtp.Packet{
Header: nextHeader(0, true),
Payload: stapA(sps, pps),
}); err != nil {
return err
}
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]
}
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
}
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{
Header: nextHeader(0, false),
Payload: stapA(sps, pps),
Header: nextHeader(packet.Timestamp*90, true),
Payload: _payload,
}); err != nil {
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
}
func (rtc *WebRTC) Publish(streamPath string) bool {
@@ -289,24 +294,13 @@ func (rtc *WebRTC) Publish(streamPath string) bool {
}
return true
}
func (rtc *WebRTC) GetAnswer(offer 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
}
func (rtc *WebRTC) GetAnswer(localSdp SessionDescription) ([]byte, error) {
// Sets the LocalDescription, and starts our UDP listeners
if err = rtc.SetLocalDescription(answer); err != nil {
if err := rtc.SetLocalDescription(localSdp); err != nil {
Println(err)
return nil, err
}
if bytes, err := json.Marshal(answer); err != nil {
if bytes, err := json.Marshal(localSdp); err != nil {
Println(err)
return bytes, err
} else {
@@ -316,17 +310,22 @@ func (rtc *WebRTC) GetAnswer(offer SessionDescription) ([]byte, error) {
func run() {
http.HandleFunc("/webrtc/play", func(w http.ResponseWriter, r *http.Request) {
streamPath := r.URL.Query().Get("streamPath")
offer := SessionDescription{}
bytes, err := ioutil.ReadAll(r.Body)
err = json.Unmarshal(bytes, &offer)
if err != nil {
Println(err)
return
}
// offer := SessionDescription{}
// bytes, err := ioutil.ReadAll(r.Body)
// err = json.Unmarshal(bytes, &offer)
// if err != nil {
// Println(err)
// return
// }
rtc := new(WebRTC)
rtc.RemoteAddr = r.RemoteAddr
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)
} else {
Println(err)
@@ -349,7 +348,16 @@ func run() {
rtc := new(WebRTC)
rtc.RemoteAddr = r.RemoteAddr
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)
} else {
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__) {
// extracted by mini-css-extract-plugin
/***/ }),
/***/ "c857":
/***/ "e91a":
/***/ (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_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_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__ = __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_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 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
/* 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&
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)])}
// 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._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 = []
// 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&
//
@@ -242,112 +242,123 @@ 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",
// ]
// }
]
}
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"
var stream = null;
var streamPath = "live/rtc";
/* harmony default export */ var Appvue_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
};
},
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));
}
});
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
};
},
stopSession(){
pc.close()
pc = new RTCPeerConnection(config)
this.remoteSDP = ""
this.localSDP = ""
this.connectICE().catch(err=> this.$toast.error(err.message))
methods: {
async startSession(type) {
this.type = type;
this.ask = true;
const result = await this.ajax({
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(){
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"];
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) {
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&
/* 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&
var Appvue_type_style_index_0_id_3d66f6b2_scoped_true_lang_css_ = __webpack_require__("c857");
// EXTERNAL MODULE: ./src/App.vue?vue&type=style&index=0&id=03ea1df8&scoped=true&lang=css&
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
/* globals __VUE_SSR_CONTEXT__ */
@@ -464,7 +475,7 @@ var component = normalizeComponent(
staticRenderFns,
false,
null,
"3d66f6b2",
"03ea1df8",
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__) {
// extracted by mini-css-extract-plugin
/***/ }),
/***/ "c857":
/***/ "e91a":
/***/ (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_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_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__ = __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_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 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
/* 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&
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)])}
// 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._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 = []
// 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&
//
@@ -251,112 +251,123 @@ 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",
// ]
// }
]
}
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"
var stream = null;
var streamPath = "live/rtc";
/* harmony default export */ var Appvue_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
};
},
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));
}
});
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
};
},
stopSession(){
pc.close()
pc = new RTCPeerConnection(config)
this.remoteSDP = ""
this.localSDP = ""
this.connectICE().catch(err=> this.$toast.error(err.message))
methods: {
async startSession(type) {
this.type = type;
this.ask = true;
const result = await this.ajax({
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(){
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"];
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) {
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&
/* 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&
var Appvue_type_style_index_0_id_3d66f6b2_scoped_true_lang_css_ = __webpack_require__("c857");
// EXTERNAL MODULE: ./src/App.vue?vue&type=style&index=0&id=03ea1df8&scoped=true&lang=css&
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
/* globals __VUE_SSR_CONTEXT__ */
@@ -473,7 +484,7 @@ var component = normalizeComponent(
staticRenderFns,
false,
null,
"3d66f6b2",
"03ea1df8",
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>
<div>
<pre v-if="$parent.titleTabActive == 1">{{localSDP}}</pre>
<pre v-else-if="$parent.titleTabActive == 2">{{remoteSDP}}</pre>
<div v-else>
<mu-text-field v-model="streamPath" label="streamPath"></mu-text-field>
<span class="blink" v-if="!localSDP || ask">Connecting</span>
<template v-else-if="iceConnectionState!='connected'">
<m-button @click="startSession('publish')">Publish</m-button>
<m-button @click="startSession('play')">Play</m-button>
</template>
<m-button @click="stopSession" v-else-if="iceConnectionState=='connected'">Stop</m-button>
<br />
<video ref="video1" :srcObject.prop="stream" width="640" height="480" autoplay muted></video>
<div>
<pre v-if="$parent.titleTabActive == 1">{{localSDP}}</pre>
<pre v-else-if="$parent.titleTabActive == 2">{{remoteSDP}}</pre>
<div v-else>
<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>
<br />
<video ref="video1" :srcObject.prop="stream" width="640" height="480" autoplay muted></video>
</div>
</div>
</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",
// ]
// }
]
}
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"
var stream = null;
var streamPath = "live/rtc";
export default {
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
};
},
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));
}
});
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
};
},
stopSession(){
pc.close()
pc = new RTCPeerConnection(config)
this.remoteSDP = ""
this.localSDP = ""
this.connectICE().catch(err=> this.$toast.error(err.message))
methods: {
async startSession(type) {
this.type = type;
this.ask = true;
const result = await this.ajax({
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(){
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"];
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) {
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>
<style scoped>
@keyframes blink {
@keyframes blink {
0% {
opacity: 0.2;
opacity: 0.2;
}
50% {
opacity: 1;
opacity: 1;
}
100% {
opacity: 0.2;
opacity: 0.2;
}
}
.blink {
}
.blink {
animation: blink 1s infinite;
}
}
</style>