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:[email protected]"/>

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:[email protected]"/>

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:[email protected]"/>

還有:

<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:[email protected]"/>
</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:[email protected]"/>

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

讀到這裏,你還有錄像的問題嗎?

發佈了51 篇原創文章 · 獲贊 21 · 訪問量 4萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章