在线语音合成 Java SDK 文档(科大讯飞)

在线语音合成 Java SDK 文档

科大讯飞官方文档地址.
官方问题解答 — java sdk常见问题分析解答

1. SDK引入

  1. 将Msc.jar包放到lib文件夹,lib文件夹放到项目根目录(目前是app工程的根目录);[^1]
  2. 还需要json-jena-1.0.jar,这个jar包由讯飞提供,但是直接增加pom中org.json的依赖也行(本工程用的org.json,没有使用讯飞的jar包);
  3. pom文件引入本地jar包 Msc.jar
    app工程的pom文件修改 Msc.jar的scope和systemPath: system ${project.basedir}/lib/Msc.jar;
  4. pom文件的plugin配置要加上 true 确保app工程打包时要将本地Mac.jar打包进去;
  5. jar包设置错误,项目无法启动

阿达

//pom.xml( vc2-app)

//pom.xml( vc2-app)
<!-- 科大讯飞  语音合成 -->
<dependency>
   <groupId>Msc</groupId>
   <artifactId>Msc</artifactId>
   <version>8.8.8.8</version>
   <scope>system</scope>
   <systemPath>${project.basedir}/lib/Msc.jar</systemPath>
</dependency>

<dependency>
   <groupId>org.json</groupId>
   <artifactId>json</artifactId>
   <version>20160810</version>
</dependency>


<build>
   <plugins>
      <plugin>
         <groupId>org.springframework.boot</groupId>
         <artifactId>spring-boot-maven-plugin</artifactId>
         <configuration>
            <mainClass>com.sinoecare.vc2.app.VillcloudAppApplication</mainClass>
            <includeSystemScope>true</includeSystemScope>
         </configuration>
      </plugin>
      <plugin>
         <groupId>com.spotify</groupId>
         <artifactId>docker-maven-plugin</artifactId>
      </plugin>
   </plugins>
</build>

2.库文件引入

  1. libmsc32.so;libmsc64.se;msc32.dll;msc64.dll 分别对应linux和window下的32位和64位系统
  2. window下,直接将四个文件放到parent工程的根目录下 如图3;
  3. linux下,将四个文件放到系统/lib文件下 如图2;
  4. 官方解释:http://bbs.xfyun.cn/forum.php?mod=viewthread&tid=9864
  5. 库文件引入不正确 sdk会报20021的错误

图2:
在这里插入图片描述

图3:
在这里插入图片描述

3.工具类MscUtil

  1. MscUtil已经封装好,使用语音合成直接调用transToSpeech方法即可;注意appId和remoteSysService需要再调用时注入,作为参数提供给该方法;
  2. appid 是sdk识别合成发起的标识;在vc2-app的bootstrap.yml配置
  3. MscTestController有调用Demo

//MscController

  1. 实现SynthesizeToUriListener ,
  2. 重写合成方法 synthesize 可以设置对应的语音类型
  3. 定义flag 初始化为 0循环判断flag的状态 , 只有当 onSynthesizeCompleted内置方法调用后 表示语音合成已经完成 否则 线程休眠一秒 直到合成完成 再进行下一步
package com.sinoecare.vc2.app.controller;

import cn.hutool.core.util.ReUtil;
import cn.hutool.core.util.StrUtil;
import com.iflytek.cloud.speech.*;
import com.sinoecare.vc2.app.remoteService.RemoteSysService;
import com.sinoecare.vc2.app.util.MscUtil;
import com.sinoecare.vc2.common.core.constant.MscConstans;
import com.sinoecare.vc2.common.core.util.R;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiImplicitParam;
import io.swagger.annotations.ApiImplicitParams;
import io.swagger.annotations.ApiOperation;
import lombok.Data;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;

import java.util.List;


/**
 * 科大讯飞sdk接口测试
 *
 * @author lanlan
 * @date 2019-09-05 11:44:45
 */
@Slf4j
@RestController
@Data
@RequestMapping("/msc")
@Api(tags = "科大讯飞sdk接口测试", protocols = "http")
public class MscController implements SynthesizeToUriListener {

	@Value("${msc.appid}")
	private String appid;

	@Autowired
	private RemoteSysService remoteSysService;

	private int flag = 0;    // 0初始化,1成功,2失败
	List<String> listR = null;

