freeswitch中通过嵌入式脚本监听会议事件

EventConsumer

通过freeswitch.EventConsumer("CUSTOM")来创建一个消费者,用来监听字自定义事件,当然我们也可以通过freeswitch.EventConsumer("all")来监听所有事件,但是这样会导致事件处理函数被频繁调用,所以不推荐这样做。如果我们确实需要监听多个事件,可以参考下面这种写法

lua 复制代码
local con = freeswitch.EventConsumer()
con:bind("CUSTOM")
con:bind("CHANNEL_HANGUP")

例如我们需要在会议开始、会议中有成员加入、成员退出以及会议结束时进行一些业务逻辑处理,我们可以参考一下代码来实现

lua 复制代码
-- 创建一个消费者
local con = freeswitch.EventConsumer("CUSTOM")

local function event_handle()
    local conference_name = event:getHeader("Conference-Name")
    local conference_size = event:getHeader("Conference-Size")
    local action = event:getHeader("Action")
    local caller_name = event:getHeader("Caller-Caller-ID-Name")
    
    -- 判断当前接收到的是什么事件
    if action == "conference-create" then
        freeswitch.consoleLog("INFO", "Conference started:" .. conference_name)
        --- 会议创建事件,执行对应的业务逻辑
    elseif action == "conference-destroy" then
        freeswitch.consoleLog("INFO", "Conference ended:" .. conference_name)
        --- 会议销毁事件,执行对应的业务逻辑
    elseif action == "add-member" then
        freeswitch.consoleLog("INFO", "Conference info add-member: " .. conference_name .. " callerName: " .. caller_name .. " conferenceSize: " .. conference_size)
        --- 会议中有成员加入,执行对应的业务逻辑
    elseif action == "del-member" then
        freeswitch.consoleLog("INFO", "Conference info del-member: " .. conference_name .. " callerName: " .. caller_name)
        --- 会议有成员退出,执行对应的业务逻辑     
    end
end

--- 消费事件pop中可以使用0也可以使用1,1表示阻塞,0表示不阻塞,如果使用0的话需要在监听的逻辑中加入sleep,否则会导致CPU占用过高
--- 此处可以使用pcall来捕获异常
for event in (function() return con:pop(1) end) do
    if event and run_tag == '1' then
        local ok, res = pcall(event_handle, event)
        if not ok then
            freeswitch.consoleLog("ERR", "event_handle error: " .. res)
        end
    end
end

如果我们需要在freeswitch中来执行这个脚本可以在控制台或者在fs_cli中使用lua或者luarun来执行。如果我们需要该脚本长期运行,并且跟随freeswitch一起启动,我们可以在frewswitch中作如下配置,找到freeswitch/conf/autoload_configs/lua.conf.xml文件增加如下配置

xml 复制代码
<settings name="LUA_SCRIPTS">
  <param name="startup-script" value="/usr/local/freeswitch/conf/directory/listen.lua"/>
</settings>

配置完毕重启或者执行reloadxml即可

Event socket

上面介绍的是使用嵌入式的脚本来完成会议相关事件的监听,如果是大事件更推荐使用event socket来处理,以Java语言为例,我们可以使用esl-client来完成我们的需求

java 复制代码
import ch.qos.logback.classic.Logger;

@Slf4j
@Service
public class FreeswitchClient {

    private static final String FREESAWITCH_HOST = "127.0.0.1";
    private static final Integer FREESAWITCH_PORT = 6666;
    private static final String FREESAWITCH_PASSWORD = "123456789";
    private static final Integer FREESAWITCH_CLIENT_TIMEOUT = 20;

    public static void main(String[] args) {
        try {
            // 创建esl连接
            Client client = new Client();
            client.connect(FREESAWITCH_HOST, FREESAWITCH_PORT, FREESAWITCH_PASSWORD, FREESAWITCH_CLIENT_TIMEOUT);
            client.setEventSubscriptions("plain", "all");

            // 注册监听事件
            client.addEventListener(new IEslEventListener() {
                @Override
                public void eventReceived(EslEvent eslEvent) {
                    String eventName = eslEvent.getEventName();
                    if ("CUSTOM".equals(eventName)) {
                        Map<String, String> eventHeaders = eslEvent.getEventHeaders();
                        // 当前会议名称
                        String conferenceName = eventHeaders.get("Conference-Name");
                        String jsonString = JSONObject.toJSONString(eslEvent);
                        // 当前会议人数
                        String conferenceSize = eventHeaders.get("Conference-Size");

                        log.info("conference info:{},人数:{}", conferenceName, conferenceSize);

                        String action = eventHeaders.get("Action");

                        if ("add-member".equals(action)) {
                            // todo: 执行对应的业务逻辑
                        }
                        if ("del-member".equals(action)) {
                            // todo: 执行对应的业务逻辑
                        }

                        if ("conference-destroy".equals(action)) {
                            // todo: 执行对应的业务逻辑
                        }
                    } else if ("CHANNEL_DESTROY".equals(eventName)) {
                        // todo: 执行对应的业务逻辑
                    }
                }

                @Override
                public void backgroundJobResultReceived(EslEvent eslEvent) {

                }
            });
        } catch (Exception e) {
            log.error("freeswitch client error:{}", e.getMessage());
        }
    }
}
相关推荐
香蕉可乐荷包蛋14 分钟前
Python面试问题
开发语言·python·面试
ErizJ24 分钟前
Golang|分布式索引架构
开发语言·分布式·后端·架构·golang
.生产的驴25 分钟前
SpringBoot 接口国际化i18n 多语言返回 中英文切换 全球化 语言切换
java·开发语言·spring boot·后端·前端框架
Howard_Stark29 分钟前
Spring的BeanFactory和FactoryBean的区别
java·后端·spring
饮长安千年月29 分钟前
学生管理系统审计
java·网络安全·代码审计
八股文领域大手子33 分钟前
深入浅出限流算法(三):追求极致精确的滑动日志
开发语言·数据结构·算法·leetcode·mybatis·哈希算法
-曾牛38 分钟前
Spring Boot中@RequestParam、@RequestBody、@PathVariable的区别与使用
java·spring boot·后端·intellij-idea·注解·spring boot 注解·混淆用法
新时代苦力工1 小时前
处理对象集合,输出Map<String, Map<String, List<MyObject>>>格式数据,无序组合键处理方法
java·数据结构·list
niesiyuan0001 小时前
MAC如何安装多版本jdk(以8,11,17为例)
java
几度泥的菜花1 小时前
优雅实现网页弹窗提示功能:JavaScript与CSS完美结合
开发语言·javascript·css