HowTo文档
如何在XSwitch中对接SRS
SRS是一个简单、高效的优秀的开源实时音视频服务器,支持 RTMP/WebRTC/HLS/HTTP-FLV/SRT/MPEG-DASH/GB28181、Linux/Windows/macOS、X86_64/ARMv7/AARCH64/M1/RISCV/LOONGARCH/MIPS 等协议和技术。
本文假定你已经熟悉SRS,也假定你已经熟悉XSwitch。如果你还不熟悉SRS,请参阅文末的链接查看SRS文档,如果你还不熟悉XSwitch,可以试试XSwitch快速入门。
背景
FreeSWITCH是一个开源的软交换平台和MCU,而SRS是一个开源的实时音视频服务器和SFU。很久之前通过RTMP对接过SRS。现在SRS已支持WebRTC以及WHIP协议,在SRS创始人winlin的推动下,我们开始了相关的对接工作。
为什么要对接?因为FreeSWITCH和SRS各有所长。这就像大家经常问到的问题一样——SRS是否能实现MCU呢?FreeSWITCH是否能实现SFU功能?其实答案都是一样的——能,但是为什么要实现?理论上,只要有足够的if-else
,任何功能都可以实现,但任何实现都需要考虑实现成本和维护成本。其实从漫长的软件生命周期来说,开源软件的生命周期还是比较长的,相对而言,软件的维护成本比开发成本更高。SRS在级联、直播、低延迟直播等场景已经做得很好了,而且还有Janus、Kurento、MediaSoup、Poin等各种SFU,FreeSWITCH再去做意义就不是很大,同理,SRS本身也不是很有必要自己实现一个MCU。各自把自己擅长的部分做好。
具体计划是,先在XSwitch中对接SRS。XSwitch是基于FreeSWITCH做的商业化产品,XSwitch中已经有了很多WHIP和WebRTC相关的支持,因此实现起来比较简单。等实现初步的对接流程后,我们会实现一个开源的模块,让使用开源版本的FreeSWITCH用户也可以对接SRS,SRS用户也可以使用FreeSWITCH作为MCU。
本文仅讨论XSwitch与SRS的对接。可以使用XSwitch社区版免费测试。
架构和流程
XSwitch相当于传统的软交换系统和MCU,一个SDP可以支持双向的推拉流。而SRS的推拉流是分开的,推和拉分别需要一个SDP。
SRS和FreeSWITCH都是服务器端的软件,因此,谁从谁推拉流就有两种实现方式。
XSwitch从SRS推拉流
XSwitch作为客户端向SRS推流,从SRS拉流。如下图。
其中,红色代表推流,蓝色代表拉流,黑色是双向流。
SRS从XSwitch推拉流
XSwitch也支持WHIP协议,但SRS尚未实现客户端模式的推拉流。
关于XSwitch中的WHIP推拉流,详见如何在XSwitch中使用WebRTC 。
启动SRS
启动镜像:
export CANDIDATE="192.168.x.x"
docker run --rm -it -d --name srs -p 1935:1935 -p 1985:1985 -p 8080:8080 --env CANDIDATE=$CANDIDATE -p 8000:8000/udp ossrs/srs:6 ./objs/srs -c conf/docker.conf
打开 http://localhost:8080/ 可以查看SRS的Web页面,上面有推拉流相关的Demo。一般使用livestream
这个流进行演示。
注意:,SRS在6.0.52
以下的版本中有个Bug会导致Crash,参见 https://github.com/ossrs/srs/pull/3591 。
如果你不使用Docker,也可以使用以下命令自行编译运行:
git clone -b develop https://gitee.com/ossrs/srs.git &&
cd srs/trunk && ./configure && make && ./objs/srs -c conf/srs.conf
在Windwows页面推流
在使用windows页面使用localhost推流,需要在操作系统做如下配置
查看本地设置netsh.exe interface portproxy show all
# 设置
netsh.exe interface portproxy add v4tov4 listenaddress=127.0.0.1 listenport=8080 connectaddress=192.168.0.1 connectport=8080
netsh.exe interface portproxy add v4tov4 listenaddress=127.0.0.1 listenport=1985 connectaddress=192.168.0.1 connectport=1985
netsh.exe interface portproxy add v4tov4 listenaddress=127.0.0.1 listenport=8000 connectaddress=192.168.0.1 connectport=8000
# 清除
netsh.exe interface portproxy delete v4tov4 listenaddress=127.0.0.1 listenport=8080
netsh.exe interface portproxy delete v4tov4 listenaddress=127.0.0.1 listenport=1985
netsh.exe interface portproxy delete v4tov4 listenaddress=127.0.0.1 listenport=8000
启动XSwitch
参见XSwitch入门 及 XSwitch下载安装指南 安装XSwitch,并熟悉XSwitch的使用。注意:XSwitch 6.0.0以上的版本才支持SRS对接,推荐使用6.0.7以上版本。
xrtc Endpoint
XSwitch中实现了一个xrtc Endpoint,除XSwitch标准Endpoint参数外,还支持如下参数:
video_use_audio_ice
:在Bundle模式,视频使用音频的ICE绑定信息。rtp_payload_space
:指定视频的RTP载荷值,不指定有时候会有冲突。absolute_codec_string
:音视频编码,一般为OPUS,H264
,在呼叫字符串中使用时其中的逗号要使用\
转义。url
:SRS 推拉流 URL。
XSwitch推流到SRS
XSwitch是一个软交换平台和MCU。SRS对接在XSwitch内实现为一个Endpoint。
推流,从本地mp4文件中读取视频流:
bgapi originate {video_use_audio_ice=true,rtp_payload_space=106,absolute_codec_string=OPUS\,H264,url=http://localhost:1985/rtc/v1/whip/?app=live&stream=livestream}xrtc/auto_answer &playback(/tmp/test.mp4)
呼叫一个null
Channel,桥接到SRS推流:
bgapi originate {null_video_codec=H264}null/1234 &bridge({video_use_audio_ice=true,rtp_payload_space=106,absolute_codec_string=OPUS\,H264,url=http://localhost:1985/rtc/v1/whip/?app=live&stream=livestream}xrtc/auto_answer)
如果你手上有SIP视频话机,可以将一个视频话机(如1006)的视频流推给SRS,如:
bgapi originate user/1006 &bridge({video_use_audio_ice=true,rtp_payload_space=106,absolute_codec_string=OPUS\,H264,url=http://localhost:1985/rtc/v1/whip/?app=live&stream=livestream}xrtc/auto_answer)
除上述命令外,你也可以直接在视频话机上发起呼叫。呼叫前确保XSwitch中有相应的路由。如,在XSwitch中,添加一个路由:
- 目的地:
livestream
- 最大号长:
10
- 目的地类型:系统
- 目的地:代码如下
bridge {video_use_audio_ice=true,rtp_payload_space=106,absolute_codec_string=OPUS\,H264,url=http://localhost:1985/rtc/v1/whip/?app=live&stream=livestream}xrtc/auto_answer
直接使用视频话机呼叫livestream
,可以直接推流到SRS的livestream
流。
可以通过以下方法在SRS侧观看视频流:
WHEP Play:http://localhost:1985/rtc/v1/whip-play/?app=live&stream=livestream
通过RTC播放器可以查看拉流效果:webrtc://localhost/live/livestream
XSwitch拉流
- RTC推流到:
webrtc://localhost/3000/livestream
- WHIP Publish:
http://localhost:1985/rtc/v1/whip/?app=3000&stream=livestream
可以在XSwitch中使用命令拉流到视频会议,其中3000
是视频会议号:
conference 3000 bgdial {video_use_audio_ice=true,rtp_payload_space=106,absolute_codec_string=OPUS\,H264,url=http://localhost:1985/rtc/v1/whip-play/?app=3000&stream=livestream}xrtc/auto_answer
注意:上面仅是简单的会议,在XSwitch中,会议名称是形如:会议号-域
这样的格式,如3000-xswitch.cn
。
通过Webhook自动将SRS流拉到XSwitch视频会议中
上面的命令都是手工执行的,用起来比较笨。为了让整套系统聪明一点,可以在SRS侧配置Webhook,这样,当SRS侧有人推流时,XSwitch可以自动启动会议,并把相应的流拉入会议。
要配置SRS的Webhook,使用以下步骤:
启动SRS镜像并进入Shell:
export CANDIDATE="192.168.x.x"
docker run --rm -it -d --name srs -p 1935:1935 -p 1985:1985 -p 8080:8080 --env CANDIDATE=$CANDIDATE -p 8000:8000/udp ossrs/srs:v6.0.36 bash
修改/usr/local/srs/conf/docker.conf
,在vhost
下增加callback相关配置:
http_hooks {
enabled on;
on_publish http://xswitch:8081/api/whip/srs;
on_unpublish http://xswitch:8081/api/whip/srs;
}
运行SRS:
/usr/local/srs/objs/srs -c conf/docker.conf
在SRS侧推流,会调用http_hooks
回调,XSwitch会收到on_publish
回调,收到后XSwitch会自动拉流到跟流同名的视频会议。
注意,为了能在XSwitch中接收Webhook请求,需要在xtra_config.lua
中开启srs_api_url
配置项。目前,开启该参数后XSwitch侧对/api/whip/srs
没有鉴权,请注意保护。
开启后,在XSwitch侧使用SIP终端呼叫会议号3000
,会自动进入会议3000-xswitch.cn
。在SRS侧推流:
- app:
3000-xswitch.cn
- stream:
livestream
或其他
注意:不同的推流终端用不同的stream
以免冲突,用相同的app
以便加入同一个会议。
控制时序图大致如下图所示,其中箭头方向为控制信号发送请求的方向,不是流的发送方向。
使用
如果你不使用完整版的XSwitch,也可以使用不带UI的XSwitch。xswitch-free 是小樱桃科技推出的免费版Docker镜像,可以用于在没有UI的情况下测试XSwitch的各种功能。
简单推拉流
可以使用上述XSwitch中同样的命令推拉流。
配置verto.conf添加Webhook Handler
启动 xswitch-free docker,参见 https://github.com/rts-cn/xswitch-free
弹出配置文件:
make eject
在verto.conf中添加HTTP配置,参见:http://rts.cn/freeswitch/FreeSWITCH-Explained/Modules/mod-verto/RESTful-Verto_8454242/#docusaurus_skipToContent_fallback
<vhosts>
<vhost domain="localhost">
<param name="alias" value="seven.local freeswitch.org"/>
<!-- <param name="root" value="/usr/local/freeswitch/htdocs"/> -->
<!-- <param name="script_root" value="/usr/local/freeswitch/scripts"/> -->
<param name="index" value="index.html"/>
<!--
<param name="auth-realm" value="FreeSWITCH"/>
<param name="auth-user" value="freeswitch"/>
<param name="auth-pass" value="rocks"/>
-->
<rewrites>
<rule expression="^/api" value="whip.lua"/>
</rewrites>
</vhost>
--[[
Restful by Seven Du.
GET /channels
GET /channels/uuid
POST /channels
PUT /channels/uuid
DELETE /channels/uuid
DELETE /channels
]]
function headers()
stream:write("HTTP/1.0 200 OK\r\n")
if (accept == "application/json") then
stream:write("Content-Type: application/json\r\n")
else
stream:write("Content-Type: text/plain\r\n")
end
stream:write("\r\n")
end
-- print(env:serialize())
api = freeswitch.API()
method = env:getHeader("Request-Method")
http_uri = env:getHeader("HTTP-Request-URI")
http_query = env:getHeader("HTTP-QUERY")
accept = env:getHeader("Accept")
uuid = string.sub(http_uri, "11") -- remove /channels/ from uri
freeswitch.consoleLog("ERR", "[" .. method .. "]\n")
-- freeswitch.consoleLog("ERR", http_uri .. "\n")
-- freeswitch.consoleLog("ERR", http_query .. "\n")
if (method == "GET") then
ret = "OK I'm FreeSWITCH MCU"
elseif (method == "POST") then
dialstr = "{}xrtc/auto_answer"
print(dialstr)
ret = api:execute("originate", dialstr)
...
end
headers()
stream:write(ret .. "\n")
重启Docker,在SRS侧添加Webhook。
以上只是一个示例,如果你用于生产环境,可以使用一个真正的Web服务器接收Web请求,并通过ESL或XCC等API控制FreeSWITCH打开xrtc Channel加入一个会议。
XSwitch实现的API接口:https://docs.xswitch.cn/dev-guide/api/ ,供大家参考实现。
其他
XSwitch的默认配置有一些安全设置,不允许任意的人任意的流进入视频会议,因此,您可能需要多熟悉一下XSwitch。如果有任何问题,欢迎给我产反馈。
如果你需要一个开源的FreeSWITCH解决方案,可以看这里:http://freeswitch.org.cn/blog/2023/08/use_srs/ 。
参考
- SRS:https://ossrs.net/lts/zh-cn/docs/v5/doc/introduction
- Get Started:https://ossrs.net/lts/zh-cn/docs/v4/doc/getting-started
- SRS与FreeSWITCH集成:https://github.com/ossrs/srs/issues/3459 以及 https://github.com/ossrs/srs/discussions/3625
- SRS Callback:https://ossrs.net/lts/zh-cn/docs/v4/doc/http-callback
- SRS Unity Player:https://github.com/ossrs/srs-unity#usage-player