跳到主要内容

通话控制

呼叫

RustPBX 支持 SIP 和 WebRTC 两种通话方式,在连接 RustPBX 时通过路径区分:

  • /call/sip: 使用 SIP 协议建立通话,RTP 传输音频。
  • /call/webrtc: 直接使用 SDP Offer 建立通话。

使用 Invite 命令发起呼叫。 当通话建立成功会收到 Answer 事件, 否则会收到 Reject 事件。

1: Invite
1: Invite
客户端
客户端
2: INVITE
2: INVITE
RustPBX
RustPBX
电话
电话
3: 200 OK
3: 200 OK
4. Answer
4. Answer
5. ACK
5. ACK
Text is not SVG - cannot display

呼叫和接听都使用 CallOption, 除设置被叫地址外,其他参数相同, 主要用于配置以下功能:

  • TTS: 文本转语音
  • ASR: 语音识别
  • VAD: 语音活动检测
  • 录音: 录音
  • denoise: 降噪

SIP 呼叫

SIP 呼叫需要在 CallOption 中设置主叫(caller)和被叫(callee) 的 SIP 地址,例:

{
"command": "invite",
"option": {
"caller": "sip:6001@192.168.1.100",
"callee": "sip:6002@192.168.1.100"
}
}

caller 地址可以设置为 UserAgent 的 SIP 地址, 默认为 sip:{本机IP}:13050

UserAgent 的 SIP 地址可以在 config.toml 中配置:

config.toml
[ua]
addr = "0.0.0.0"
udp_port = 13050 # 避免使用 5060
信息

UserAgent 相当于一个话机,因此他有自己的 SIP 地址。

WebRTC 呼叫

WebRTC 呼叫需要在 option.offer 字段中设置呼叫目标的 SDP Offer,例如:

{
"command": "invite",
"option": {
"offer": "v=0\r\no=- 123456789 2 IN IP4 127.0.0.1\r\n..."
}
}

接听/拒绝

接听比呼叫略微复杂,需要配置 Webhook 接收来电通知。有以下几个步骤:

  • 配置 Webhook
  • 当有来电时,RustPBX 会向 Webhook 地址发送请求
  • WebHook 服务根据请求中的 dialogId 连接 RustPBX
  • 发送 Accept 命令接听,或者 Reject 命令拒绝
2: WebHook
http://localhost:8090/webhook?dialogId: 666
2: WebHook...
客户端
客户端
1: INVITE
1: INVITE
RustPBX
RustPBX
电话
电话
5: 200 OK/603 Decline
5: 200 OK/603 Decline
3. 连接
ws://localhost:8080/call/sip?id=666
3. 连接...
5: ACK
5: ACK
4. Accept/Reject
4. Accept/Reject
Text is not SVG - cannot display

配置 Webhook

config.toml 中配置 Webhook 地址:

config.toml
[ua.handler]
type = "webhook"
url = "http://localhost:8090/webhook"
method = "POST"

接收通知

当有电话呼入时,RustPBX 会向 Webhook 地址发送 POST 请求, 例:

{
"event": "invite",
"dialogId": "9zUPiixVNO-xRTf4NqCV-dv9qE2iB",
"caller": "sip:6001@192.168.139.103",
"callee": "sip:192.168.3.197",
"createdAt": "2025-10-23T06:33:26.623706+00:00"
}
信息

dialogId 格式为: {call_id}-{tag1}-{tag2}, 其中 tag1from_tagto_tag 中的字典序较大者,tag2 为较小者。

连接 RustPBX

使用 dialogId 作为 id 参数的值,建立 WebSocket 连接

'ws://localhost:8080/call/sip?id=9zUPiixVNO-xRTf4NqCV-dv9qE2iB'

接听/拒绝

然后发送 Accept (接听) / Reject (拒绝) 命令 :

示例代码:

RustPBX Go SDK 中有 webhook 示例代码,可以参考:

cmd/webhook.go

func serveWebhook(parent context.Context, option CreateClientOption, addr, prefix string) {
server := gin.Default()
server.POST(prefix, func(c *gin.Context) {
var form IncomingCall
if err := c.ShouldBindJSON(&form); err != nil {
c.JSON(400, gin.H{"error": err.Error()})
return
}

client := createClient(parent, option, form.DialogID)

go func() {
ctx, cancel := context.WithCancel(parent)
defer cancel()
err := client.Connect("sip")
if err != nil {
option.Logger.Errorf("Failed to connect to server: %v", err)
}
defer client.Shutdown()

client.Accept(option.CallOption)
time.Sleep(300 * time.Millisecond)
client.TTS(option.Greeting, "", "", true, false, nil, nil, false)
<-ctx.Done()
}()

c.JSON(200, gin.H{"message": "OK"})
})
server.Run(addr)
}
信息

参阅 RustPBX Go SDK 获取更多信息。

转接

在通话中使用 Refer 命令可以将通话转接到另一个号码,用于"转人工"场景。

转接流程:

  • 通话已经建立, 发送 Refer 命令
  • RustPBX 呼叫转接目标
  • 目标接听后,RustPBX 互相转发两端音频
2. Refer
2. Refer
客户端
客户端
1. 通话
1. 通话
RustPBX
RustPBX
电话
电话
4. 200 OK
4. 200 OK
人工
人工
3. Invite
3. Invite
转发
转发
5. 通话
5. 通话
Text is not SVG - cannot display

挂断

在通话建立后,使用 Hangup 命令挂断通话。示例:

{
"command": "hangup",
"reason": "Normal clearing"
}

事件

在通话的建立到结束整个过程中,会触发多种事件,如图示:

电话
电话
UserAgent
UserAgent
INVITE
INVITE
BYE
BYE
4xx
4xx
200 OK
200 OK
200 OK
200 OK
事件
事件
Track Start Ringing Reject Answer Track End Hangup
180 Ringing
180 Ringing
Text is not SVG - cannot display

TrackStart

创建 RTP/WebRTC Track

Ringing

响铃事件, 对方已经收到呼叫,还未接听。

Answer

通话建立,对方已经接听。

Reject

对方拒绝,或其他 4xx 异常。

信息

请求失败响应码列表: Request Failure 4xx

Hangup

通话建立后,对方挂断。

TrackEnd

RTP/WebRTC Track 结束。

信息

TTS/Play 命令也会创建对应的 Track, 同样也会触发 TrackStart 和 TrackEnd 事件。可以用 TrackId 区分。

参见:TTS/Play

其他事件

ASR 和 VAD 功能会触发相应的事件,包括:

  • AsrDelta: 中间识别结果,内容可能会变动。
  • AsrFinal: 最终识别结果,内容稳定。
  • Speaking: 语音活动检测,有语音输入。
  • Silence: 语音活动检测,一段时间没有语音输入。

详见:ASRVAD