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());
        }
    }
}
相关推荐
thekenofdis1 小时前
Lua脚本执行多个redis命令提示“CROSSSLOT Keys in request don‘t hash to the same slot“问题
redis·lua·哈希算法
bagadesu2 小时前
使用Docker构建Node.js应用的详细指南
java·后端
没有bug.的程序员2 小时前
Spring Cloud Gateway 性能优化与限流设计
java·spring boot·spring·nacos·性能优化·gateway·springcloud
molunnnn2 小时前
第四章 Agent的几种经典范式
开发语言·python
洛_尘3 小时前
JAVA EE初阶 2: 多线程-初阶
java·开发语言
Slow菜鸟3 小时前
Java 开发环境安装指南(五) | Git 安装
java·git
@卞4 小时前
C语言常见概念
c语言·开发语言
wjs20244 小时前
Eclipse 关闭项目详解
开发语言
沐知全栈开发4 小时前
《隐藏(Hide)》
开发语言