1):讯飞开发者账号。
2):讯飞语音合成Linux sdk,会一点C语言或者找会C的开发,目前不能超过2048超过需要增加逻辑并做容错机制。
3):Zabbix 整理告警等级,并定时将Disaster级别的告警信息输出到指定文件。
采集zabbix Disaster级别告警信息 :https://blog.csdn.net/meijinmeng/article/details/103320696
4):Jenkins整理输出信息到指定文件。
1):sdk 语音合成基础代码部分
注意:SDK中-->samples/tts_sample/tts_sample.c
samples/tts_sample/64bit_make.sh
/*
* 语音合成(Text To Speech,TTS)技术能够自动将任意文字实时转换为连续的
* 自然语音,是一种能够在任何时间、任何地点,向任何人提供语音信息服务的
* 高效便捷手段,非常符合信息时代海量数据、动态更新和个性化查询的需求。
*/
#include
#include
#include
#include
#include "qtts.h"
#include "msp_cmn.h"
#include "msp_errors.h"
/* wav音频头部格式 */
typedef struct _wave_pcm_hdr
{
char riff[4]; // = "RIFF"
int size_8; // = FileSize - 8
char wave[4]; // = "WAVE"
char fmt[4]; // = "fmt "
int fmt_size; // = 下一个结构体的大小 : 16
short int format_tag; // = PCM : 1
short int channels; // = 通道数 : 1
int samples_per_sec; // = 采样率 : 8000 | 6000 | 11025 | 16000
int avg_bytes_per_sec; // = 每秒字节数 : samples_per_sec * bits_per_sample / 8
short int block_align; // = 每采样点字节数 : wBitsPerSample / 8
short int bits_per_sample; // = 量化比特数: 8 | 16
char data[4]; // = "data";
int data_size; // = 纯数据长度 : FileSize - 44
} wave_pcm_hdr;
/* 默认wav音频头部数据 */
wave_pcm_hdr default_wav_hdr =
{
{ 'R', 'I', 'F', 'F' },
0,
{'W', 'A', 'V', 'E'},
{'f', 'm', 't', ' '},
16,
1,
1,
16000,
32000,
2,
16,
{'d', 'a', 't', 'a'},
0
};
/* 文本合成 */
int text_to_speech(const char* filename, const char* des_path, const char* params)
{
int ret = -1;
FILE* fp = NULL;
FILE* in = NULL;
const char* sessionID = NULL;
unsigned int audio_len = 0;
wave_pcm_hdr wav_hdr = default_wav_hdr;
int synth_status = MSP_TTS_FLAG_STILL_HAVE_DATA;
int file_length = 0;
char *src_text = NULL;
if (NULL == filename || NULL == des_path)
{
printf("params is error!\n");
return ret;
}
in = fopen(filename, "rb");
if(NULL == in) {
printf("open %s error.\n", filename);
return ret;
}
fp = fopen(des_path, "wb");
if (NULL == fp)
{
printf("open %s error.\n", des_path);
return ret;
}
fseek(in, 0L, SEEK_END);
file_length = ftell(in);
src_text = (char *)malloc(file_length+1);
if(NULL == src_text) {
printf("askMemFailed.\n");
fclose(in);
fclose(fp);
return ret;
}
fseek(in, 0L, SEEK_SET);
fread(src_text,file_length,1,in);
src_text[file_length] = '\0';
/* 开始合成 */
sessionID = QTTSSessionBegin(params, &ret);
if (MSP_SUCCESS != ret)
{
printf("QTTSSessionBegin failed, error code: %d.\n", ret);
fclose(fp);
fclose(in);
free(src_text);
return ret;
}
ret = QTTSTextPut(sessionID, src_text, (unsigned int)strlen(src_text), NULL);
if (MSP_SUCCESS != ret)
{
printf("QTTSTextPut failed, error code: %d.\n",ret);
QTTSSessionEnd(sessionID, "TextPutError");
fclose(fp);
fclose(in);
free(src_text);
return ret;
}
printf("正在合成 ...\n");
fwrite(&wav_hdr, sizeof(wav_hdr) ,1, fp); //添加wav音频头,使用采样率为16000
while (1)
{
/* 获取合成音频 */
const void* data = QTTSAudioGet(sessionID, &audio_len, &synth_status, &ret);
if (MSP_SUCCESS != ret)
break;
if (NULL != data)
{
fwrite(data, audio_len, 1, fp);
wav_hdr.data_size += audio_len; //计算data_size大小
}
if (MSP_TTS_FLAG_DATA_END == synth_status)
break;
printf(">");
usleep(150*1000); //防止频繁占用CPU
}
printf("\n");
if (MSP_SUCCESS != ret)
{
printf("QTTSAudioGet failed, error code: %d.\n",ret);
QTTSSessionEnd(sessionID, "AudioGetError");
fclose(fp);
fclose(in);
free(src_text);
return ret;
}
/* 修正wav文件头数据的大小 */
wav_hdr.size_8 += wav_hdr.data_size + (sizeof(wav_hdr) - 8);
/* 将修正过的数据写回文件头部,音频文件为wav格式 */
fseek(fp, 4, 0);
fwrite(&wav_hdr.size_8,sizeof(wav_hdr.size_8), 1, fp); //写入size_8的值
fseek(fp, 40, 0); //将文件指针偏移到存储data_size值的位置
fwrite(&wav_hdr.data_size,sizeof(wav_hdr.data_size), 1, fp); //写入data_size的值
fclose(fp);
fclose(in);
if(src_text)
free(src_text);
src_text = NULL;
fp = NULL;
/* 合成完毕 */
ret = QTTSSessionEnd(sessionID, "Normal");
if (MSP_SUCCESS != ret)
{
printf("QTTSSessionEnd failed, error code: %d.\n",ret);
}
return ret;
}
int main(int argc, char* argv[])
{
int ret = MSP_SUCCESS;
const char* login_params = "appid = 59a4c2a0, work_dir = .";//登录参数,appid与msc库绑定,请勿随意改动
/*
* rdn: 合成音频数字发音方式
* volume: 合成音频的音量
* pitch: 合成音频的音调
* speed: 合成音频对应的语速
* voice_name: 合成发音人
* sample_rate: 合成音频采样率
* text_encoding: 合成文本编码格式
*
*/
const char* session_begin_params = "voice_name = xiaoyan, text_encoding = utf8, sample_rate = 16000, speed = 50, volume = 50, pitch = 50, rdn = 2";
const char* filename = "tts_sample.wav"; //合成的语音文件名称
const char* text = "/tmp/error.log"; //合成文本
/* 用户登录 */
ret = MSPLogin(NULL, NULL, login_params);//第一个参数是用户名,第二个参数是密码,第三个参数是登录参数,用户名和密码可在http://www.xfyun.cn注册获取
if (MSP_SUCCESS != ret)
{
printf("MSPLogin failed, error code: %d.\n", ret);
goto exit ;//登录失败,退出登录
}
printf("\n###########################################################################\n");
printf("## 语音合成(Text To Speech,TTS)技术能够自动将任意文字实时转换为连续的 ##\n");
printf("## 自然语音,是一种能够在任何时间、任何地点,向任何人提供语音信息服务的 ##\n");
printf("## 高效便捷手段,非常符合信息时代海量数据、动态更新和个性化查询的需求。 ##\n");
printf("###########################################################################\n\n");
/* 文本合成 */
printf("开始合成 ...\n");
ret = text_to_speech(text, filename, session_begin_params);
if (MSP_SUCCESS != ret)
{
printf("text_to_speech failed, error code: %d.\n", ret);
}
printf("合成完毕\n");
exit:
/*printf("按任意键退出 ...\n");*/
/*getchar();*/
MSPLogout(); //退出登录
return 0;
}
`
2):Zabbix合成部分
```bash
#!/bin/bash
#1.清空上次记录
#>/tmp/error.log
#2.获取程序报错数量
#projects='orders platform goods webmanager distribution gateway payment account physique marketing device-distribution wechatmanager eureka ifly-skill gen2-core gen2-cmos gen1-core gen1-cmos recommend wechatseller tag'
#for i in $projects
# do
# echo "$i 的报错数量:">>/tmp/error.log
# zabbix_get -s 127.0.0.1 -p 10050 -k "error_count[$i]">>/tmp/error.log
#done
#3.获取zabbix api最新的严重告警信息
alert=""
python /srv/zabbix_py.py>/tmp/zabbix.log
alert=`cat /tmp/zabbix.log`
if [ ${#alert} -eq 0 ];then
echo "zabbix暂无严重告警,感谢收听再见">>/tmp/alert.log
#rm -f /application/demon/bin/tts_sample.wav
#jenkins 发包播报
#echo "$jenkins">>/tmp/error.log
#4.合成语音部门
#cd /application/demon/samples/tts_sample
#source 64bit_make.sh
#cd /application/demon/bin
#./tts_sample
else
echo "$alert">>/tmp/error.log
#4.合成语音部门
cd /application/demon/samples/tts_sample
source 64bit_make.sh
cd /application/demon/bin
./tts_sample
fi
```
**3):Jenkins 合成部分**
```bash
#!/bin/bash
#1.清空上次记录
#>/tmp/error.log
chmod 777 /tmp/jenkins.log
chmod 777 /tmp/error.log
chmod 777 /tmp/zabbix.log
chmod 777 /tmp/alert.log
#2.获取程序报错数量
#projects='orders platform goods webmanager distribution gateway payment account physique marketing device-distribution wechatmanager eureka ifly-skill gen2-core gen2-cmos gen1-core gen1-cmos recommend wechatseller tag'
#for i in $projects
# do
# echo "$i 的报错数量:">>/tmp/error.log
# zabbix_get -s 127.0.0.1 -p 10050 -k "error_count[$i]">>/tmp/error.log
#done
#3.获取zabbix api最新的严重告警信息
alert=""
python /srv/zabbix_py.py>/tmp/zabbix.log
if [ ! -f "/tmp/jenkins.log" ]; then
touch /tmp/jenkins.log
else
alert=`cat /tmp/zabbix.log`
jenkins=`cat /tmp/jenkins.log`
if [ ${#alert} -eq 0 ];then
echo "$(date +%F-%H:%M:%S) zabbix暂无严重告警,感谢收听再见">>/tmp/alert.log
#rm -f /application/demon/bin/tts_sample.wav
if [ ${#jenkins} -eq 0 ];then
echo "jenkins 无发包任务,感谢收听再见">>/tmp/alert.log
#rm -f /application/demon/bin/tts_sample.wav
else
#jenkins 发包播报
echo "$jenkins">/tmp/error.log
#4.合成语音部门
cd /application/demon/samples/tts_sample
source 64bit_make.sh
cd /application/demon/bin
./tts_sample
cp /application/demon/bin/tts_sample.wav /home/user && chown user.user /home/user/tts_sample.wav
rm -f /application/demon/bin/tts_sample.wav
fi
fi
fi
```
1):windows
#bat脚本
@echo off
if "%1" == "h" goto begin
mshta vbscript:createobject("wscript.shell").run("%~nx0 h",0)(window.close)&&exit
taskkill /f /t /im wmplayer.exe
del /f /s /q "C:\Download\tts_sample.wav"
"C:\Program Files\WinSCP\WinSCP" /console /command "option batch continue" "option confirm off" "open sftp://root:[email protected]:22" "option transfer binary" "get /application/demon/bin/tts_sample.wav C:\Download\" "exit" /log=C:\Download\log_file.txt
SET Source="C:\Download\tts_sample.wav"
if exist %Source% (
start "%ProgramFiles(x86)%\Windows Media Player\wmplayer.exe" "C:\Download\tts_sample.wav" -min
"D:\application\PotPlayer\PotPlayerMini64.exe" "D:\tts_sample.wav" -autoexit
"C:\Program Files\WinSCP\WinSCP.com" /command "open sftp://root:[email protected]:22 -explicit" "rm /application/demon/bin/tts_sample.wav" "exit"
"C:\Program Files\WinSCP\WinSCP.com" /command "open sftp://root:[email protected]:22 -explicit" "rm /tmp/error.log" "exit"
"C:\Program Files\WinSCP\WinSCP.com" /command "open sftp://root:[email protected]:22 -explicit" "rm /tmp/jenkins.log" "exit"
::"D:\application\PotPlayer\PotPlayerMini64.exe" "D:\tts_sample.wav" -autoexit
exit
) else (
taskkill /f /t /im wmplayer.exe
taskkill /f /t /im "PotPlayerMini64.exe"
exit
)
2):Linux(ubuntu)
```bash
#!/bin/bash
#1.删除本地播放任务和视频文件
rm -f /application/tts_sample.wav
#2.下载远程音频文件
scp -P 1622 [email protected]:/home/user/tts_sample.wav /application/tts_sample.wav
#3.后台播放音频文件
if [ ! -f "/application/tts_sample.wav" ];then
exit
else
#播放音频
cd /application
aplay tts_sample.wav &
if [ $? -eq 0 ];then
#4.播放完成后删除远程音频文件和error.log jenkins.log
ssh -p 1622 [email protected] "cd /home/user && rm -f tts_sample.wav"
ssh -p 1622 [email protected] "> /tmp/error.log && >/tmp/jenkins.log"
echo "aplay 播放成功">>/application/aplay.log
else
echo "aplay 播放失败">>/application/aplay.log
fi
fi
```
以上设置好后,使用4个月成功率高达98%以上,基本实现了播报需求。
1.核心sdk c语言脚本的合成部分。
2.zabbix 和 jenkins播报不能有冲突,需要有一个优先级。
3.语音播放后不能有重复或者漏播情况,需要播放后删除源音频文件。
4.播放语音的机器需要长期稳定,最好是Ubuntu系统。