我正在尝试向客户进行自动呼叫,我已经设置好了freepbx并可以正常工作,现在我希望能够触发一些nodejs代码来进行呼叫,获取音频流并将其传递给dialogflow和根据对白流程响应,向客户播放MP3(或任何其他音频类型)。
我已经尝试过此软件包:
https://github.com/versatica/JsSIP
我可以稳定通话并获取音频流。是的,那很好,即使不是在浏览器中的html中也没有。。。但是我发现了!
https://github.com/versatica/jssip-node-websocket
看起来像我所有问题的答案,直到我尝试从自己的nodejs脚本发出呼叫为止,令人惊讶,它不起作用,甚至不打算起作用,它只是用于发送sip信号,但不能之所以打个电话,是因为该程序包在WebRTC上中继(仅在浏览器上运行)
然后我发现了这个问题:
Simple SIP phone in nodeJS without WebRTC
提到了一些名为sip的程序包,我需要尝试一下,哇,这是纯粹的sip通讯,对此我不太了解,但是经过大量工作之后,我设法连接到了我的freepbx,验证并拨打电话!!那时一切似乎都很好,但是现在...音频在哪里?
据我了解,在大量阅读sip之后,所有的媒体传输都是由RTP执行的,但是我的问题是,我该如何实现呢?我需要创建一些RTP媒体服务器来处理此问题,或者我需要做什么?非常感谢您对正确方向的任何帮助,澄清或指导,在此先感谢您,我的英语不好。
这是我当前的代码:
const sip = require('sip');
const util = require('util');
const digest = require('sip/digest');
const rstring = () => Math.floor(Math.random() * 1e6).toString();
sip.start({
publicAddress: 'My public IP Address',
tcp: false,
logger: {
send: (message, address) => {
debugger;
util.debug("send\n" + util.inspect(message, false, null));
},
recv: (message, address) => {
debugger;
util.debug("recv\n" + util.inspect(message, false, null));
},
error: (message, address) => {
debugger;
util.debug("ERROR\n" + util.inspect(message, false, null));
},
},
});
// Making the call
sip.send({
method: 'INVITE',
version: '2.0',
uri: 'sip:destination@domain.com',
headers: {
to: {
uri: 'sip:destination@domain.com',
},
from: {
uri: 'sip:origin@domain.com',
params: {
tag: rstring(),
},
},
'call-id': rstring(),
cseq: {
method: 'INVITE',
seq: Math.floor(Math.random() * 1e5),
},
'content-type': 'application/sdp',
contact: [
{
uri: 'origin@domain.com',
},
],
},
content: `v=0\r\no=- 234 1 IN IP4 PUBLIC.IP.ADDRESS\r\ns=-\r\nc=IN IP4 PUBLIC.IP.ADDRESS\r\nb=TIAS:13888000\r\nt=0 0\r\nm=audio PORT RTP/AVP 114 0 8 9 112 111 101\r\nb=TIAS:64000\r\nb=AS:64\r\na=rtpmap:114 opus/48000/2\r\na=fmtp:114 minptime=10; useinbandfec=1\r\na=rtpmap:0 PCMU/8000\r\na=rtpmap:8 PCMA/8000\r\na=rtpmap:9 G722/8000\r\na=rtpmap:112 ilbc/8000\r\na=rtpmap:111 speex/16000\r\na=rtpmap:101 telephone-event/8000\r\na=fmtp:101 0-15\r\na=sendrecv\r\na=rtcp:11801\r\na=ptime:20\r\n`,
},
(rs) => {
if (rs.status === 401) {
// sending ACK
const rq = {
method: 'INVITE',
version: '2.0',
uri: 'sip:destination@domain.com',
headers: {
to: {
uri: rs.headers.to.uri,
},
from: rs.headers.from,
'call-id': rs.headers['call-id'],
cseq: {
method: 'INVITE',
seq: rs.headers.cseq.seq + 1,
},
'content-type': 'application/sdp',
contact: [
{
uri: 'origin@domain.com',
},
],
},
content: `v=0\r\no=- 234 1 IN IP4 PUBLIC.IP.ADDRESS\r\ns=-\r\nc=IN IP4 PUBLIC.IP.ADDRESS\r\nb=TIAS:13888000\r\nt=0 0\r\nm=audio PORT RTP/AVP 114 0 8 9 112 111 101\r\nb=TIAS:64000\r\nb=AS:64\r\na=rtpmap:114 opus/48000/2\r\na=fmtp:114 minptime=10; useinbandfec=1\r\na=rtpmap:0 PCMU/8000\r\na=rtpmap:8 PCMA/8000\r\na=rtpmap:9 G722/8000\r\na=rtpmap:112 ilbc/8000\r\na=rtpmap:111 speex/16000\r\na=rtpmap:101 telephone-event/8000\r\na=fmtp:101 0-15\r\na=sendrecv\r\na=rtcp:11801\r\na=ptime:20\r\n`,
};
digest.signRequest(rs.headers['www-authenticate'][0], rq, rs, {
user: 'username',
password: 'password',
});
sip.send(rq);
} else {
process.exit(1);
}
});
答案 0 :(得分:2)
我遇到了同样的问题,但没有找到任何解决方案。因此,我分叉了sip.js并更改了源代码。有用!我在浏览器上使用了一些节点模块,而不是本机的websocket RTC API。 参见https://github.com/Winston87245/SIP.js。
根据https://tools.ietf.org/html/rfc3261第12页,您需要了解SIP(RFC 3261)和SDP(RFC 4566)的工作方式。
据我所知,当客户端A振铃后收到来自B的200 OK响应时,根据SDP的Client A(处于OK响应中)直接连接到Client B,不需要SIP代理。换句话说,它是一个P2P连接。您还需要了解ICE(RFC 8445)。
我希望这可以为您提供帮助。如有任何疑问,请随时与我联系。
答案 1 :(得分:0)
我知道使用星号的唯一方法。这是开源的SIP和RTP服务器等等。您只需要在nodejs中维护调用状态。将该Sip消息传递给Asterisk,并在sip标头中添加您自己的联系人,然后Asterisk将使用sdp负载将呼叫返回给您。
sdp有效负载告诉媒体服务器RTP在哪里以及如何通过网络从甲方传播到乙方,反之亦然。一旦sip连接建立,RTP流将根据sdp传输。
甲方 ==> Nodejs(sip.js) ==> 星号 ==> Nodejs(sip.js ) ==> 乙方
对于甲方和乙方,您可以使用XLite或任何其他VOIP拨号器。