随着视频监控应用的发展,涌现了大量的监控平台提供商,它们的接入协议各不相同,对不同厂商设备集中调阅的复杂度越来越高。在这样的产业背景下,GB/T28181 应运而生。
GB28181 定义了基于 SIP(会话初始协议)、SDP(会话描述协议)等协议的互联规范,安全注册、实时视音频点播等应用基于 SIP REGISTER、INVITE 等请求和响应方法。
配置 XSwitch 分机
进入【呼叫】⇨【分机】,新建一个分机,根据协议统一编码规则,应创建 20 位十进制数字字符号码,比如:34020000001320000005。
点击新创建的分机,进入分机详情页,修改类型
为海康摄像头
,这样在呼叫该监控时,XSwitch 会自动添加Subject
消息头域以及正确的 SDP 信息。
需要说明一下,GB28181 设备或者平台一般不认域名,创建分机时需要单独配置一下域,一般取分机号码前 10 位即可。
监控摄像头配置
以海康摄像头为例,进入【配置】⇨【网络】⇨【高级配置】⇨【平台接入】,选择平台接入方式为28181
,同时配置 SIP 服务器地址端口、用户名、ID、密码,启用并保存配置即可。
如果注册状态显示为在线
则表示注册成功,如下图:
* 这里需要记住该处配置的SIP 服务器 ID
,呼叫摄像头进行实时点播时会用到。
实时音视频点播
点播场景可以获取到设备的音视频,注意,设备是sendonly
。如果想获取到设备的音频,设备需要选择复合流
,否则 PS 流中只有视频。
路由配置
进入【呼叫】⇨【路由】,新建一条路由:
hk
,也可以随意340
,根据上文提到的编码规则default
20
本地分机
同时需要在号码变换中修改主叫号码变换为34020000001320000001
。
注意:
此处的主叫号码应该设置为上文中提及的SIP 服务器 ID
,否则呼叫时,可能会收到415 Unsupported Media Type
.
xTalk
或者 SIP 视频电话直接呼叫监控分机即可。如果你想在终端fs_cli
发起呼叫,可以直接:
bgapi originate {origination_caller_id_number=34020000001320000001}user/34020000001320000005 &conference(3000)
上述命令只有在分机类型选择为海康摄像头时才好用。
其实完整的命令应该是这样的:
bgapi originate {origination_caller_id_number=34020000001320000001,sip_h_Subject=34020000001320000005:0\,34020000001320000001:0,absolute_codec_string=PS}user/34020000001320000005 &conference(3000)
Subject各字段含义分别为媒体流发送者设备编码:发送端媒体流序列号,媒体流接收者设备编码:接收端媒体流序列号。
其中,媒体流发送者指的是摄像头,接收端指的是 XSwitch。
另外,我们看到这里设置的absolute_codec_string
为PS
,因此你需要检查一下 XSwitch 中是否已经成功加载mod_ps
。
如果对协商过程感兴趣,可以在终端fs_cli
开启sofia global siptrace on
或者参考 GB28181-2016 附录部分。
recvonly
。MESSAGE
消息 Notify 设备,设备回复MESSAGE
Response 后,会主动发送INVITE
,所以需要配置对应的路由。进入【呼叫】⇨【路由】新建一条路由,其中被叫号码为前文提及的SIP 服务器 ID
,如果对接的是平台,真正的主叫设备 ID 在INVITE
头部Subject
字段中,from 则为平台注册到 XSwitch 的号码,平台会管理很多设备。
MESSAGE 参考:
MESSAGE sip:34020000001320000005@192.168.3.98:5060 SIP/2.0
Via: SIP/2.0/UDP 192.168.3.200;rport;branch=z9hG4bK1ap14K9Bmvrcg
Route: <sip:34020000001320000005@192.168.3.98:5060>
Max-Forwards: 70
From: "34020000001320000001" <sip:34020000001320000001@140.143.134.19:10160>;tag=1pN12ray0F6Ha
To: <sip:34020000001320000005@192.168.3.98:5060>
Call-ID: 6dcee39e-820d-4204-b890-8500b838188d
CSeq: 59825685 MESSAGE
User-Agent: FreeSWITCH-mod_sofia/1.10.8-dev+git~20221102T021101Z~fcab6ea333~64bit
Allow: INVITE, ACK, BYE, CANCEL, OPTIONS, MESSAGE, INFO, UPDATE, REGISTER, REFER, NOTIFY, PUBLISH, SUBSCRIBE
Supported: timer, path, replaces
Content-Type: Application/MANSCDP+xml
Content-Length: 185
X-FS-Sending-Message: 63e5e877-2fb6-4467-98ac-33de4cdd890a
<?xml version="1.0"?>
<Notify>
<CmdType>Broadcast</CmdType>
<SN>111</SN>
<SourceID>34020000001320000001</SourceID>
<TargetID>34020000001320000005</TargetID>
</Notify>
INVITE 参考:
INVITE sip:34020000001320000001@192.168.3.200:5060 SIP/2.0
Via: SIP/2.0/UDP 192.168.3.98:5060;rport;branch=z9hG4bK621100893
From: <sip:34020000001320000005@192.168.3.98:5060>;tag=1324899375
To: <sip:34020000001320000001@192.168.3.200:5060>
Call-ID: 1063016033
CSeq: 20 INVITE
Contact: <sip:34020000001320000005@192.168.3.98:5060>
Content-Type: application/sdp
Max-Forwards: 70
User-Agent: IP Camera
Subject: 34020000001320000001:1,34020000001320000005:2
Content-Length: 214
v=0
o=34020000001320000005 2260 2260 IN IP4 192.168.3.98
s=Play
c=IN IP4 192.168.3.98
t=0 0
m=audio 15062 RTP/AVP 8 96
a=recvonly
a=rtpmap:8 PCMA/8000
a=rtpmap:96 PS/90000
y=0200000017
f=v/////a/1/8/1
发送MESSAGE
lua 脚本参考 broadcast.lua:
local body = ''
local sn = '111'
local source_id = '34020000001320000001' -- 服务器编码 ID
local device_id = '34020000001320000005' -- 设备编码 ID
local to = '34020000001320000005' -- 平台注册到 FS 的号码(对接平台时为下级平台编码)或者跟 device_id 相同(直接对接设备)
local api = freeswitch.API()
local domain = api:execute("global_getvar", "domain")
body = '<?xml version="1.0" encoding="GB2312"?>\n' ..
'<Notify>\n<CmdType>Broadcast</CmdType>\n<SN>'.. sn ..'</SN>\n<SourceID>' .. source_id ..'</SourceID>\n<TargetID>' .. device_id .. '</TargetID>\n' ..
'</Notify>\n'
local event = freeswitch.Event("Custom", "SMS::SEND_MESSAGE");
event:addHeader('type', 'Application/MANSCDP+xml')
-- 对接平台时,平台可能不认 from 中的 domain
-- event:addHeader('from', source_id .. '@local_sip_ip:local_sip_port')
event:addHeader('from', source_id .. '@' .. domain)
event:addHeader('to', to .. '@' .. domain)
event:addHeader('sip_profile', 'default')
event:addHeader('dest_proto', 'sip')
event:addBody(body)
event:fire();
conference
来实现。首先,点播设备:
conference 3000 bgdial {origination_caller_id_number=34020000001320000001,sip_h_Subject=34020100001320000005:0\,34020000001320000001:0,absolute_codec_string=PS,conference_member_flags=mute}user/34020000001320000005
发起广播,需要将广播来话路由到同一个 conference 中:
lua broadcast.lua
呼叫普通 SIP 终端:
conference 3000 bgdial user/1009
由于点播+广播是两路呼叫,设备在 conference 中存在两个成员,这样点播到的音频会再次广播给设备,设备会啸叫。需要单独处理一下,点播设备时设置conference_member_flags=mute
,这样谁也听不到设备的声音,然后:
conference 3000 relate id1 id2 nohear
conference 3000 unmute all
其中:id1
对应广播成员,id2
对应点播成员。
至此,对讲完成。
本文分享自 FreeSWITCH中文社区 微信公众号,前往查看
如有侵权,请联系 cloudcommunity@tencent.com 删除。
本文参与 腾讯云自媒体同步曝光计划 ,欢迎热爱写作的你一起参与!