手机录入语音翻译为文字

2024-07-15  本文已影响0人  呼噜噜睡

也许偶尔就会有这样的需求,我是说如果,就是需要在手机端录入语音,然后发往后端,转为文字,再做对应的逻辑处理。是不是一听就很想有copy的想法呢,是的,就是有可以copy的东西。

首先整体思路是用最小的代价,实现我们的功能。那么手机端的语音录入,我们可以借助于微信小程序去实现,小程序内部有api可以调用语音输入。然后将得到的语音发往后端,后端呢,去调用百度的语音接口,就完成了语音翻译。

好了,接下来开启我们的代码之旅吧。

首先需要明确一个概念,在微信的体系内,如何去标识一个用户呢,那就是openId,单个用户的openId在某个微信小程序下是唯一的,我们就用它去标识。那些微信小程序的注册和申请、域名配置啥、小程序开发工具下载啥的咱们就跳过吧。还有一个,如果我们没有https的备案域名,开发的时候也不要紧,只要我们在开发者工具里面将域名校验给关闭掉就可以。

第一步,获取openId,这个任务自然是交给后端去做了。首先在微信小程序端,会获得一个code,这个code只有5分钟的有效期,可以根据code去兑换openId,小程序端的逻辑如下:

App({
  onLaunch() {
    // 登录
    wxUtil.login(code => {//code自动获取
      console.log(code)
      let paramJson = {code: code};
      wxUtil是一个工具类,包装了微信的http请求,不用关注
      wxUtil.post('wx/appletcode2openid', paramJson, wxUtil.audio, { isShowLoading: true }, (result) =>{
        console.log(result);
        wxUtil.setOpenIdByStorage(result.data.openID);
      });
     });
  },
  globalData: {
    userInfo: null
  }
})

对应的后端获取openId的逻辑:

/**
     * 微信小程序根据code获取openId等信息
     *
     * @return
     * @throws
     * @throws IOException
     */
public static WxAppletAuthResultVO getOpenIdByAuthCodeOnApplet(String appId, String appSecret, String code) {
    if(appId==null||appId.trim().isEmpty()){
        throw new RuntimeException("appId为空");
    }
    if(appSecret==null||appSecret.trim().isEmpty()){
        throw new RuntimeException("appSecret为空");
    }
    if(code==null||code.trim().isEmpty()){
        throw new RuntimeException("code为空");
    }
    try {
        String url = "https://api.weixin.qq.com/sns/jscode2session?appid=APPID&secret=SECRET&js_code=JSCODE&grant_type=authorization_code".replace("APPID", appId).replace("SECRET",appSecret).replace("JSCODE", code);
        String result = HttpUtil.doPost(url, null);
        if(result==null||result.isEmpty()){
            throw new RuntimeException("微信小程序根据code获取openId等信息返回为空");
        }
        
        return JSON.parseObject(result, WxAppletAuthResultVO.class);
    } catch (Exception e) {
        e.printStackTrace();
        throw e;
    }
    return null;
}

有了openId,下面我们就可以获取录入的语音了,然后将语音和openId一起发往后端。微信小程序端的js代码:

const wxUtil = require('../../utils/wxutil.js');
const recorderManager = wx.getRecorderManager();
const innerAudioContext = wx.createInnerAudioContext({"useWebAudioImplement": true});

recorderManager.onStop((res) => {//注意  给recorderManager注册了事件  后面会触发
  var tempFilePath = res.tempFilePath;//音频文件地址
  const fs = wx.getFileSystemManager();
  fs.readFile({//读取文件并转为ArrayBuffer
    filePath: tempFilePath,
    success(res) {
      wx.showLoading({
        title: '正在语音识别中...',
      });
      const base64Data = wx.arrayBufferToBase64(res.data);
      var fileSize = res.data.byteLength ;
      var paramJson = {
        format: 'pcm',
        sampleRate: 16000,
        encodeBitRate: 48000,
        data: base64Data
      };
      wxUtil.post('wx/audioupload', paramJson, wxUtil.audio, { isShowLoading: true }, (result) =>{
        console.log( result);
      });
    }
  })
});