	@ApiOperation(value = "科大讯飞sdk接口测试")
	@PostMapping("/transToSpeech")
	@ApiImplicitParams({
		@ApiImplicitParam(paramType = "query", name = "words", dataType = "String", required = true, value = "要转的话"),
		@ApiImplicitParam(paramType = "query", name = "fileName", dataType = "String", required = true, value = "文件名")
	})
	public R transToSpeech(@RequestParam(name = "words", required = true) String words,
						   @RequestParam(name = "fileName", required = true) String fileName) {
		log.info("根据id查询详情,words = {}, fileName = {}", words, fileName);
		try {

			flag = 0;
			listR = null;
			//合成
			String uri = synthesize(trimeTip(words), fileName, appid, "1", this);
			// 合成完成的回调函数完成前休眠    onSynthesizeCompleted
			while (flag == 0) {
				Thread.sleep(1000);
			}
			//合成回调后flge会改为1  ,  pcm转MP3后上传ftp服务
			if (flag == 1) {
				listR = remoteSysService.uplordSpeech(uri, null).getData();
			}
//			log.info("flag = {}", flag);
//			log.info(this.listR.get(0));
			return new R<>(listR);
		} catch (Exception e) {
			log.error(e.getMessage());
			return R.error(e.getMessage());
		}
	}

	public void onBufferProgress(int progress) {
		log.info("*************合成进度*************" + progress);
	}

	public void onSynthesizeCompleted(String uri, SpeechError error) {
		if (error == null) {
			log.info("*************合成成功*************");
			log.info("合成音频生成路径:" + uri);
			try {
//				listR = remoteSysService.uplordSpeech(uri, "3333").getData();
//						log.info(listR.toString());
				flag = 1;

			} catch (Exception e) {
				log.error("合成失败", e);
				flag = 2;
			}
		} else
			flag = 2;
		log.info("*************" + error.getErrorCode()
			+ "*************");
	}
	/**
	 * 合成
	 */
	public static String synthesize(String words, String fileName, String appid, String voiceName, SynthesizeToUriListener synthesizeToUriListener) {
		SpeechUtility utility = SpeechUtility.createUtility(SpeechConstant.APPID + "=" + appid);
		SpeechSynthesizer speechSynthesizer = SpeechSynthesizer.createSynthesizer();
		String userDir = System.getProperty("user.dir");
		//      "./tts_test.pcm"
		String uri = userDir + "/" + fileName + ".pcm";
		// 设置发音人
		if (StrUtil.isBlank(voiceName) || MscConstans.VOICE_NAME_MAP.get(voiceName) == null) {
			voiceName = MscConstans.VOICE_NAME_MAP.get("1");
		} else {
			voiceName = MscConstans.VOICE_NAME_MAP.get(voiceName);
		}
		speechSynthesizer.setParameter(SpeechConstant.VOICE_NAME, voiceName);
		speechSynthesizer.setParameter(SpeechConstant.TTS_AUDIO_PATH, uri);
		//启用合成音频流事件,不需要时,不用设置此参数
		speechSynthesizer.setParameter(SpeechConstant.TTS_BUFFER_EVENT, "1");
		// 设置合成音频保存位置(可自定义保存位置),默认不保存
		speechSynthesizer.synthesizeToUri(words, uri, synthesizeToUriListener);
		log.info("------------------uri-----------------------" + uri + "-----------------" + appid);
		return uri;
	}

	@Override
	public void onEvent(int eventType, int arg1, int arg2, int arg3, Object obj1, Object obj2) {
	}


	//剔除尖括号内容
	private String trimeTip(String words) {
		if (StrUtil.isNotBlank(words)) {
			while (ReUtil.contains("<(.*?)>", words)) {
				words = ReUtil.delFirst("<(.*?)>", words);
			}
			words = words.trim();
		}
		return words;
	}

}


//合成的文件是 pcm 需要转换成mp3
ffmpeg 转换时要设置为8000 如果16000则可能语音变速


public static void pcmToMP3(String localPath, String targetFilePath) {
		log.info("执行pcm转mp3");
		String command = "ffmpeg -y -f s16be -ac 2 -ar 8000 -acodec pcm_s16le -i " + localPath + " " + targetFilePath;
		log.info("the command is : " + command);
		Runtime runtime = Runtime.getRuntime();
		try {
			Process proc = runtime.exec(command);
			InputStream stderr = proc.getErrorStream();
			InputStreamReader isr = new InputStreamReader(stderr);
			BufferedReader br = new BufferedReader(isr);
			String line = null;
			StringBuffer sb = new StringBuffer();
			while ((line = br.readLine()) != null)
				sb.append(line);
			int exitVal = proc.waitFor();
			log.info("the exitVal is : " + exitVal);
		} catch (IOException e) {
			e.printStackTrace();
		} catch (InterruptedException e) {
			log.error("ffmpeg exec cmd Exception ", e);
		}
		log.info("执行命令结束");
	}

  • 3
    点赞
  • 7
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值