`
haoningabc
  • 浏览: 1478015 次
  • 性别: Icon_minigender_1
  • 来自: 北京
社区版块
存档分类
最新评论

freeswitch的helloworld

    博客分类:
  • sip
阅读更多

########
客户端mac用yate
ios用 adore sip client



############### asr
vim  modules.con
asr_tts/mod_pocketsphinx

make mod_pocketsphinx-install


freeswitch/etc/freeswitch/autoload_configs/modules.conf.xml
 <!-- ASR /TTS -->
    <load module="mod_flite"/>
    <load module="mod_pocketsphinx"/>
    <!-- <load module="mod_cepstral"/> -->
    <load module="mod_tts_commandline"/>
    <!-- <load module="mod_rss"/> -->

如果没有这个就要手工
load mod_flite
load mod_pocketsphinx

freeswitch/etc/freeswitch/dialplan/default.xml
<extension name="ASR">
      <condition field="destination_number" expression="^1235$">
        <action application="answer" />
        <action application="set" data="tts_engine=flite" />
        <action application="set" data="tts_voice=kal" />
        <action application="play_and_detect_speech" data="say:'please say yes or no hahaha' detect:pocketsphinx yes_no"/>
        <action application="log" data="INFO ${detect_speeck_result}" />
      </condition>
    </extension>




freeswitch/share/freeswitch/grammar/yes_no.gram
#JSGF V1.0;

/**
  * JSGF Grammar for names
  */

grammar example;


<yes> = [ yes ];
<no> = [ no ];

public <result> = [ <yes> | <no> ] ;


启动拨打1235

在log中查看freeswitch/var/log/freeswitch/freeswitch.log

e0266345-e1de-4f19-9352-88d52a92f028 2019-05-23 15:09:20.530197 [INFO] switch_ivr_async.c:4460 (sofia/internal/1006@192.168.0.100) START OF SPEECH
2019-05-23 15:09:21.750191 [DEBUG] mod_pocketsphinx.c:464 Recognized: no, Confidence: 100, Confidence-Threshold: 0
e0266345-e1de-4f19-9352-88d52a92f028 2019-05-23 15:09:21.770121 [INFO] switch_ivr_async.c:4450 (sofia/internal/1006@192.168.0.100) DETECTED SPEECH


识别出yes或no


#########中文asr识别###########

需要的中文 tdt_sc_8k在
git clone https://github.com/skerit/cmusphinx
cd cmusphinx-master/pocketsphinx/model/hmm/zh
把tdt_sc_8k放在
/usr/local/freeswitch/share/freeswitch/grammar/model


freeswitch/etc/freeswitch/autoload_configs/pocketsphinx.conf.xml

<param name="narrowband-model" value="tdt_sc_8k"/>
<!--<param name="wideband-model" value="wsj1"/>-->
<!--<param name="dictionary" value="default.dic"/>-->
<param name="dictionary" value="zh_broadcastnews_utf8.dic"/>


需要字典
zh_broadcastnews_utf8.dic
参考
https://www.jianshu.com/p/f5d0b6bcea68
https://github.com/znstj/mrobot_speech

考到
freeswitch/share/freeswitch/grammar/zh_broadcastnews_utf8.dic

cp zh.gram  /usr/local/freeswitch/share/freeswitch/grammar
#JSGF V1.0;

/**
  * JSGF Grammar for names
  */

grammar names;


<du> = 杜;
<jin> = 金;
<fang> = 房;
<孙> = 孙;
<中> = 中;
<山> = 山;

public <jf> = <jin><fang>;
public <djf> = <du><jin><fang>;
public <szs> = <孙> <中> <山>;


asr.lua 放到freeswitch/share/freeswitch/scripts





#########录音及播放
录音
originate user/1006 &record(/tmp/welcome.wav)

播放
originate user/1006 &playback(/tmp/welcome.wav)

#执行lua
把test.lua放入
/usr/local/freeswitch/share/freeswitch/scripts

originate user/1006 &lua(test.lua)

session:answer()
session:sleep(1000)
session:streamFile("/tmp/welcome.wav")
session:hangup()




如果是在命令行直接执行lua
freeswitch@bogon> lua /tmp/api.lua
api = freeswitch.API()
reply = api:execute("version", "")
freeswitch.consoleLog("INFO", "Got reply:\n\n" .. reply .. "\n")



##########javascript脚本######
brew install v8
安装目录
vim modules.conf
打开mod_v8

make mod_v8-install


#################


##################
编译tts模块
需要在源码目录的modules.conf
打开注释
#asr_tts/mod_cepstral
asr_tts/mod_flite
#asr_tts/mod_pocketsphinx
asr_tts/mod_tts_commandline

asr_tts/mod_unimrcp

freeswitch安装完之后
make install 

make mod_flite-install


进行安装

freeswitch的命令行


一定要load
load mod_flite




freeswitch>originate user/1005 &speak('flite|rms|Hello,welcome to freeswitch,haha,I am haoning')


freeswitch/etc/freeswitch/dialplan/default.xml加入
<extension name="TTS">
    <condition field="destination_number" expression="1234">
      <action application="answer" />
      <action application="speak" data="flite|rms|Hello,welcome to freeswitch,haha,I am haoning"/>
    </condition>
</extension>


拨打1234测试
################

编译目录
vim modules.conf
#asr_tts/mod_cepstral
asr_tts/mod_flite
#asr_tts/mod_pocketsphinx
asr_tts/mod_tts_commandline



make mod_tts_commandline-install

autoload_configs/tts_commandline.conf.xml
<settings>
 <!--<param name="command" value="echo ${text} | text2wave -f ${rate} > ${file}"/>-->
    <param name="command" value="say -v ${voice} -o ${file}.aiff ${text}; sox ${file}.aiff ${file}; rm -f ${file}.aiff"/>
</settings>

freeswitch/etc/freeswitch/dialplan/default.xml 修改
<extension name="TTS">
  <condition field="destination_number" expression="^1234$">
    <action application="answer" />
    <action application="set" data="tts_engine=tts_commandline" />
    <action application="set" data="tts_voice=Ting-Ting" />
    <action application="speak" data="欢迎使用freeswitch,我是小美"/>
  </condition>
</extension>


load mod_tts_commandline

拨打1234测试

如果想不load
freeswitch/etc/freeswitch/autoload_configs/modules.conf.xml
打开tts注释

###############
vim modules.conf
asr_tts/mod_unimrcp
make mod_unimrcp-install






########################
aws上的

centos7安装


https://freeswitch.org/confluence/display/FREESWITCH/CentOS+7+and+RHEL+7
yum install -y http://files.freeswitch.org/freeswitch-release-1-6.noarch.rpm epel-release
yum install -y freeswitch-config-vanilla freeswitch-lang-* freeswitch-sounds-*

tts:
yum list|grep freeswitch
yum install freeswitch-asrtts-flite
yum install freeswitch-asrtts-tts-commandline asrtts-unimrcp -y

systemctl enable freeswitch
systemctl start freeswitch

客户端进入
fs_cli -rRS




可能会有https://files.freeswitch.org/yum-1.6/7server/x86_64/repodata/repomd.xml 找不到的问题
可能是7Server的问题,需要修改repo,把$releasever 改成 7server小写的



由于内ip和公网ip不一样,电话通了但是没声音
公网电话通了但是没声音:
https://blog.csdn.net/hry2015/article/details/78388839

/etc/freeswitch/sip_profiles/internal.xml
    <!--<param name="ext-rtp-ip" value="auto-nat"/>-->
    <param name="ext-rtp-ip" value="13.231.152.115"/>
    <!--<param name="ext-sip-ip" value="auto-nat"/>-->
    <param name="ext-sip-ip" value="13.231.152.115"/>


启用internal配置文件
vars.xml:
<X-PRE-PROCESS cmd="set" data="default_password=1234"/>
<!--<X-PRE-PROCESS cmd="set" data="use_profile=external"/>-->
<X-PRE-PROCESS cmd="set" data="use_profile=internal"/>



internal.xml中的accept-blind-reg与accept-blind-auth 均为true!这样可以做到自注册!
<domain name="all" alias="true" parse="true"/>


ios客户端用ador sip client

两个手机登录后,用户用1001和1005
查看用户

sofia status profile internal reg


###########################

jssip:
https://blog.csdn.net/foruok/article/details/74321214


#########################

mac安装
https://freeswitch.org/confluence/display/FREESWITCH/macOS+Manual+Installation


一定要安装libtool 
brew install libtool
会有glibtool 和glibtoolize 生成


brew install autoconf automake curl jpeg ldns libsndfile libtiff libtool lua openssl opus pcre pkg-config speex speexdsp sqlite signalwire/homebrew-signalwire/flite signalwire/homebrew-signalwire/libks signalwire/homebrew-signalwire/signalwire-c


git clone https://freeswitch.org/stash/scm/fs/freeswitch.git
./bootstrap.sh

./configure --prefix=/usr/local/freeswitch
make
make install
make sounds-install
make moh-install
make cd-sounds-install 
make cd-moh-install

lsof -i:5060


启动
freeswitch

另一个窗口打开客户端

fs_cli
关闭:
Shutdown


jssip:
https://www.bootcdn.cn/jssip/


#######################

首先介绍下什么是DID? 翻译为中文为“直接向内拨号”

https://blog.csdn.net/daitu3201/article/details/80031503

sofia status profile internal
sofia status profile internal reg

jssip
https://www.jianshu.com/p/813becfc6388

sipjs:
http://sipjs.com/download/


#############################
vars.xml:
<X-PRE-PROCESS cmd="set" data="default_password=1234"/>
<!--<X-PRE-PROCESS cmd="set" data="use_profile=external"/>-->
<X-PRE-PROCESS cmd="set" data="use_profile=internal"/>



注册新用户
https://blog.csdn.net/daitu3201/article/details/80031503
http://www.bubuko.com/infodetail-1443623.html
错误 :总提示“freeswitch You must define a domain called
internal.xml中的accept-blind-reg与accept-blind-auth 均为true!这样可以做到自注册!
<domain name="all" alias="true" parse="true"/>

/usr/local/freeswitchnew/etc/freeswitch/sip_profiles/external#

gw-DID.xml
<include>
  <gateway name="gw-DID">
    <param name="realm" value="172.18.201.122"/>  // sip provider 提供的服务器IP
    <param name="username" value="88888888"/>// sip provider 提供的DID账号
    <param name="password" value="12345678"/> // sip provider 提供的DID账号密码
    <param name="proxy" value="172.18.201.122"/>  // sip provider 提供的服务器IP
    <param name="register" value="true"/>
    <param name="expire-seconds" value="600"/>
    <param name="ping" value="30"/>
    <param name="sip-trace" value="true"/>
  </gateway>
</include>


配置拨码计划


呼入
在 /usr/local/freeswitchnew/etc/freeswitch/dialplan 中修改 public.xml,
或者在public目录下加
添加如下内容:

<extension name="sipprovider">   
  <condition field="destination_number" expression="^88888888$">
    <action application="transfer" data="1008 XML default"/>
  </condition>
</extension>


呼出:
/usr/local/freeswitchnew/etc/freeswitch/dialplan/default
添加call_out.xml
<include>
    <extension name="call out">
      <condition field="destination_number" expression="^0(\d+)$">
      <action application="bridge" data="sofia/gateway/gw-DID/$1"/>
      </condition>
    </extension>
</include>



重启查看用户
sofia status profile internal reg
sofia status profile internal


originate sofia/gateway/gw-DID/88888888 &echo

originate sofia/gateway/gw-DID/88888888 &park


version

status
sofia status
sofia help
sofia status gateway gw-DID

show channes
show calls


#######
h5的客户端


<!DOCTYPE html>
<html>
<head>
    <meta charset="UTF-8">
    <title>sipjs-webphone</title>
    <script src="./js/sip-0.13.8.min.js"></script>
    <script>
        var config = {
            uri: '1000@172.18.201.122',
            displayName: 'tianyu',
            registrarServer: 'sip:172.18.201.122:5066',
            authorizationUser: '1000',
            password: '1234',
            transportOptions: {
                wsServers: ['ws://172.18.201.122:5066'],
                traceSip: true
            },
            log: {
                level: "debug"
            },
            register: true
        };
        var ua = new SIP.UA(config);
    </script>
</head>
<body>
</body>
</html>

sofia status profile internal reg
能看到的




<!DOCTYPE html>
<html>
<head>
  <title>JsSIP + WebRTC + freeSWITCH</title>
  <meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
  <meta name="Author" content="foruok" />
  <meta name="description" content="JsSIP based example web application." />
  <script src="js/jssip.min.js" type="text/javascript"></script>
  <style type="text/css">
  </style>
</head>


<body>

  <div id="login-page" style="width: 424px; height: 260px; background-color: #f2f4f4; border: 1px solid grey; padding-top: 4px">
    <table border="0" frame="void" width="418px">
      <tr>
        <td class="td_label" width="160px" align="right"><label for="sip_uri">SIP URI:</label></td>
        <td width="258px"><input value="sip:1000@haoning.com:5066" style="width:250px" id="sip_uri" type="text" placeholder="SIP URI (i.e: sip:alice@example.com)"/></td>
      </tr>
      <tr>
        <td class="td_label"  align="right"><label for="sip_password">SIP Password:</label></td>
        <td><input value="1234" style="width:250px" id="sip_password" type="password" placeholder="SIP password"/></td>
      </tr>
      <tr>
        <td class="td_label" align="right"><label for="ws_uri">WSS URI:</label></td>
        <td><input value="ws://172.18.201.122:5066" style="width:250px" id="ws_uri" class="last unset" type="text" placeholder="WSS URI (i.e: wss://example.com)"/></td>
      </tr>
      <tr>
        <td class="td_label"  align="right"><label class="input_label" for="sip_phone_number">SIP Phone Info:</label></td>
        <td><input value="sip:1002@haoning.com:5066" style="width:250px" id="sip_phone_number" type="text" placeholder="sip:3000@192.168.40.96:5060"></td>
      </tr>
      <tr>
        <td colspan="2" align="center"><button onclick="testStart()"> Initialize </button></td>
      </tr>
      <tr>
        <td colspan="2" align="center"><button onclick="testCall()"> Call </button></td>
      </tr>
      <tr>
        <td  colspan="2" align="center"><button onclick="captureLocalMedia()"> Capture Local Media</button></td>
      </tr>
    </table>
  </div>

  <div style="width: 424px; height: 324px;background-color: #333333; border: 2px solid blue; padding:0px; margin-top: 4px;">
        <video id="videoView" width="420px" height="320px" autoplay ></video>
  </div>

</body>
  <script type="text/javascript">
    var outgoingSession = null;
    var incomingSession = null;
    var currentSession = null;
    var videoView = document.getElementById('videoView');

    var constraints = {
      audio: true,
      video: true,
      mandatory: {
        maxWidth: 640,
        maxHeight: 360
      }
    };
    URL = window.URL || window.webkitURL;

    var localStream = null;
    var userAgent = null;

    function gotLocalMedia(stream) {
      console.info('Received local media stream');
      localStream = stream;
      videoView.src = URL.createObjectURL(stream);
    }

    function captureLocalMedia() {
      console.info('Requesting local video & audio');
      navigator.webkitGetUserMedia(constraints, gotLocalMedia, function(e){
        alert('getUserMedia() error: ' + e.name);
      });
    }

    function testStart(){

      var sip_uri_ = document.getElementById("sip_uri").value.toString();
      var sip_password_ = document.getElementById("sip_password").value.toString();
      var ws_uri_ = document.getElementById("ws_uri").value.toString();

      console.info("get input info: sip_uri = ", sip_uri_, " sip_password = ", sip_password_, " ws_uri = ", ws_uri_);

      var socket = new JsSIP.WebSocketInterface(ws_uri_);
      var configuration = {
        sockets: [ socket ],
        outbound_proxy_set: ws_uri_,
        uri: sip_uri_,
        password: sip_password_,
        register: true,
        session_timers: false
      };

      userAgent = new JsSIP.UA(configuration);

      userAgent.on('registered', function(data){
        console.info("registered: ", data.response.status_code, ",", data.response.reason_phrase);
      });

      userAgent.on('registrationFailed', function(data){
        console.log("registrationFailed, ", data);
        //console.warn("registrationFailed, ", data.response.status_code, ",", data.response.reason_phrase, " cause - ", data.cause);
      });

      userAgent.on('registrationExpiring', function(){
        console.warn("registrationExpiring");
      });

      userAgent.on('newRTCSession', function(data){
        console.info('onNewRTCSession: ', data);
        if(data.originator == 'remote'){ //incoming call
          console.info("incomingSession, answer the call");
          incomingSession = data.session;
          data.session.answer({'mediaConstraints' : { 'audio': true, 'video': true,       mandatory: { maxWidth: 640, maxHeight: 360 } }, 'mediaStream': localStream});
        }else{
          console.info("outgoingSession");
          outgoingSession = data.session;
          outgoingSession.on('connecting', function(data){
            console.info('onConnecting - ', data.request);
            currentSession = outgoingSession;
            outgoingSession = null;
          });
        }
          data.session.on('accepted', function(data){
            console.info('onAccepted - ', data);
            if(data.originator == 'remote' && currentSession == null){
              currentSession = incomingSession;
              incomingSession = null;
              console.info("setCurrentSession - ", currentSession);
            }
          });
          data.session.on('confirmed', function(data){
            console.info('onConfirmed - ', data);
            if(data.originator == 'remote' && currentSession == null){
              currentSession = incomingSession;
              incomingSession = null;
              console.info("setCurrentSession - ", currentSession);
            }
          });
        data.session.on('sdp', function(data){
          console.info('onSDP, type - ', data.type, ' sdp - ', data.sdp);
          //data.sdp = data.sdp.replace('UDP/TLS/RTP/SAVPF', 'RTP/SAVPF');
          //console.info('onSDP, changed sdp - ', data.sdp);
        });
        data.session.on('progress', function(data){
          console.info('onProgress - ', data.originator);
          if(data.originator == 'remote'){
            console.info('onProgress, response - ', data.response);
          }
        });
        data.session.on('peerconnection', function(data){
          console.info('onPeerconnection - ', data.peerconnection);
          data.peerconnection.onaddstream = function(ev){
              console.info('onaddstream from remote - ', ev);
              videoView.src = URL.createObjectURL(ev.stream);
          };
        });
      });

      userAgent.on('newMessage', function(data){
        if(data.originator == 'local'){
          console.info('onNewMessage , OutgoingRequest - ', data.request);
        }else{
          console.info('onNewMessage , IncomingRequest - ', data.request);
        }
      });

      console.info("call register");
      userAgent.start();
    }

    // Register callbacks to desired call events
    var eventHandlers = {
      'progress': function(e) {
          console.log('call is in progress');
        },
      'failed': function(e) {
          console.log('call failed: ', e);
      },
      'ended': function(e) {
          console.log('call ended : ', e);
      },
      'confirmed': function(e) {
        console.log('call confirmed');
      }
    };

    function testCall(){
      var sip_phone_number_ = document.getElementById("sip_phone_number").value.toString();

      var options = {
        'eventHandlers'    : eventHandlers,
        'mediaConstraints' : { 'audio': true, 'video': true ,
                               mandatory: { maxWidth: 640, maxHeight: 360 }
          },
        'mediaStream': localStream
      };

      //outgoingSession = userAgent.call('sip:3000@192.168.40.96:5060', options);
      outgoingSession = userAgent.call(sip_phone_number_, options);
    }
  </script>
</html>

































分享到:
评论

相关推荐

    FreeSWITCH 1.8.pdf

    《FreeSWITCH 1.8》这本书是关于VoIP(Voice over Internet Protocol,互联网协议语音)和WebRTC技术的权威指南,专注于使用FreeSWITCH这一开源软件交换机实现这些技术。FreeSWITCH是一个模块化通信平台,支持多种...

    Freeswitch权威指南,freeswitch权威指南 pdf,C,C++

    《FreeSWITCH权威指南》是一本深度探讨FreeSWITCH开源电话软交换平台的专著,主要面向希望深入了解和使用FreeSWITCH技术的开发者和通信行业从业者。FreeSWITCH以其强大的功能、灵活的架构以及开放源代码的优势,在...

    FreeSWITCH简要使用教程V1.1

    FreeSWITCH是一个开源的通信平台,它支持多种协议和接口,可以用于构建VoIP、视频会议、即时消息等多种通信系统。本简要使用教程V1.1是为那些想要了解和掌握FreeSWITCH操作的初学者或开发者准备的。通过这份文档,...

    Freeswitch集成科大讯飞及百度语音服务_freeswitch_

    【Freeswitch集成科大讯飞及百度语音服务】是一个关于如何在Freeswitch系统中整合科大讯飞和百度的语音服务的技术文档。Freeswitch是一个开源的通信平台,常用于建立VoIP(Voice over Internet Protocol)系统,提供...

    centos安装freeswitch过程实录

    ### CentOS安装FreeSWITCH过程实录 #### 一、安装依赖的第三方库 在开始部署FreeSWITCH之前,首先需要确保CentOS系统已安装了一系列必要的依赖库。这些库包括但不限于编译工具(如`gcc-c++`)、网络库(如`curl-...

    FreeSWITCH简要使用教程V1.1_freeswitch学习资料_freeswitch_

    **FreeSWITCH简介** FreeSWITCH是一个开源的、多平台的通信系统,它支持多种协议,包括SIP、H.323、Skype、XMPP等,旨在提供灵活的实时通信解决方案。作为一款强大的软交换平台,FreeSWITCH被广泛应用于VoIP、视频...

    freeswitch中文语音包

    Freeswitch是一个开源的通信平台,它支持实时通信如VoIP、视频通话、会议和许多其他企业级通信功能。此“freeswitch中文语音包”是专为Freeswitch设计的,目的是为了使该系统能够支持中文语言环境,提供中文语音提示...

    FreeSwitch搭建软交换中心指导

    FreeSwitch 搭建软交换中心指导 本文档旨在指导读者如何搭建 FreeSwitch 软交换中心,并了解软交换的基本特点。实验环境为 CentOS 7,FreeSwitch 1.6。 一、实验目标 通过安装 FreeSwitch,实际体验交换机在通信...

    Freeswitch权威指南,freeswitch权威指南 pdf,C,C++源码.zip

    《Freeswitch权威指南》是一本深度探讨Freeswitch开源通信平台的专业书籍,结合C和C++源码,为读者提供了全面且深入的学习资源。Freeswitch是一个强大的、开源的、多线程的VoIP(Voice over Internet Protocol)...

    freeswitch 中文语音包

    FreeSwitch 是一个开源的通信平台,它支持多种通信协议,如SIP、Skype for Business (formerly Lync)、WebRTC等,广泛应用于VoIP(Voice over IP)系统。中文语音包是为FreeSwitch设计的,目的是为了提供中文语言...

    OpenSips与freeswitch群集搭建

    OpenSips与FreeSWITCH集群搭建是一个复杂的任务,涉及到多个组件的集成和配置。OpenSips是一个开源的SIP服务器,它用作VoIP网络中的会话初始化协议(SIP)路由器,提供负载均衡、会话管理等功能。而FreeSWITCH是一个...

    freeswitch的gb28181模块

    《freeswitch的GB28181模块详解与应用》 在信息技术高速发展的今天,视频监控系统已经广泛应用于各种场所,确保公共安全和个人隐私。其中,GB28181作为中国国家标准,规范了基于IP网络的视频监控系统的互通性,而...

    freeswitch呼入呼出路由配置详解

    在本文中,我们将深入探讨Freeswitch的呼入呼出路由配置,这是一个关键的环节,对于任何使用Freeswitch作为其VoIP通信基础架构的组织来说都至关重要。Freeswitch是一个开源的通信平台,它支持多种协议,如SIP、TLS、...

    Freeswitch for windows(客户端、服务器打包)

    Freeswitch是一款强大的开源通信平台,它支持多种协议,包括SIP、TLS、WebSocket等,可用于构建VoIP、视频会议、即时消息等多种通信系统。在Windows环境下,Freeswitch提供了客户端和服务器端的打包版本,使得用户...

    freeswitch的esl控制方式demo

    **Freeswitch ESL控制方式详解** Freeswitch是一款开源、多平台的VoIP通信系统,它支持多种协议和控制方式,其中包括XML配置和Event Socket Library(ESL)API。本资源主要关注的是通过ESL进行控制的方式,这是一种...

    FreeSwitch配置和使用手册(DOC).doc

    FreeSwitch配置和使用手册 1. FreeSwitch 简介 FreeSwitch是一个强大的开源通信平台,设计用于处理各种媒体通信,包括语音、视频和文本。它不仅能够作为个人软电话客户端,还可以作为企业级PBX(Private Branch ...

    FreeSWITCH 1.8 使用手册

    FreeSWITCH 1.8 manual, a very comprehensive introduction, English text version , PDF file . 最新版 高清晰 文本电子版: FreeSWITCH-1.8使用手册, 介绍的很全面,英文版本

    freeswitch-16-cookbook.pdf_freeswitch_

    《freeswitch 1.6 Cookbook》是一本专注于FreeSWITCH 1.6版本的实践指南,旨在帮助读者深入理解和掌握这一开源通信平台的各个方面。FreeSWITCH是一个强大的、多线程、多平台的软交换系统,广泛应用于VoIP、视频会议...

Global site tag (gtag.js) - Google Analytics