|
@@ -13,6 +13,7 @@
|
|
>
|
|
>
|
|
{{ number }}
|
|
{{ number }}
|
|
</el-button>
|
|
</el-button>
|
|
|
|
+ <audio v-show="false" controls autoplay="autoplay" id="audioCtl"></audio>
|
|
</div>
|
|
</div>
|
|
<!-- 语音输入按钮 -->
|
|
<!-- 语音输入按钮 -->
|
|
<el-button type="info" @click="startVoiceInput"> 语音输入 </el-button>
|
|
<el-button type="info" @click="startVoiceInput"> 语音输入 </el-button>
|
|
@@ -35,11 +36,23 @@ export default {
|
|
},
|
|
},
|
|
data() {
|
|
data() {
|
|
return {
|
|
return {
|
|
|
|
+ id: this.generateGuid(),
|
|
|
|
+ baseUrl: "api/webrtc/",
|
|
|
|
+ pc: null,
|
|
// 拨号盘上的数字和符号
|
|
// 拨号盘上的数字和符号
|
|
numbers: ["1", "2", "3", "4", "5", "6", "7", "8", "9", "*", "0", "#"],
|
|
numbers: ["1", "2", "3", "4", "5", "6", "7", "8", "9", "*", "0", "#"],
|
|
};
|
|
};
|
|
},
|
|
},
|
|
computed: {
|
|
computed: {
|
|
|
|
+ getOfferUrl() {
|
|
|
|
+ return `${this.baseUrl}getoffer?id=${this.id}`;
|
|
|
|
+ },
|
|
|
|
+ setAnswerUrl() {
|
|
|
|
+ return `${this.baseUrl}setanswer?id=${this.id}`;
|
|
|
|
+ },
|
|
|
|
+ setIceCandidateUrl() {
|
|
|
|
+ return `${this.baseUrl}addicecandidate?id=${this.id}`;
|
|
|
|
+ },
|
|
currentPhoneNumber: {
|
|
currentPhoneNumber: {
|
|
get() {
|
|
get() {
|
|
return this.phoneNumber;
|
|
return this.phoneNumber;
|
|
@@ -60,10 +73,14 @@ export default {
|
|
callNumber() {
|
|
callNumber() {
|
|
if (this.currentPhoneNumber) {
|
|
if (this.currentPhoneNumber) {
|
|
alert(`正在拨打号码: ${this.currentPhoneNumber}`);
|
|
alert(`正在拨打号码: ${this.currentPhoneNumber}`);
|
|
|
|
+ this.start();
|
|
} else {
|
|
} else {
|
|
alert("请输入电话号码");
|
|
alert("请输入电话号码");
|
|
}
|
|
}
|
|
},
|
|
},
|
|
|
|
+ downNumber() {
|
|
|
|
+ this.closePeer();
|
|
|
|
+ },
|
|
startVoiceInput() {
|
|
startVoiceInput() {
|
|
const recognition = new (window.SpeechRecognition ||
|
|
const recognition = new (window.SpeechRecognition ||
|
|
window.webkitSpeechRecognition)();
|
|
window.webkitSpeechRecognition)();
|
|
@@ -75,6 +92,93 @@ export default {
|
|
};
|
|
};
|
|
recognition.start();
|
|
recognition.start();
|
|
},
|
|
},
|
|
|
|
+
|
|
|
|
+ generateGuid() {
|
|
|
|
+ return "xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx".replace(
|
|
|
|
+ /[xy]/g,
|
|
|
|
+ function (c) {
|
|
|
|
+ var r = (Math.random() * 16) | 0,
|
|
|
|
+ v = c == "x" ? r : (r & 0x3) | 0x8;
|
|
|
|
+ return v.toString(16);
|
|
|
|
+ }
|
|
|
|
+ );
|
|
|
|
+ },
|
|
|
|
+ async start() {
|
|
|
|
+ this.closePeer();
|
|
|
|
+
|
|
|
|
+ let videoControl = document.querySelector("#audioCtl");
|
|
|
|
+
|
|
|
|
+ const localStream = await navigator.mediaDevices.getUserMedia({
|
|
|
|
+ video: false,
|
|
|
|
+ audio: true,
|
|
|
|
+ });
|
|
|
|
+ videoControl.srcObject = localStream;
|
|
|
|
+
|
|
|
|
+ this.pc = new RTCPeerConnection(null);
|
|
|
|
+
|
|
|
|
+ localStream.getTracks().forEach((track) => {
|
|
|
|
+ console.log("add local track " + track.kind + " to peer connection.");
|
|
|
|
+ console.log(track);
|
|
|
|
+ this.pc.addTrack(track, localStream);
|
|
|
|
+ });
|
|
|
|
+
|
|
|
|
+ this.pc.onicegatheringstatechange = function () {
|
|
|
|
+ console.log("onicegatheringstatechange: " + this.pc.iceGatheringState);
|
|
|
|
+ }.bind(this);
|
|
|
|
+
|
|
|
|
+ this.pc.oniceconnectionstatechange = function () {
|
|
|
|
+ console.log(
|
|
|
|
+ "oniceconnectionstatechange: " + this.pc.iceConnectionState
|
|
|
|
+ );
|
|
|
|
+ }.bind(this);
|
|
|
|
+
|
|
|
|
+ this.pc.onsignalingstatechange = function () {
|
|
|
|
+ console.log("onsignalingstatechange: " + this.pc.signalingState);
|
|
|
|
+ }.bind(this);
|
|
|
|
+
|
|
|
|
+ this.pc.onicecandidate = async function (event) {
|
|
|
|
+ if (event.candidate) {
|
|
|
|
+ console.log("new-ice-candidate:");
|
|
|
|
+ console.log(event.candidate.candidate);
|
|
|
|
+ console.log(event.candidate);
|
|
|
|
+ await fetch(this.setIceCandidateUrl, {
|
|
|
|
+ method: "POST",
|
|
|
|
+ body: JSON.stringify(event.candidate),
|
|
|
|
+ headers: { "Content-Type": "application/json" },
|
|
|
|
+ });
|
|
|
|
+ }
|
|
|
|
+ }.bind(this);
|
|
|
|
+
|
|
|
|
+ let offerResponse = await fetch(this.getOfferUrl);
|
|
|
|
+ let offer = await offerResponse.json();
|
|
|
|
+ console.log("got offer: " + offer.type + " " + offer.sdp + ".");
|
|
|
|
+ await this.pc.setRemoteDescription(offer);
|
|
|
|
+
|
|
|
|
+ this.pc
|
|
|
|
+ .createAnswer()
|
|
|
|
+ .then(
|
|
|
|
+ function (answer) {
|
|
|
|
+ return this.pc.setLocalDescription(answer);
|
|
|
|
+ }.bind(this)
|
|
|
|
+ )
|
|
|
|
+ .then(
|
|
|
|
+ async function () {
|
|
|
|
+ console.log("Sending answer SDP.");
|
|
|
|
+ console.log("SDP: " + this.pc.localDescription.sdp);
|
|
|
|
+ await fetch(this.setAnswerUrl, {
|
|
|
|
+ method: "POST",
|
|
|
|
+ body: JSON.stringify(this.pc.localDescription),
|
|
|
|
+ headers: { "Content-Type": "application/json" },
|
|
|
|
+ });
|
|
|
|
+ }.bind(this)
|
|
|
|
+ );
|
|
|
|
+ },
|
|
|
|
+ closePeer() {
|
|
|
|
+ if (this.pc != null) {
|
|
|
|
+ console.log("close peer");
|
|
|
|
+ this.pc.close();
|
|
|
|
+ }
|
|
|
|
+ },
|
|
},
|
|
},
|
|
};
|
|
};
|
|
</script>
|
|
</script>
|