(1)搜索腾讯云官网
(2)打开语音识别
腾讯云语音识别(Automatic Speech Recognition,ASR)为开发者提供语音转文字服务的最佳体验。经公司内部微信、QQ 、腾讯视频、王者荣耀等大体量业务落地验证,日服务亿级用户,性能稳定。腾讯语音识别技术开放实时语音识别、一句话识别和录音文件识别服务,满足不同类型开发者需求。除公有云接入外,腾讯语音识别技术也支持私有化部署。
小编:微信和王者荣耀的语音识别还是很强大的,其它的虽然并不清楚
(3)先来看下语音识别的接口文档
![1552371855329](C:\Users\lichuanran\AppData\Roaming\Typora\typora-user-images\15523718
1>通过post请求来发送语音数据,从而得到结果
2>请求大小不能超过600k
超过600k不会报错,但是识别时长会有点长
3>音频时长不可超过60s
4>支持音频格式 wav 、mp3
5>比特率128k或者256k
256k比128k保存的数据更具体,对应的文件大小也更大
6>音频流的采样率8000或者16000 (单位时间内有多少数据来描述采样点)
分别对应接口文档的EngSerViceType(引擎类型)的8K或者16k
16000的采样率识别准确率比8000采样率更高
7>请求频率25次/s
使用多线程进行死循环发现,达到25次/s会把请求延迟一点,并不会报错
8>单声道
注:下文小编会介绍怎么把 任意一个音频文件 转换为一个 符合腾讯云识别标准 的音频文件
(1)下载SDK
https://cloud.tencent.com/document/product/441/19814
1>打开SDK会发现有两个类 SASRsdk 和 SASRtest 一个wav格式的语音文件
import javax.crypto.Mac; import javax.crypto.spec.SecretKeySpec; import java.io.File; import java.io.FileInputStream; import java.io.UnsupportedEncodingException; import java.util.Base64; import java.util.Map; import java.util.Random; import java.util.TreeMap; import java.net.URLEncoder; import java.io.OutputStream; import java.io.InputStream; import java.io.BufferedReader; import java.net.URL; import java.net.HttpURLConnection; import java.io.InputStreamReader; public class SASRsdk { private static String SecretId, SecretKey, EngSerViceType, SourceType, VoiceFormat, fileURI;
public static String formSignstr(String serverUrl, Map<String, String> mapReq) { StringBuilder strBuilder = new StringBuilder(serverUrl); // to make that all the parameters are sorted by ASC order TreeMap<String, String> sortedMap = new TreeMap(mapReq); for (Map.Entry<String, String> entry : sortedMap.entrySet()) { strBuilder.append(entry.getKey()); strBuilder.append('='); strBuilder.append(entry.getValue()); strBuilder.append('&'); } if (mapReq.size() > 0) { strBuilder.setLength(strBuilder.length() - 1); } //System.out.println("sign str: " + strBuilder); return strBuilder.toString(); } public static String formPostbody(Map<String, String> mapReq) { StringBuilder stringBuilder = new StringBuilder(); // to make that all the parameters are sorted by ASC order TreeMap<String, String> sortedMap = new TreeMap(mapReq); for (Map.Entry<String, String> entry : sortedMap.entrySet()) { try { stringBuilder.append(URLEncoder.encode(entry.getKey(), "UTF-8")); stringBuilder.append('='); stringBuilder.append(URLEncoder.encode(entry.getValue(), "UTF-8")); stringBuilder.append('&'); } catch (UnsupportedEncodingException e) { e.printStackTrace(); } } return stringBuilder.toString(); } public static String base64_hmac_sha1(String value, String keyStr) { String encoded = ""; String type = "HmacSHA1"; try { byte[] key = (keyStr).getBytes("UTF-8"); byte[] Sequence = (value).getBytes("UTF-8"); Mac HMAC = Mac.getInstance(type); SecretKeySpec secretKey = new SecretKeySpec(key, type); HMAC.init(secretKey); byte[] Hash = HMAC.doFinal(Sequence); encoded = Base64.getEncoder().encodeToString(Hash); } catch (Exception e) { e.printStackTrace(); } return encoded; } /* - 获得unix时间戳 */ public static String toUNIXEpoch() { long unixTime = System.currentTimeMillis() / 1000L; return unixTime + ""; } /* - 生成随机nonce */ public static String toUNIXNonce() { long unixTime = System.currentTimeMillis() / 1000L; String str = unixTime + ""; String nonce = str.substring(0, 4); return nonce; } public static String createSign(String signStr, String secretKey) { return base64_hmac_sha1(signStr, secretKey); } private static String getRandomString(int length) { //定义一个字符串(A-Z,a-z,0-9)即62位; String str = "zxcvbnmlkjhgfdsaqwertyuiopQWERTYUIOPASDFGHJKLZXCVBNM1234567890"; //由Random生成随机数 Random random = new Random(); StringBuffer sb = new StringBuffer(); //长度为几就循环几次 for (int i = 0; i < length; ++i) { //产生0-61的数字 int number = random.nextInt(62); //将产生的数字通过length次承载到sb中 sb.append(str.charAt(number)); } //将承载的字符转换成字符串 return sb.toString(); } public static int setConfig( String SecretId, String SecretKey, String EngSerViceType, String SourceType, String VoiceFormat, String fileURI ) { if (SecretId.length() <= 0) { System.out.println("SecretId can not be empty!"); return -1; } if (SecretKey.length() <= 0) { System.out.println("SecretKey can not be empty!"); return -1; } if (EngSerViceType.length() <= 0 || (EngSerViceType.compareTo("8k") != 0 && EngSerViceType.compareTo("16k") != 0)) { System.out.println("EngSerViceTyp is not valied !"); return -1; } if (SourceType.length() <= 0 || (SourceType.compareTo("0") != 0 && SourceType.compareTo("1") != 0)) { System.out.println("SourceType is not valied !"); return -1; } if (VoiceFormat.length() <= 0 || (VoiceFormat.compareTo("mp3") != 0 && VoiceFormat.compareTo("wav") != 0)) { System.out.println("VoiceFormat is not valied !"); return -1; } if (fileURI.length() <= 0) { System.out.println("fileURI can not be empty!"); return -1; } SASRsdk.SecretId = SecretId; SASRsdk.SecretKey = SecretKey; SASRsdk.EngSerViceType = EngSerViceType; SASRsdk.SourceType = SourceType; SASRsdk.VoiceFormat = VoiceFormat; SASRsdk.fileURI = fileURI; return 0; } public static int sendVoice() { Map<String, String> reqMap = new TreeMap(); reqMap.put("Action", "SentenceRecognition"); reqMap.put("SecretId", SecretId); reqMap.put("Timestamp", toUNIXEpoch()); reqMap.put("Nonce", toUNIXNonce()); reqMap.put("Version", "2018-05-22"); reqMap.put("ProjectId", "0"); reqMap.put("SubServiceType", "2"); reqMap.put("EngSerViceType", EngSerViceType); reqMap.put("SourceType", SourceType); if (SourceType.compareTo("0") == 0) { try { String Url = URLEncoder.encode(fileURI, "UTF-8"); reqMap.put("Url", Url); } catch (UnsupportedEncodingException e) { e.printStackTrace(); } } else if (SourceType.compareTo("1") == 0) { FileInputStream fileInputStream = null; try { fileInputStream = new FileInputStream(new File(fileURI)); int datalen = fileInputStream.available(); byte[] dataPacket = new byte[datalen]; int n = fileInputStream.read(dataPacket); //System.out.println("n :"+n); String Data = Base64.getEncoder().encodeToString(dataPacket); String DataLen = datalen + ""; // System.out.println("data len: "+DataLen); reqMap.put("Data", Data); reqMap.put("DataLen", DataLen);
} catch (Exception e) { e.printStackTrace(); } } else { return -3; } reqMap.put("VoiceFormat", VoiceFormat); String UsrAudioKey = getRandomString(16); reqMap.put("UsrAudioKey", UsrAudioKey); String _url = "POSTaai.tencentcloudapi.com/?"; String signstr = formSignstr(_url, reqMap); // System.out.println("signstr: " + signstr); String signing = createSign(signstr, SecretKey); // System.out.println("签名: " + signing); String tmppostdata = formPostbody(reqMap); String sign = ""; try { sign = URLEncoder.encode(signing, "UTF-8"); } catch (UnsupportedEncodingException e) { e.printStackTrace(); } StringBuilder postdata = new StringBuilder(tmppostdata); postdata.append("Signature="); postdata.append(sign); String post = postdata.toString(); //System.out.println("post : "+post); String serverUrl = "https://aai.tencentcloudapi.com"; HttpURLConnection con = null; StringBuilder sbResult = new StringBuilder(); try { URL url = new URL(serverUrl); con = (HttpURLConnection) url.openConnection(); con.setRequestMethod("POST"); con.setDoOutput(true); con.setDoInput(true); con.setUseCaches(false); con.setRequestProperty("Host", "aai.tencentcloudapi.com"); con.setRequestProperty("Content-Type", "application/x-www-form-urlencoded"); con.setRequestProperty("Charset", "utf-8"); // 往服务器写入数据 OutputStream out = con.getOutputStream(); out.write(post.getBytes()); out.flush(); // 接收服务器返回的数据 InputStream in = con.getInputStream(); BufferedReader br = new BufferedReader(new InputStreamReader(in)); String line;// 每一行的数据 while ((line = br.readLine()) != null) { sbResult.append(line); } System.out.println(sbResult.toString()); } catch (Exception e) { throw new RuntimeException(e); } finally { if (con != null) { con.disconnect(); con = null; } } return 0; } }
(2)进行初步测试 --wav 采样率16000 比特率256kbps 远程文件
public static void main(String[] args) { //用户需修改为自己的SecretId,SecretKey String SecretId = "AKID31NbfXbpBLJ4kGJrytc9UfgVAlGltJJ8"; String SecretKey = "kKm26uXCgLtGRWVJvKtGU0LYdWCgOvGP"; // 识别引擎 8k or 16k String EngSerViceType = "16k"; // 语音数据来源 0:语音url or 1:语音数据bodydata(data数据大小要小于800k) String SourceType = "0"; //音频格式 wav,mp3 String VoiceFormat = "wav"; // 语音数据地址 String fileURI="http://liqiansunvoice-1255628450.cosgz.myqcloud.com/30s.wav"; //调用setConfig函数设置相关参数 int res = SASRsdk.setConfig(SecretId, SecretKey, EngSerViceType, SourceType, VoiceFormat, fileURI); if (res < 0) { return; } //调用sendVoice函数获得音频识别结果 SASRsdk.sendVoice(); }
1>测试结果
{"Response":{"Result":"雨是最寻常的一下就是三两天。可别恼看像牛毛像花针像细丝密密地斜织着。人家屋顶上全笼着一层烟雾树叶却绿的发亮,小草也青得逼你的眼,傍晚的时候上灯了。一点点黄晕的光。烘托出一片安静而和平的夜在乡下在小路上石桥边默默撑着伞的人。","RequestId":"b08e7b64-3b0b-4658-a478-a4650f2a7c48"}}
2>根据语音数据地址,下载文件
文件的比特率为256kbps 因此 识别引擎(EngSerViceType)16k 、语音数据来源 (SourceType)0
3>SecretId和SecretKey 通过腾讯云可以新建
![1552377914206](C:\Users\li
(3)继续测试 --wav 采样率8000 比特率128kbps 本地文件
public static void main(String[] args) { //用户需修改为自己的SecretId,SecretKey String SecretId = "AKID31NbfXbpBLJ4kGJrytc9UfgVAlGltJJ8"; String SecretKey = "kKm26uXCgLtGRWVJvKtGU0LYdWCgOvGP"; // 识别引擎 8k or 16k String EngSerViceType = "8k"; // 语音数据来源 0:语音url or 1:语音数据bodydata(data数据大小要小于800k) String SourceType = "1"; //音频格式 wav,mp3 String VoiceFormat = "wav"; // 语音数据地址 String fileURI = "D:\\test.wav"; //调用setConfig函数设置相关参数 int res = SASRsdk.setConfig(SecretId, SecretKey, EngSerViceType, SourceType, VoiceFormat, fileURI); if (res < 0) { return; } //调用sendVoice函数获得音频识别结果 SASRsdk.sendVoice(); }
1>测试结果
{"Response":{"Result":"张先生,您好。那个为了规范保险从业人员的销售行为。也为了更好的保护您的合法权益。根据保监会规定我们将。哎。您能不能说话客气点。你会不会好好说话,会不会会不会会不会好像说。","RequestId":"2b93994a-7c01-4237-9c3a-07dfa14eb34d"}}
2>使用的语音文件为SDK自带
文件比特率为128kbps、采样率为8000 即 识别引擎(EngSerViceType)8k 、本地文件 SourceType=1
3>如果不按上面所示进行测试,得到的结果会识别不准确哦
(4)使用自己的文件进行测试(MP3)
1>使用16k识别引擎
{"Response":{"Result":"�","RequestId":"6c18c00a-1a6e-4da4-b3a7-701088c864c8"}}
2>使用8k识别引擎
{"Response":{"Result":"嗯。嗯嗯。呃,嗯。呃。嗯嗯。嗯嗯,呃。呃。嗯。嗯嗯。嗯嗯,呃。呃。嗯。嗯。嗯。嗯。嗯。","RequestId":"7d03d1fc-a586-470a-bdfb-81b4ccbf8fc5"}}
3>我们发现,识别结果有严重的误差
原因:语音文件为320kbps,采样率远远大于41000。导致识别失败,或者结果全是语气词
4>将自己的语音文件转换成 比特率为128kbps,采样率为16000,单声道 (下面会介绍用java怎么转换)
使用16k识别引擎测试—>识别成功
5>将自己的语音文件转换成 比特率为128kbps,采样率为8000 ,单声道
使用8k识别引擎测试—>识别成功
缺点:较16k识别引擎。准确率更低,文件的大小却无差别
(1)、把 任意格式的语音文件 转换为 符合腾讯接口的格式文件
1>导入jar包
<!-- https://mvnrepository.com/artifact/com.github.dadiyang/jave --> <dependency> <groupId>com.github.dadiyang</groupId> <artifactId>jave</artifactId> <version>1.0.2</version> </dependency>
2> JAVE 简介 和 作用
J 即java ,A 即 audio , V 即 voice ,E 即 encoding。它一个工具,一个用纯java语言写的跨平台的,一通用的Ascii码图形化的文本编辑器。其功能和微软的记事本有些类似,主要是一个字处理工具,但提供图形化输入;操作像是微软的画图软件,因为该软件主要是通过鼠标进行文本的编辑。进一步看了一下该软件的功能,操作和功能并不复杂。该软件主要的卖点是授权开发源代码方式,其用百分之百java语言开发的跨平台特点。
可以用来给音频,视频 重新编码 , 视频剪辑 , 视频格式的转换等一系列强大的功能。
3>
try { //File source = new File("file path source"); //File target = new File("file path target"); // Audio Attributes/音频编码属性 AudioAttributes audio = new AudioAttributes(); /* * 它设置将用于音频流转码的编解码器的名称。您必须从当前Encoder实例的getAudioEncoders()方法返回的列表中选择一个值。否则, * 您可以传递AudioAttributes.DIRECT_STREAM_COPY特殊值,该值需要源文件中原始音频流的副本。 */ audio.setCodec("libmp3lame"); /* * 它设置新重新编码的音频流的比特率值。如果未设置比特率值,编码器将选择默认值。该值应以每秒位数表示。例如,如果你想要128 kb / * s比特率,你应该调用setBitRate(new Integer(128000))。 */ audio.setBitRate(128000); /* 它设置将在重新编码的音频流中使用的音频通道的数量(1 =单声道,2 =立体声)。如果未设置通道值,编码器将选择默认值。 */ audio.setChannels(1); /* * 它设置新重新编码的音频流的采样率。如果未设置采样率值,编码器将选择默认值。该值应以赫兹表示。例如,如果您想要类似CD的44100 * Hz采样率,则应调用setSamplingRate(new Integer(44100))。 */ //audio.setSamplingRate(44100); audio.setSamplingRate(16000); /* 可以调用此方法来改变音频流的音量。值256表示没有音量变化。因此,小于256的值是音量减小,而大于256的值将增加音频流的音量。 */ audio.setVolume(new Integer(256)); // Encoding attributes/编码属性 EncodingAttributes attrs = new EncodingAttributes(); /* * 它设置将用于新编码文件的流容器的格式。给定参数表示格式名称。 * 编码格式名称有效且仅在它出现在正在使用的Encoder实例的getSupportedEncodingFormats()方法返回的列表中时才受支持。 */ attrs.setFormat("mp3"); /* 它设置音频编码属性。如果从未调用过新的EncodingAttributes实例,或者给定参数为null,则编码文件中不会包含任何音频流 */ attrs.setAudioAttributes(audio); /* * 它为转码操作设置偏移量。源文件将从其开始的偏移秒开始重新编码。例如,如果您想剪切源文件的前五秒, * 则应在传递给编码器的EncodingAttributes对象上调用setOffset(5)。 */ // attrs.setOffset(5F); /* * 它设置转码操作的持续时间。只有源的持续时间秒才会在目标文件中重新编码。例如,如果您想从源中提取和转码30秒的一部分, * 则应在传递给编码器的EncodingAttributes对象上调用setDuration(30) */ // attrs.setDuration(30F); // Encode/编码 Encoder encoder = new Encoder(); encoder.encode(source, target, attrs); } catch (Exception ex) { ex.printStackTrace(); }
(1)、搜索 百度AI开放平台
(2)、创建应用
(3)、查看技术文档
(4)、选择java SDK
(5)、SDK下载 选择java SDK进行下载
(1)、创建maven工程
(2)、加入依赖
<dependency> <groupId>com.baidu.aip</groupId> <artifactId>java-sdk</artifactId> <version>4.1.1</version> </dependency>
(3)、创建wav语音格式的音频
目前格式仅仅支持pcm,wav或amr,填写mp3即会有此错误(mp3转pcm会出现音频质量过差的错误)
如何获取以上某种格式的音频,用来测试呢
手机下载录音专家,录音后会有形成wav格式的音频,在 手机文件存储 (一般是过1分钟左右,会出现在音频文件中) 中找到生成的wav格式文件,发送到电脑上
音频文件不能过大,小于4M,音频长度要小于60s
(4)、
**
public class Sample { //设置APPID/AK/SK public static final String APP_ID = "15598353"; public static final String API_KEY = **"IwqPzfgVlGLKMbUIw3TVlF77"; public static final String SECRET_KEY = "xxxxxxxxxxxxxxx"; public static void main(String[] args) { // 初始化一个AipSpeech AipSpeech client = new AipSpeech(APP_ID, API_KEY, SECRET_KEY); // 可选:设置网络连接参数 client.setConnectionTimeoutInMillis(2000); client.setSocketTimeoutInMillis(60000); // 可选:设置代理服务器地址, http和socket二选一,或者均不设置 //client.setHttpProxy("proxy_host", proxy_port); // 设置http代理 //client.setSocketProxy("proxy_host", proxy_port); // 设置socket代理 // 可选:设置log4j日志输出格式,若不设置,则使用默认配置 //也可以直接通过jvm启动参数设置此环境变量 System.setProperty("aip.log4j.conf", "log4j.properties"); new Sample().asr(client); // 调用接口 //JSONObject res = client.asr("test.pcm", "pcm", 16000, null); //System.out.println(res.toString(2)); } public void asr(AipSpeech client){ // 对本地语音文件进行识别 String path = "D:\\测试文件\\970f1c080e0c78476d337a80ba5114f9.wav"; JSONObject asrRes = client.asr(path, **"wav"**, 16000, **null**); System.out.println(asrRes); // 对语音二进制数据进行识别 byte[] data = new byte[0]; //readFileByBytes仅为获取二进制数据示例 try { data = Util.readFileByBytes(path); } catch (IOException e) { e.printStackTrace(); } JSONObject asrRes2 = client.asr(data, "wav", 16000, null); System.out.println(asrRes.getInt("err_no")==0); System.out.println(asrRes2.get("result")); } }
注:APP_ID API_KEY SECRET_KEY 在百度AI开放平台 注册服务后,会有这3个的值
(5)、测试结果:
(1)、
1>我们可以看到有语音听写、语音转写
语音听写:一分钟以内 人机对话、输入法、语音搜索
语音转写:五小时以内 日常对话、演讲
2>支持格式
语音听写:采样率为8kHz或16kHz,位长16bit,单声道的wav、pcm
语音转写:单声道、多声道的wav、flac、opus、m4a、mp3
3>语音听写创建
1、
2、
3、
4、
5、
4>语音转写创建
1、
2、
3、语音转写可以选择java哦,我这个是webapi的
本文介绍了腾讯、百度、讯飞的语音识别。百度和讯飞使用简单,腾讯相对使用就比较复杂点了。
腾讯一句话识别是最突出的功能,支持识别mp3格式的语音文件。腾讯的语音识别在王者荣耀、微信
都有大量的使用,并发还是可以的,虽然给客户1s 25次的请求比较少,但是出问题的可能性比较小。
并且腾讯语音识别时间是非常短的,本地测试2s多一点,真正使用也就是1s左右。讯飞的语音转写时
间就比较长了,在8s左右一个请求。讯飞的语音听写时间在3s左右,百度的语音听写类似。