JsSIP外呼时"peerconnection"事件未触发且无法听到远端声音的原因及解决方法
兄弟,我特别理解你遇到这种情况的糟心——外呼能发起但听不到对方声音,连peerconnection事件都没触发,这排查起来确实挠头。结合我处理过的类似问题,给你梳理几个最可能的原因和解决办法:
事件绑定时机完全错了
这是最常见的坑!很多人会在调用ua.call()发起呼叫之后,才去给会话绑定peerconnection事件,但这个事件在会话初始化的早期就已经触发了,等你绑的时候黄花菜都凉了。
正确的做法是提前监听新会话的创建事件,在会话刚生成的时候就把peerconnection事件绑上:// 先监听UA的newRTCSession事件,提前捕获新会话 ua.on('newRTCSession', (session) => { // 在这里立刻绑定peerconnection事件,绝对不会错过 session.on('peerconnection', (peerconnection) => { console.log('终于等到PeerConnection了!', peerconnection); // 顺便在这里处理远端音频流,解决听不到声音的问题 peerconnection.ontrack = (event) => { const remoteAudio = document.getElementById('remote-audio'); remoteAudio.srcObject = event.streams[0]; }; }); }); // 之后再发起呼叫 const targetNumber = '1001'; const session = ua.call(targetNumber, callOptions);要是你之前是在
ua.call()之后才绑session.on('peerconnection', ...),那肯定监听不到,赶紧改过来试试。媒体约束没配置对,或者权限没拿到
外呼时如果没明确告诉JsSIP你需要音频,浏览器也没给麦克风权限,那PeerConnection根本建不起来,peerconnection自然不会触发,声音更别想了。
发起呼叫时一定要传正确的媒体约束:const callOptions = { mediaConstraints: { audio: true, // 必须明确开启音频,这是核心 video: false // 语音电话就设为false } }; const session = ua.call(targetNumber, callOptions);另外记得检查浏览器的麦克风权限,要是之前拒绝过,去设置里重新允许,不然媒体流初始化直接失败。
SDP协商出问题了
有时候不是你的代码错了,是SIP服务器返回的SDP有问题——比如没包含音频媒体行,或者用了浏览器不支持的编码格式。
你可以开JsSIP的调试日志看看详细过程,在代码开头加一句:JsSIP.debug.enable('JsSIP:*');然后打开浏览器控制台,搜SDP相关的日志,看看offer和answer里有没有
m=audio的行,编码格式是不是PCMU、OPUS这种浏览器支持的。要是服务器的SDP有问题,得找运维或者服务器配置的人调。没处理远端音频流,或者音频元素有问题
就算peerconnection触发了,要是你没把远端的音频流绑定到页面的audio元素上,还是听不到声音。除了刚才在peerconnection事件里用ontrack处理,也可以用会话的addstream事件(JsSIP 3.x也支持):session.on('addstream', (event) => { const remoteAudio = document.getElementById('remote-audio'); remoteAudio.srcObject = event.stream; });还要检查你的audio元素:有没有正确创建?是不是被设成静音了?音量是不是0?这些细节别漏了。
漏了会话错误事件监听
有时候呼叫过程中已经出了错,但你没监听,根本不知道问题在哪。给会话多绑几个错误和状态事件,能帮你快速定位:session.on('failed', (data) => { console.error('呼叫失败原因:', data.cause); }); session.on('sdp', (data) => { console.log('SDP协商日志:', data.type, data.sdp); });比如
failed事件会告诉你是“媒体协商失败”还是“服务器无响应”,比瞎猜强多了。
备注:内容来源于stack exchange,提问作者Subhan Chaudhry