Page({
  data: {},
  onLoad() {},
  //语音识别
  handleTouchStart: function(e){
    //录音参数
    const options = {
      sampleRate: 16000,
      numberOfChannels: 1,
      encodeBitRate: 48000,
      format: 'pcm'
    }
    //开启录音
    recorderManager.start(options);
    wx.showLoading({
      title: '正在录音中...',
    });
  },
  handleTouchEnd: function(e){
    recorderManager.stop();//stop之后就会触发onStop事件
  }
})

这样,我们是直接把语音文件转为base64的字符串,发往后端。后端就去调用百度的接口转为文字。百度的接口虽然付费,但是有免费调用量,需要先注册账号,申请应用,然后调用。

调用之前需要先获取百度语音的accessToken:

public static BaiduAudioAccessTokenVO getAccessToken(String apiKey,String secretKey){
    Map<String, String> parameters = new HashMap<>();
    parameters.put("grant_type","client_credentials");
    parameters.put("client_id",apiKey);
    parameters.put("client_secret",secretKey);
    String response = HttpUtil.sendPost("https://aip.baidubce.com/oauth/2.0/token",parameters);
    log.info("调用百度语音accessToken返回:" + response);
    BaiduAudioAccessTokenVO baiduAudioAccessTokenVO = JSON.parseObject(response, BaiduAudioAccessTokenVO.class);
    ParamCheckUtil.objectNull(baiduAudioAccessTokenVO,"调用接口未获取到accessToken");
    ParamCheckUtil.stringEmpty(baiduAudioAccessTokenVO.getAccess_token(),"调用接口未获取到accessToken");
    return baiduAudioAccessTokenVO;
}

接着调用百度语音接口:

public String transToText(String base64Audio,Integer len,String format,Integer rate) {
  //1参数校验
  ParamCheckUtil.stringEmpty(base64Audio,"语音文件为空");
  ParamCheckUtil.stringEmpty(format,"语音格式不能为空");
  ParamCheckUtil.notTrue(
          "pcm".equalsIgnoreCase(format)
                  || "wav".equalsIgnoreCase(format)
                  || "amr".equalsIgnoreCase(format),"语音文件格式不符合要求");

  //2 获取百度语音accessToken
  String accessToken = this.getAccessToken();
  //3 语音转为文字
  BaiduAudio2TextDTO audio2TextDTO = new BaiduAudio2TextDTO();
  audio2TextDTO.setFormat(format);
  audio2TextDTO.setRate(rate);
  audio2TextDTO.setCuid(baiduAudioProperties.getAppID());
  audio2TextDTO.setToken(accessToken);
  audio2TextDTO.setLen(len);
  audio2TextDTO.setBase64Audio(base64Audio);
  String text = BaiduAudioUtil.audio2Text(audio2TextDTO);
  log.info("翻译文字为:" + text);
  return text;
}

//工具类
public static String audio2Text(BaiduAudio2TextDTO baiduAudio2TextDTO){
    Map<String, Object> parameters = new HashMap<>();
    parameters.put("format",baiduAudio2TextDTO.getFormat());
    parameters.put("rate",baiduAudio2TextDTO.getRate());
    parameters.put("channel",1);
    parameters.put("cuid",baiduAudio2TextDTO.getCuid());
    parameters.put("token",baiduAudio2TextDTO.getToken());
    parameters.put("speech",baiduAudio2TextDTO.getBase64Audio());
    parameters.put("len",baiduAudio2TextDTO.getLen());
    String response = HttpUtil.sendPostJson("https://vop.baidu.com/server_api",JSON.toJSONString(parameters));
    log.info("语音转换接口返回:" + response);
    ParamCheckUtil.stringEmpty(response,"语音转换接口返回为空");
    BaiduAudio2TextVO textVO = JSON.parseObject(response, BaiduAudio2TextVO.class);
    return textVO.getResult().get(0);
}

就这样,就完成了。

上一篇 下一篇

猜你喜欢

热点阅读