FreeSWITCH之视频录像

我们今天来说说视频录像吧。

我们先看例子 default/0020_record…..xml,我们一行一行的讲。


<condition field="destination_number" expression="^(6080)$">

匹配被叫号码6080

<action application="export" data="nolocal:absolute_codec_string=OPUS,VP8"/>

设置B-Leg的编码是OPUS和VP8。

<action application="set" data="hangup_after_bridge=true"/>

说过很多次了。如果不明白,看《FreeSWITCH权威指南》,跟视频无关。

<action application="set" data="record_concat_video=true"/>

这样通道变量与eavesdrop_concat_video类似,就是把两路视频合成到一块。

<!--
DO NOT EXPORT execute_on_answer in this case.
It will cause both sessions to record to the exact same file.
-->
<action application="set" data="execute_on_answer=record_session /var/www/html/rec/${strftime(%Y%m%d_%H%M%S)}_${destination_number}.mp4"/>

在A-Leg上设置execute_on_answer,即当应答时开始录像。不要用export同时设置到两条腿上,那样两腿同时录到同一个文件名会有冲突(当然,你可以尝试两腿分别录到不同的文件名)。

<action application="bridge" data="sofia/external/sip:decode@cantina.freeswitch.org"/>

bridge B-Leg。其中,这里的B-Leg是FreeSWITCH官方提供的一个测试服务,如果你打不通,可以自己试一个测试账号或服务器,如你当然可以改成 bridge user/b 或者自己启动另外一个FreeSWITCH作为B-Leg。其中,上述的测试服务也是一台FreeSWITCH,它使用了decode_video这个App,表面上看,它跟echo一样,但是它会对视频解码,在控制台上能看到相关的日志。

再看一个例子:


<condition field="destination_number" expression="^(6081)$">
<action application="export" data="nolocal:absolute_codec_string=OPUS,VP8"/>
<action application="set" data="hangup_after_bridge=true"/>
<action application="set" data="record_concat_video=true"/>

这回被叫是6081。其它跟上面一样。

<action application="record_session" data="/var/www/html/rec/${strftime(%Y%m%d_%H%M%S)}_${destination_number}.mp4"/>

直接调用了record_session,而没有用execute_on_answer,也就是说,从最开始的Early Media阶段就开始录。

<action application="bridge" data="sofia/external/sip:decode@cantina.freeswitch.org"/>

bridge产生B-Leg。



下一个:

<condition field="destination_number" expression="^(6082)$">
<action application="export" data="nolocal:absolute_codec_string=OPUS,VP8"/>
<action application="set" data="hangup_after_bridge=true"/>
<action application="set" data="record_concat_video=true"/>
<action application="answer"/>

跟上一个几乎一样,只是,在录像前先应答A-Leg。

<action application="record_session"
data="/var/www/html/rec/${strftime(%Y%m%d_%H%M%S)}_${destination_number}.mp4"/>
<action application="bridge" data="sofia/external/sip:decode@cantina.freeswitch.org"/>

还有:

<condition field="destination_number" expression="^(6083)$">
<action application="set" data="hangup_after_bridge=true"/>
<action application="export" data="record_concat_video=true"/>
<!-- Shouldn't bind the same file name to both legs,
if both press *2 it clobbers the file -->
<!-- bind_meta_app can have these args <key> [a|b|ab] [a|b|o|s] -->
<action application="bind_meta_app" data="2 a i record_session::/var/www/html/rec/${strftime(%Y%m%d_%H%M%S)}_${destination_number}_a.mp4"/>
<action application="bind_meta_app" data="2 b i record_session::/var/www/html/rec/${strftime(%Y%m%d_%H%M%S)}_${destination_number}_b.mp4"/>
<action application="bridge" data="{sip_h_X-Send-DTMF=*2}sofia/external/sip:decode@cantina.freeswitch.org"/>
</condition>
</extension>

