事情经过是这样的,公司最近准备搞一个移动端的项目,里面需要集成打电话功能(就是可以从页面直接打电话类型微信语音的感觉),最先考虑到是移动端项目(h5)就采用的uniapp,但电话播出去后却出现了h5无声音,但被叫端有声音。其中使用到audio 的srcObject属性,经自己实验得知uniapp的audio没有srcObject属性,故无法使用uniapp来实现该功能。我将源码复制到vue项目中,就不存在单通的问题。故决定将uniapp项目调整为vue2 + vantui的h5项目。贴上关键代码,方便日后有需求可以查看
JSSIP版本:“jssip”: “^3.3.11”
该代码不涉及接听电话
<template>
<div>
<button @click="startCall">拨打</button>
<audio id="audioElement"></audio>
</div>
</template>
<script>
import JsSIP from "jssip";
export default {
data() {
return {
ua: null,
};
},
created() {
this.handleUA();
},
methods: {
startCall() {
this.ua.call("phonenum", your_options);
},
//初始化配置
initConfig() {
// Create our JsSIP instance and run it:
const socket = new JsSIP.WebSocketInterface('your_fs_wss_url’);
const configuration = {
sockets: [socket],
uri: `sip:${your mobile}@${your_fs_register_url}`,
authorization_user: 'your mobile',
password: this.userInfo.mobile,
// WebSocket重新连接调度之间的最大间隔(秒)。默认值是30。
connection_recovery_max_interval: 300,
// WebSocket重新连接尝试之间的最小间隔(秒)。默认值是2。
connection_recovery_min_interval: 10,
// String 注册到fs显示的url
contact_uri: `sip:${your mobile}@${your_fs_register_url};transport=wss`,
// 外显
display_name: this.org.id,
// 来电后,120秒内未接听,将会拒绝.默认60s
no_answer_timeout: 120,
// 会话计时器,默认true
session_timers: false,
// 用于刷新会话计时器的SIP方法。有效值是UPDATE或INVITE。默认值是UPDATE。
session_timers_refresh_method: "invite",
// 是否应该在启动时自动注册.默认true
register: true,
// 注册过期时间(秒) 默认值是600。
register_expires: 7200,
// User-Agent header中的值,默认是JsSIP
user_agent: "your_user_agent",
registrar_server: `sip:${your_fs_register_url}`,
};
this.ua = new JsSIP.UA(configuration);
},
handleUA() {
this.initConfig();
this.ua.start();
if (!this.ua.isRegistered()) {
//未注册的情况下
this.ua.register();
}
if (this.ua.isConnected()) {
console.log("软电话已连接");
}
this.ua.on("registered", (data) => {
console.log("软电话认证成功");
});
this.ua.on("registrationFailed", (data) => {
console.log("软电话认证失败");
});
// 新来会话
this.ua.on("newRTCSession", function (data) {
let originator = data.originator;
let session = data.session;
//连接中
session.on("connecting", (data) => {
console.log("建立连接中");
});
// 连接已接受
session.on("accepted", () => {
console.log("连接已接受");
});
// 接通,在这一步可以处理音频播放
// 接通并不代表对方已经接受,接通代表 滴 滴 滴
session.on("confirmed", () => {
console.log("接通中");
const audioElement = document.getElementById("audioElement");
audioElement.autoplay = true;
const stream = new MediaStream();
const receivers = session.connection?.getReceivers();
if (receivers)
receivers.forEach((receiver) => stream.addTrack(receiver.track));
console.log("audioElement.srcObject2", "srcObject" in audioElement);
audioElement.srcObject = stream;
// 最后都要播放
audioElement.play();
});
// 结束
session.on("ended", () => {
console.log("通话结束");
});
// 失败
session.on("failed", () => {
console.log("失败");
});
// 手动让打孔结束,最多4次,有时候等待时间会很长
let iceCandidateCount = 0;
session.on("icecandidate", (data) => {
if (iceCandidateCount++ > 4) data.ready();
});
});
},
},
};
</script>