本来计划FreeSwitch 通过tts_commandline对接第三方语音合成,但是由于在家安装的是windows版本,系统安装后mod缺少commandline模版,所以导致无法使用该模版。系统自带的TTS引起filter效果非常差,且不支持中文语音合成,导致在测试的过程中很多工作进行不下去。
家里的电脑是windows10操作系统,安装的也是windows版本的FreeSwitch v1.11.2版本。由于测试语音播报,无法使用TTS引擎,所以自己今天徒手手撕paddlespeech TTS 与FreeSwitch集成。
整体的实现原理:
实现步骤:
第一步:安装paddlespeech 语音系统,PaddleSpeech 的window环境搭建
第二步:开启paddlespeech的流式服务,PaddleSpeech 本地部署+启用流式服务
第三步:代理模块请求语音服务器获得音频流,存储到FS指定的位置
第四步:代理模块与FS通信播放相关音频流。
具体相关代码:
监听FS发送过来的指令
/**
*
* FreeSwitch Outbound 方式服务器
*
* @author 赵海洋
* @date 2024-09-10
*/
public class SpeakAgentApp {
public static void main(String[] args) throws InterruptedException {
SocketClient outboundServer = new SocketClient(new InetSocketAddress("127.0.0.1", 18086),
new IClientHandlerFactory() {
@Override
public IClientHandler createClientHandler(){
return new TTSOutboundHandler();
}
});
outboundServer.startAsync();
}
}
/**
*
* FreeSwitch OutboundHandler 方式服务器
*
* @author 赵海洋
* @date 2024-09-10
*/
public class TTSOutboundHandler implements IClientHandler {
@Override
public void onEslEvent(Context ctx, EslEvent event) {
String eventName = event.getEventName();
String calleeNumber = event.getEventHeaders().get("Caller-Callee-ID-Number");
String callerNumber = event.getEventHeaders().get("Caller-Caller-ID-Number");
System.out.println("事件:" + eventName);
System.out.println("---------------");
System.out.println("calleeNumber:" + calleeNumber);
System.out.println("callerNumber:" + callerNumber);
System.out.println("---------------");
System.out.println("over");
System.out.println("---------------");
Map<String, String> eventHeaders = event.getEventHeaders();
System.out.println("--------eventHeaders:-------");
if(eventHeaders!=null){
eventHeaders.forEach((key,value) ->{
System.out.println(" "+eventName+" Headers "+key+":"+value);
});
}
Map<EslHeaders.Name, String> messageHeaders = event.getMessageHeaders();
System.out.println("--------messageHeaders:-------");
if(messageHeaders!=null){
messageHeaders.forEach((key,value) ->{
System.out.println(" "+eventName+" message "+key+":"+value);
});
}
}
@Override
public void onConnect(Context ctx, EslEvent event) {
String uuid = event.getEventHeaders().get("Unique-ID");
if (event.getEventName().equalsIgnoreCase("CHANNEL_DATA")) {
// this is the response to the initial connect
System.out.println("======================= incoming channel data =============================");
System.out.println("Event-Date-Local: " + event.getEventDateLocal());
System.out.println("Unique-ID: " + uuid);
System.out.println("speak context: " + event.getEventHeaders().get("variable_speak_context"));
System.out.println("Answer-State: " + event.getEventHeaders().get("Answer-State"));
System.out.println("Caller-Destination-Number: " + event.getEventHeaders().get("Caller-Destination-Number"));
System.out.println("======================= = = = = = = = = = = = =============================");
String speak_context = event.getEventHeaders().get("variable_speak_context");
//得到文字
System.out.println("speak context======: " +speak_context);
try{
String audioFile = new TTSServer("http://127.0.0.1:8092/paddlespeech/tts/streaming").text2Wav(speak_context);
System.out.println("audioFile======: " +audioFile);
if(audioFile!=null){
playSound(ctx,uuid,audioFile);
}
}catch (IOException e){
e.printStackTrace();
}
//播放语音
ctx.closeChannel();
System.out.println("命令已送达!");
} else {
throw new IllegalStateException("Unexpected event after connect: [" + event.getEventName() + ']');
}
}
}
FS通过lua脚本实现相关操作
/**
*
* FreeSwitch 测试脚本
*
* @author 赵海洋
* @date 2024-09-10
*/
function speak(context)
session:setVariable("speak_context", context)
session:execute("socket","127.0.0.1:18086 full")
end
session:answer();
while (session:ready() == true) do
-- 防止自动挂断
session:setAutoHangup(false);
speak("我是中国人何必学外文")
--休眠5秒
session:sleep(5000)
session:hangup();
end
标签:TTS,System,println,windowsJava,context,FreeSwitch,speak,event,out
From: https://blog.csdn.net/zhyooo123/article/details/142102256