<extension name="test5">
<condition field="destination_number" expression="^(6084)$">
<action application="set" data="hangup_after_bridge=true"/>
<!-- Shouldn't bind the same file name to both legs,
if both press *2 it clobbers the file -->
<!-- bind_meta_app can have these args <key> [a|b|ab] [a|b|o|s] -->
<action application="bind_meta_app" data="2 a i record_session::/var/www/html/rec/${strftime(%Y%m%d_%H%M%S)}_${destination_number}_a.mp4"/>
<action application="bind_meta_app" data="2 b i record_session::/var/www/html/rec/${strftime(%Y%m%d_%H%M%S)}_${destination_number}_b.mp4"/>

分别在A-Leg和B-Leg上绑定一个按键,当在通话中按下*2时,就会自动录像。需要注意使用两个不同的文件名,防止双方都按下*2时相同的文件名相互打架。

<action application="bridge" data="{sip_h_X-Send-DTMF=*2}sofia/external/sip:decode@cantina.freeswitch.org"/>

bridge产生B-Leg。

讲完了。视频录像其实就是这么简单。

但为什么好多小朋友录像都遇到问题呢?那我就再说几句。

先从录音说起。基本的录音方式有两种,阻塞的和不阻塞的。

阻塞的是record,它会阻塞,因而只能录A-Leg。
不阻塞的是record_session,它会在内部启动一个新线程,启动一个Media Bug进行录音,Dialplan会继续执行,因而可以用brdige产生B-Leg,这样通话的双方就都能录上。

再说视频。其实视频没什么好说的,因为,还是上面两个App,如果有了视频,就能自动录像了,只不过如果是非阻塞的还需要启动一个视频的Media Bug。但,无论如何,其实你不需要关心这些,因为所有这一切都是那么自然而然的发生了,你只需要在参数中把文件扩展名写成mp4即可。

所以,如果你看懂了《FreeSWITCH权威指南》,以不变应万变,到了视频,也不会有任何问题。

也有人有问题,那就是FreeSWITCH还有一个App,就做record_fsv。

record_fsv是一个黑客级的解决方案。话说那时候FreeSWITCH不能进行视频解码,因而,FreeSWITCH就机械地把收到的视频RTP包放到一个文件里,等播放的时候,再用play_fsv从视频文件里取出来,直接通过RTP发出去。由于这是一个非通用的解决方案,所以,FreeSWITCH使用了自己的视频文件格式,扩展名是.fsv,FreeSWITCH Video的缩写。

record_fsv是阻塞的,因而,你不能使用record_session录像。我们前面说了,如果想用record_session录像,就需要视频的Media Bug。

说到mp4了,还有故事。

FreeSWITCH官方版里的mp4录像,最早是在mod_vlc里实现的。但是,后来我们发现,用mod_vlc播放mp4还行,录像效果不好,很难控制,提供的API极其难用。后来,我就实现了mod_av(最早叫mod_ffmpeg)。这个模块我写了好几年,ffmpeg的API变化很大,改来改去无数次,最后一次改动是他们分裂出了libav,FreeSWITCH里的mod_av是基于libav的,因为Debian上用的是libav。当然,我们也希望它能跟ffmpeg兼容,但还没有收到报告谁在ffmpeg基础上编译通过了。

好吧,这不是两个模块都支持mp4了么。其实还有一个,那就是人们念念不忘的mod_mp4v2。

这么多模块都实现了mp4,你需要做的就是,在用的时候只加载其中一个,否则,你不确定系统在用哪个。

但如果FreeSWITCH不能同时加载那些模块那FreeSWITCH就太弱了。其实,FreeSWITCH不弱的。

你可以选择用mod_av录像,只需要在文件名前加上相应的协议名就可以了,如

record av:///tmp/test.mp4
record vlc:///tmp/test.mp4

mod_mp4v2还没有实现这样「协议」,你愿意试一试提交个小补丁么?

那,如果没有人提交补丁怎么办?就没办法了吗?

有,FreeSWITCH怎么会让你没办法,这样写

record {modname=mod_mp4v2}/tmp/test.mp4

读到这里,你还有录像的问题吗?

阅读更多
文章标签: freeswitch 录像
所属专栏: freeswitch
上一篇CentOS---网络配置详解
下一篇freeswitch+webrtc
想对作者说点什么? 我来说一句

没有更多推荐了,返回首页

关闭
关闭