freeswitch esl outbound中如何放音采集按键?
Posted yjmyzz
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了freeswitch esl outbound中如何放音采集按键?相关的知识,希望对你有一定的参考价值。
关于这个功能,esl-client 上给出的源码示例极具误导性,根本跑不起来,见: https://github.com/esl-client/esl-client/blob/master/src/test/java/OutboundTest.java
正确姿势:必须在事件订阅的回调里,才能拿到用户按键值
示例代码:
package org.freeswitch.esl.client; import org.freeswitch.esl.client.dptools.Execute; import org.freeswitch.esl.client.dptools.ExecuteException; import org.freeswitch.esl.client.internal.Context; import org.freeswitch.esl.client.outbound.IClientHandler; import org.freeswitch.esl.client.outbound.IClientHandlerFactory; import org.freeswitch.esl.client.outbound.SocketClient; import org.freeswitch.esl.client.transport.event.EslEvent; import org.freeswitch.esl.client.transport.message.EslHeaders.Name; import org.freeswitch.esl.client.transport.message.EslMessage; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import java.net.InetSocketAddress; import java.util.regex.Pattern; import static com.google.common.base.Throwables.throwIfUnchecked; public class OutboundDTMFTest { private static Logger logger = LoggerFactory.getLogger(OutboundDTMFTest.class); private static String sb = "/usr/local/freeswitch/sounds/en/us/callie/ivr/8000/"; String prompt = sb + "ivr-please_enter_extension_followed_by_pound.wav"; String failed = sb + "ivr-that_was_an_invalid_entry.wav"; public static void main(String[] args) { new OutboundDTMFTest(); } public OutboundDTMFTest() { try { //outbound test final SocketClient outboundServer = new SocketClient( new InetSocketAddress("localhost", 8086), new OutboundHandlerFactory()); outboundServer.startAsync(); } catch (Throwable t) { throwIfUnchecked(t); } } public class OutboundHandlerFactory implements IClientHandlerFactory { @Override public IClientHandler createClientHandler() { //just for sample , recommend use singleton pattern, to avoid new too many instance return new OutboundHandler(); } } public class OutboundHandler implements IClientHandler { StringBuffer buffer = new StringBuffer(10); String pattern1 = "^\d+"; String pattern2 = "^\d+#$"; @Override public void onConnect(Context context, EslEvent eslEvent) { try { Execute exe = new Execute(context, ""); //订阅DTMF事件 EslMessage eslMessage = context.sendCommand("event plain DTMF"); if (eslMessage.getHeaderValue(Name.REPLY_TEXT).startsWith("+OK")) { logger.info("subscribe event success!"); } exe.answer(); int timeOutSeconds = 30; //放音采集 exe.playAndGetDigits(1, 1, 10, timeOutSeconds * 1000, "#", prompt, failed, pattern1, timeOutSeconds * 1000); //等待用户输入按键 long start = System.currentTimeMillis(); while (true) { if (System.currentTimeMillis() - start > timeOutSeconds * 1000) { break; } if (buffer.length() > 0 && Pattern.matches(pattern2, buffer.toString())) { break; } Thread.sleep(50); } System.out.println("you pressed:" + buffer.toString()); } catch (ExecuteException | InterruptedException e) { logger.error("Could not prompt for digits", e); } finally { context.closeChannel(); } } @Override public void onEslEvent(Context ctx, EslEvent event) { // System.out.println(event.getEventName()); if (event.getEventName().equalsIgnoreCase("DTMF")) { String key = event.getEventHeaders().get("DTMF-Digit"); if ("#".equalsIgnoreCase(key)) { //检查是否输入正确(如果错误,请将之前输入的清空掉) if (!Pattern.matches(pattern1, buffer.toString())) { buffer.setLength(0); return; } } buffer.append(key); } } } }
解释一下:
1. 首先要订阅DTMF事件,只有在事件回调里,才能拿到用户键信息
2. playAndGetDigits 在outbound async full异步模式下,这个方法的返回值,其实没啥用,永远都是__unfef__,所以要在后面循环检测结果,还要考虑用户一直不按键的情况,要有超时保底
3. 事件回调中,要考虑用户按错键的情况,比如提示用户按数字键,然后用户输入了字母或星号之类的,遇到这种,要把之前的输入结果清掉。
以上是关于freeswitch esl outbound中如何放音采集按键?的主要内容,如果未能解决你的问题,请参考以下文章
如何在FreeSWITCH外联模式下使用esl接口时,设置无应答超时时间