sudo ./freeswitch -nc -nonat
sudo ./fs_cli
load mod_av
load mod_verto
1.default
sudo vim /usr/local/freeswitch/conf/dialplan/default.xml
cpp
<extension name="cdquality_conferences">
<condition field="destination_number" expression="^(35\d{2})$">
<action application="answer"/>
<action application="set" data="conference_member_flags=moderator"/>
<action application="conference" data="$1@video-mcu-stereo"/>
</condition>
</extension>
原本如下,以上是指定为moderator,指定后verto界面会多显示信息,比如有几人在会议,设置布局等,这样设置后所有呼叫35开头的比如3500都是管理员了,可以自定义的精确设置。从以上信息可以看出来,只有呼叫35开头的才会进入会议,数据为mcu的视频数据。
cpp
<action application="set" data="conference_member_flags=join-vid-floor"/>
修改后在fs_cli中执行:
cpp
reloadxml
cpp
<!-- STEREO 48kHz conferences / Video MCU -->
<extension name="cdquality_stereo_conferences">
<condition field="destination_number" expression="^(35\d{2}).*?-screen$">
<action application="answer"/>
<action application="send_display" data="FreeSWITCH Conference|$1"/>
//可以设置共享进来就是floor,如果是up_top布局,就是最大的位置
//<action application="set" data="conference_member_flags=join-vid-floor"/>
<action application="set" data="conference_member_flags=moderator"/>
<action application="conference" data="$1@video-mcu-stereo"/>
</condition>
</extension>
屏幕分享走的是上面的代码,看见默认设置进来之后就是管理员。
sudo vim /usr/local/freeswitch/conf/autoload_configs/conference_layouts.conf.xml
cpp
</layout>
<layout name="2x2" auto-3d-position="true">
<image x="0" y="0" scale="180"/>
<image x="180" y="0" scale="180"/>
<image x="0" y="180" scale="180"/>
<image x="180" y="180" scale="180"/>
</layout>
FS把画布横向和纵向都分为360份,也就是360x360个小画布,上面有4个image,第一个image从(0,0)开始,宽高都是180x180,scale代表宽高都占180个刻度。
在终端中执行可以改变画布(conference后table就会出现会议号)
cpp
<layout name="1up_top_left+5" auto-3d-position="true">
//floor代表画面大的
<image x="0" y="0" scale="240" floor="true"/>
<image x="240" y="0" scale="120"/>
<image x="240" y="120" scale="120"/>
<image x="0" y="240" scale="120"/>
<image x="120" y="240" scale="120"/>
<image x="240" y="240" scale="120"/>
</layout>
cpp
conference 3500 vid-layout 2x2
conference 3500 vid-layout 1up_top_left+5
FS的默认配置如下,不同数的人打进来,自动切换成不同的layout。
cpp
<group name="grid">
<layout>1x1</layout>
<layout>2x1</layout>
<layout>1x1+2x1</layout>
<layout>2x2</layout>
<layout>3x3</layout>
<layout>4x4</layout>
<layout>5x5</layout>
<layout>6x6</layout>
<layout>8x8</layout>
</group>
sudo vim /usr/local/freeswitch/conf/autoload_configs/conference.conf.xml
cpp
<profile name="video-mcu-stereo">
<param name="domain" value="$${domain}"/>
<param name="rate" value="48000"/>
<param name="channels" value="2"/>
<param name="interval" value="20"/>
<param name="energy-level" value="200"/>
<!-- <param name="tts-engine" value="flite"/> -->
<!-- <param name="tts-voice" value="kal16"/> -->
<param name="muted-sound" value="conference/conf-muted.wav"/>
<param name="unmuted-sound" value="conference/conf-unmuted.wav"/>
<param name="alone-sound" value="conference/conf-alone.wav"/>
<param name="moh-sound" value="$${hold_music}"/>
<param name="enter-sound" value="tone_stream://%(200,0,500,600,700)"/>
<param name="exit-sound" value="tone_stream://%(500,0,300,200,100,50,25)"/>
<param name="kicked-sound" value="conference/conf-kicked.wav"/>
<param name="locked-sound" value="conference/conf-locked.wav"/>
<param name="is-locked-sound" value="conference/conf-is-locked.wav"/>
<param name="is-unlocked-sound" value="conference/conf-is-unlocked.wav"/>
<param name="pin-sound" value="conference/conf-pin.wav"/>
<param name="bad-pin-sound" value="conference/conf-bad-pin.wav"/>
<param name="caller-id-name" value="$${outbound_caller_name}"/>
<param name="caller-id-number" value="$${outbound_caller_id}"/>
//数字噪音,如果房间就你一个人,有噪音你知道视频还在继续,音频电话需要,视频可以关闭
<param name="comfort-noise" value="false"/>
//minimize-video-encoding指定只编码一路融屏流,不然100个客户端,会编100路
<param name="conference-flags" value="livearray-json-status|json-events|video-floor-only|rfc-4579|livearray-sync|minimize-video-encoding|manage-inbound-video-bitrate|video-required-for-canvas|video-mute-exit-canvas|mute-detect"/>
<param name="video-auto-floor-msec" value="1000"/>
<param name="video-mode" value="mux"/>
//设置多画布
//<param name="canvas-count" value="2"/>
<param name="video-layout-name" value="3x3"/>
<param name="video-layout-name" value="group:grid"/>
<param name="video-canvas-size" value="1920x1080"/>
//画布背景色,默认是灰色的
<param name="video-canvas-bgcolor" value="#333333"/>
<param name="video-layout-bgcolor" value="#000000"/>
//默认3M带宽
<param name="video-codec-bandwidth" value="3mb"/>
//不管进来多少,每s编码30帧画布
<param name="video-fps" value="30"/>
<!-- <param name="video-codec-config-profile-name" value="conference"/> -->
</profile>
可以看到默认使用的是group:grid,上面还有对视频帧率,分辨率,音频参数的设置,各种铃声的设置,interval间隔设置,其中"mux"就是指mcu。
1.default中的
cpp
<action application="conference" data="$1@video-mcu-stereo"/>
指定运行了这段代码
conference + 回车,就可以看到conference支持的各种命令
静音
cpp
conference 3500 mute all
恢复声音
cpp
conference 3500 unmute all
conference list
cpp
+OK Conference 3500 (2 members rate: 48000 flags: running|answered|enforce_min|dynamic|exit_sound|enter_sound|video_floor_only|video_rfc4579|livearray_sync|transcode_video|video_muxing|minimize_video_encoding|manage_inbound_bitrate|json_status|video_required_for_canvas)
2;verto.rtc/3500;b73a81f5-0793-0a52-2290-9020495f552c;9002;1163720462@qq.com;hear|speak|video;0;0;200
1;verto.rtc/3500;31ac85d6-95f5-03fc-87f0-5810ee649f54;123;1163720468@qq.com;hear|speak|video|floor|vid-floor;0;0;200
其中1和2是FS分配给用户的id,是递增的,可以用这个id,控制用户如:
cpp
conference 3500 mute 2
把正在播放的视频关掉
cpp
conference 3500 stop all
播放一个视频,这个视频会多个路视频流贴到画布上,播放的视频floor="true",默认是up_top画布,也就是最大。
cpp
conference 3500 play /home/yqw/juren-30s.mp4
也可以播放pdf
cpp
conference 3500 play /home/yqw/test.pdf
但需要添加模块
cpp
cd /freeswitch/src/mod/formats/mod_imagick
make install
pdf翻页功能
cpp
conference 3500 file_seek +1
将id为1的流设置为floor,如果floor已经被其他成员占用,force则强制设置。此时如果是up_top布局的画,floor就是最大的。
cpp
conference 3500 vid-floor 1 force
把1画布的流放到4画布上,如果4有流则交换
cpp
conference 3500 vid-layer 1 4
列出所有可用的布局
cpp
conference 3500 vid-layout list
cpp
<true|false>
<conf name> count //会议有多少人
<conf name> list [delim <string>]|[count]
<conf name> xml_list //xml格式的list
<conf name> json_list [compact]//会把各种属性都列举出来
<conf name> energy <member_id|all|last|non_moderator> [<newval>]
<conf name> auto-energy <member_id|all|last|non_moderator> [<newval>]
<conf name> max-energy <member_id|all|last|non_moderator> [<newval>]
//给某个id设置自动增益
<conf name> agc <member_id|all|last|non_moderator> [<newval>]
//FS支持多个画布
//设置id放在哪个画布上
<conf name> vid-canvas <member_id|all|last|non_moderator> [<newval>]
//观看哪个画布
<conf name> vid-watching-canvas <member_id|all|last|non_moder ator> [<newval>]
//overlay,比如2x2就是四个层,选择把哪个层放到哪个层上
<conf name> vid-layer <member_id|all|last|non_moderator> [<newval>]
//调声音
<conf name> volume_in <member_id|all|last|non_moderator> [<newval>]
<conf name> volume_out <member_id|all|last|non_moderator> [<newval>]
//调位置,可以听到声音的方位
<conf name> position <member_id> <x>:<y>:<z>
//自动
<conf name> auto-3d-position [on|off]
<conf name> play <file_path> [async|<member_id> [nomux]]
<conf name> moh <file_path>|toggle|[on|off]
//暂停播放上面的文件
<conf name> pause [<member_id>]
<conf name> play_status [<member_id>]
//音频视频pdf的快近快退
<conf name> file_seek [+-]<val> [<member_id>]
//说一段文本
<conf name> say <text>
//专门对莫个人说
<conf name> saymember <member_id> <text>
<conf name> cam
//停止播放,可指定
<conf name> stop <[current|all|async|last]> [<member_id>]
//可以发一个dtmf信号,比如通话中按数字就是发不同波段的dtmf信号,接收端根据信号确定对应的数字
<conf name> dtmf <[member_id|all|last|non_moderator]> <digits>
//踢出id
<conf name> kick <[member_id|all|last|non_moderator]> [<optional sound file>]
//视频翻转
<conf name> vid-flip <[member_id|all|last|non_moderator]>
<conf name> vid-border <[member_id|all|last|non_moderator]>
//让id挂掉电话
<conf name> hup <[member_id|all|last|non_moderator]>
<conf name> hold <[member_id|all]|last|non_moderator> [file]
<conf name> unhold <[member_id|all]|last|non_moderator>
<conf name> mute <[member_id|all]|last|non_moderator> [<quiet>]
静音/不静音切换
<conf name> tmute <[member_id|all]|last|non_moderator> [<quiet>]
<conf name> unmute <[member_id|all]|last|non_moderator> [<quiet>]
//视频的关掉
<conf name> vmute <[member_id|all]|last|non_moderator> [<quiet>]
//视频关掉/不关掉切换
<conf name> tvmute <[member_id|all]|last|non_moderator> [<quiet>]
//视频的快照
<conf name> vmute-snap <[member_id|all]|last|non_moderator>
<conf name> unvmute <[member_id|all]|last|non_moderator> [<quiet>]
//让id看不见
<conf name> vblind <[member_id|all]|last|non_moderator> [<quiet>]
<conf name> tvblind <[member_id|all]|last|non_moderator> [<quiet>]
<conf name> unvblind <[member_id|all]|last|non_moderator> [<quiet>]
//听不见,让id听不见
<conf name> deaf <[member_id|all]|last|non_moderator>
<conf name> undeaf <[member_id|all]|last|non_moderator>
//滤镜,有抠图,画中画功能
<conf name> vid-filter <[member_id|all]|last|non_moderator> <string>
//id间建立关系,比如我说话只让张三听到
<conf name> relate <member_id>[,<member_id>] <other_member_id>[,<other_member_id>] [nospeak|nohear|clear]
<conf name> getvar <varname>
<conf name> setvar <varname> <value>
//锁定了别人就呼不进来
<conf name> lock
<conf name> unlock
//从会议里面往外呼
<conf name> dial <endpoint_module_name>/<destination> <callerid number> <callerid name>
//异步往外呼
<conf name> bgdial <endpoint_module_name>/<destination> <callerid number> <callerid name>
//转移到另外一个会议里面
<conf name> transfer <conference_name> <member id> [...<member id>]
//录像,需要load mod_av才能支持mp4,rtmp等格式
<conf name> record <filename>
<conf name> chkrecord <confname>
//停止录像
<conf name> norecord <[filename|all]>
<conf name> pause <filename>
<conf name> resume <filename>
<conf name> recording [start|stop|check|pause|resume] [<filename>|all]
<conf name> exit_sound on|off|none|file <filename>
<conf name> enter_sound on|off|none|file <filename>
<conf name> pin <pin#>
<conf name> nopin
<conf name> get <parameter-name>
<conf name> set <max_members|sound_prefix|caller_id_name|caller_id_number|endconference_grace_time> <value>
<conf name> file-vol <vol#>
<conf name> floor <member_id|last>
<conf name> vid-floor <member_id|last> [force]
//在id下设置一个文字,比如名字,conference 3500 vid-banner 1 yqw
<conf name> vid-banner <member_id|last> <text>
//关掉流后显示一个img
<conf name> vid-mute-img <member_id|last> [<path>|clear]
//在id上显示log
<conf name> vid-logo-img <member_id|last> [<path>|clear]
//同时用多个编码器,比如vp8,264,因为解码端支持不同
<conf name> vid-codec-group <member_id|last> [<group>|clear]
//占位,设置某个画布只能有某路含vid-res-id的人才能占
<conf name> vid-res-id <member_id>|all <val>|clear [force]
//跟上面差不多
<conf name> vid-role-id <member_id|last> <val>|clear
<conf name> get-uuid <member_id|last>
//除去floor
<conf name> clear-vid-floor
<conf name> vid-layout <layout name>|group <group name> [<canvas id>]
//抓拍成png
<conf name> vid-write-png <path>
//改帧率
<conf name> vid-fps <fps>
<conf name> vid-res <WxH>
<conf name> vid-fgimg <file> | clear [<canvas-id>]
<conf name> vid-bgimg <file> | clear [<canvas-id>]
//改带宽
<conf name> vid-bandwidth <BW>
//给某个人设置分辨率,有些客户端性低下,设置小分辨率
<conf name> vid-personal [on|off]
sudo vim /usr/local/freeswitch/conf/autoload_configs/verto.conf.xml
cpp
<profiles>
<profile name="default-v4">
<param name="bind-local" value="$${local_ip_v4}:8081"/>
<param name="bind-local" value="$${local_ip_v4}:8082" secure="true"/>
<param name="force-register-domain" value="$${domain}"/>
<param name="secure-combined" value="$${certs_dir}/wss.pem"/>
<param name="secure-chain" value="$${certs_dir}/wss.pem"/>
<param name="userauth" value="true"/>
<!-- setting this to true will allow anyone to register even with no account so use with care -->
<param name="blind-reg" value="false"/>
<param name="mcast-ip" value="224.1.1.1"/>
<param name="mcast-port" value="1337"/>
<param name="rtp-ip" value="$${local_ip_v4}"/>
<param name="ext-rtp-ip" value="$${external_rtp_ip}"/>
<param name="local-network" value="localnet.auto"/>
<param name="outbound-codec-string" value="opus,h264,vp8"/>
<param name="inbound-codec-string" value="opus,h264,vp8"/>
<param name="apply-candidate-acl" value="localnet.auto"/>
<param name="apply-candidate-acl" value="wan_v4.auto"/>
<param name="apply-candidate-acl" value="rfc1918.auto"/>
<param name="apply-candidate-acl" value="any_v4.auto"/>
<param name="timer-name" value="soft"/>
<vhosts>
<vhost domain="localhost">
<param name="alias" value="seven.local freeswitch.org"/>
<param name="root" value="/home/yqw/temp/FS/github/freeswitch-1.10.0/html5/verto/video_demo"/>
<!-- <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="/my_custom_api.lua"/>
<rule expression="^/channels" value="/rest.lua"/>
</rewrites>
</vhost>
</vhosts>
</profile>
可以看到默认监听的8001和8002端口,secure="true"说明是wss的,需要用websocket,如果改成false可能不太好用。https和wss都是加密,webrtc规定需要是安全性的媒体才能发送。
可以看到和之间添加了http的虚拟服务器,添加后,FS本身就变成了一个http服务器,那么它现在又支持websocket又支持http。
以上配置参考杜老师提交的FS官方WIKI
可以看到它的地址指向/home/yqw/temp/FS/github/freeswitch-1.10.0/html5/verto/video_demo,因此需要编译video_demo应用,如下
cpp
cd freeswitch-1.10.0/html5/verto/js
make
在fs_cli客户端加载
cpp
load mod_verto
完成后,用firefox打开https://yourIP:8082,这里需要访问google的一些数据,所以网络要通www.google.com才行。
freeswitch-1.10.0/html5/verto下有两个demo
verto_communicator 用安格瑞写的
video_demo 用jequre写的