经历三天时间各种遇到困难 之后终于实现了这个功能,参照网上了许多文章 才找到一个能正常实现的方法,网上能找到的例子都不起作用,相信很多人困惑在这,为了避免别人出现这种情况,我分享我的代码,绝对可用,包括 uniapp前端使用了recorderManager和java端调用百度语音转文字,我相信很多人都很需要我写的东西,我只试验了安卓手机,html5 + 里面
plus.speech这个方式就不要用了,不好用,调用百度的语音识别时在百度的管理控制台会看到dev_id这个参数没传的错误也没找到添加这个参数的地方,所以在hbuildx里面当前项目的app模块配置这个地方不需要选
1.非常重要的一个步骤 manifest.json里面添加android.permission.RECORD_AUDIO这个权限,无论是想真机调试,由其是使用了自定义基座一定要在线打个包,让基座包含这个权限然后在手机系统 里面应用管理当前这个app的权限管理里面必须要看到有录音权限这一项
2.为了能够在使用recorderManager在进入要使用录音功能的页面会询问是否允许录音这样的权限,必须要使用recorderManager之前要调用一次硬件权限申请。这个在插件市场里面有一个https://ext.dcloud.net.cn/plugin?id=594 这个地址 App权限判断和提示这样的js,用于判断或申请某个硬件权限使用的是native.js的功能。这个插件引入项目之后会在当前项目目录的js_sdk这样一个文件夹。在里面会出现wa-permission文件 夹下面会有一个permission.js,
3.相关代码
uniapp端代码
<view class=\"popup-content\" > <view>{{msg}}</view> <view>你在说{{voicetext}}</view> <button class=\"uni-btn\" type=\"warn\" @touchstart=\"startvoice\" @touchend=\"endvoice\">按说语话松开停止</button> <button class=\"uni-btn\" type=\"warn\" @tap=\"playvoice\" >播放录音</button> </view> <script> import permision from \"@/js_sdk/wa-permission/permission.js\" const recorderManager = uni.getRecorderManager(); const innerAudioContext = uni.createInnerAudioContext(); export default { data() { return { voicetext:\"\", msg:\"\", voicepath:\"\" } }, onLoad() { this.initaudio() }, methods: { async initaudio(){ //注意此处必须为 await 因为会触发异步事件,手机上会弹出权限申请对话框处理完才能走下一步录音 let recordauth = await permision.requestAndroidPermission(\"android.permission.RECORD_AUDIO\") console.log(\"判断有没有录音权限>>>>>>\"+recordauth) if(recordauth==1){ recorderManager.onStart((res)=>{ console.log(\"开始 录音>>>>>>>>>...\") }); recorderManager.onStop((res)=>{ console.log(\"recorderstop....res.tempFilePath>>>\"+res.tempFilePath) this.voicepath = res.tempFilePath this.uploadvoicefile() // 使用uni.uploadFile上传到服务器上,此时是mp3格式 }); recorderManager.onError( (res)=> { console.log(\'onError\'+JSON.stringify(res)); }); } }, //initaudio 方法结束 startvoice(){ console.log(\"开始录音\") recorderManager.start({ format:\"mp3\", sampleRate: 16000 // 必须设置是后台设置的参数,不然百度语音识别不了 }); }, endvoice(){ console.log(\"结束录音\") //注意为了避免说话时间太短导致这个api出现bug要加一些延时 setTimeout(()=>{ recorderManager.stop() },1000) }, playvoice(){ console.log(\"点击playvoice\") if (this.voicepath) { console.log(\"播放声音\") innerAudioContext.src = this.voicepath; innerAudioContext.play(); } }, uploadvoicefile(){ // this.msg = \"调用java端服务文件路径\"+this.voicepath uni.uploadFile({ url: \'http://ip:端口/uploadFile(java端接收文件接口名)\', filePath: this.voicepath,//录音结束后返回的临时路径, name: \'file\', formData: { dev_id:1537 //中文带标点 }, success: (uploadFileRes) => { let word = uploadFileRes.data console.log(\"上传音频成功\"+word); }, fail: (res) => { console.log(\"上传音频失败\"+JSON.stringify(res)); } }); } } } </script> ``` //注意uploadFile 的url属性 这个地方ip不能是localhost或127,如果自已电脑启动java服务必须 是本机的真实ip如192.xxx这种,或者域名什么的,并且java端接口一定要支持跨域,很多人卡到这个ip上,我也是网上很难找到解决问题的贴子 注意filePath这个路径就是recorderManager的onStop事件就得到的_doc这种开头的路径,不需要加什么file:不是像网上某些人说的加这种东西
Java端
pom里面需要引用两个包
<dependency> <groupId>com.baidu.aip</groupId> <artifactId>java-sdk</artifactId> <version>4.16.3</version> </dependency> <dependency> <groupId>com.googlecode.soundlibs</groupId> <artifactId>mp3spi</artifactId> <version>1.9.5.4</version> </dependency> ``` import com.baidu.aip.speech.AipSpeech; import javazoom.spi.mpeg.sampled.file.MpegAudioFileReader; import org.apache.commons.io.IOUtils; import org.json.JSONArray; import org.json.JSONObject; import org.springframework.web.bind.annotation.*; import org.springframework.web.multipart.MultipartFile; import javax.sound.sampled.AudioFormat; import javax.sound.sampled.AudioInputStream; import javax.sound.sampled.AudioSystem; import java.io.IOException; import java.io.InputStream; import java.util.HashMap; @RestController @CrossOrigin(origins = \"*\") public class BaiduSpeech { //设置APPID/AK/SK public static final String APP_ID = \"\"; //去百度语音服务申请 public static final String API_KEY = \"\";//去百度语音服务申请 public static final String SECRET_KEY = \"\";//去百度语音服务申请 @RequestMapping(value = \"/uploadFile\") public String uploadFile( @RequestParam(\"dev_id\") int dev_id, @RequestParam(\"file\") MultipartFile file) throws Exception { byte[] pcmbytedata = mp3Convert2pcm(file.getInputStream()); HashMap<String,Object> options = new HashMap<String,Object>(); options.put(\"dev_pid\",dev_id);// JSONObject jsonfrombaidu = basicBydata(pcmbytedata,\"pcm\",options); JSONArray jsonArray = jsonfrombaidu.getJSONArray(\"result\"); String result = jsonArray.getString(0); System.out.println(result); //解析完的结果 return result; } // 获取AipSpeech对象,建议单例使用 public static AipSpeech getClient() { AipSpeech client = new AipSpeech(APP_ID, API_KEY, SECRET_KEY); // 可选:设置网络连接参数 client.setConnectionTimeoutInMillis(2000); client.setSocketTimeoutInMillis(60000); return client; } // 语音识别(来自文件) public static JSONObject basicBydata(byte[] voicedata, String fileType,HashMap<String,Object> options) { AipSpeech client = getClient(); return client.asr(voicedata, fileType, 16000, options); } /** * MP3转换PCM * @param inputStream MP3输入流 * @throws Exception */ public static byte[] mp3Convert2pcm(InputStream inputStream) throws Exception { //转换PCM audioInputStream 数据 AudioInputStream audioInputStream = getPcmAudioInputStream(inputStream); byte[] pcmBytes = IOUtils.toByteArray(audioInputStream); return pcmBytes; } /** * 获取PCM AudioInputStream 数据 * @param inputStream MP3输入流 * @return AudioInputStream PCM输入流 */ private static AudioInputStream getPcmAudioInputStream(InputStream inputStream) { AudioInputStream audioInputStream = null; AudioFormat targetFormat = null; try { AudioInputStream in = null; MpegAudioFileReader mp = new MpegAudioFileReader(); in = mp.getAudioInputStream(inputStream); AudioFormat baseFormat = in.getFormat(); targetFormat = new AudioFormat(AudioFormat.Encoding.PCM_SIGNED, baseFormat.getSampleRate(), 16, baseFormat.getChannels(), baseFormat.getChannels() * 2, baseFormat.getSampleRate(), false); audioInputStream = AudioSystem.getAudioInputStream(targetFormat, in); } catch (Exception e) { e.printStackTrace(); } return audioInputStream; } } ```
暂无评论内容