java.io.IOException: mark/reset not supported

关于调用百度语音识别API出现的小bug

这是我在小程序段测试语音识别功能出现的问题!
java.io.IOException: mark/reset not supported

小程序实现语音识别

在讲上面的bug之前我先提一下用小程序实现语音识别的大致流程吧。

  • 首先在小程序端长按按钮进行录音,得到一份MP3格式的音频文件
  • 由于百度的语音识别AI接口无法直接识别压缩的MP3格式的文件,所以需要有一个音频格式转换的函数,将mp3文件转换为pcm文件。
  • 之后进行识别,然后将识别结果重新返回到前端进行展示。

小程序段js代码

var hotapp = require('../../utils/hotapp.js');
//获取应用实例
var app = getApp();
const recorderManager = wx.getRecorderManager()
Page({
  data: {
    cancel: false,
    inputValue: [],
    focus: false
  },
  onLoad: function (options) {
    console.log(recorderManager)
  
  },
  //开始录音
  start: function () {
    const options = {
      duration: 60000,//ms,最长只有60s
      sampleRate: 16000,//采样率
      numberOfChannels: 1,//通道数
      encodeBitRate: 96000,
      format: 'mp3',
      frameSize: 50,
    }
    recorderManager.start(options);
    // 开始录音回调
    recorderManager.onStart(() => {
      console.log('开始录音')
    });
    // 错误回调
    recorderManager.onError((res) => {
      console.log(res)
    })
  },

  //停止录音
  stop: function () {
    recorderManager.stop();
    var that = this
    recorderManager.onStop((res) => {
      console.log('停止录音')
      console.log(res)
      console.log(res.tempFilePath)
      wx.uploadFile({
        url: 'http://192.168.1.102:8080/bigballoon/ai/speechRecognition.do',
        filePath: res.tempFilePath,
        name: 'speechFile',
        success: function (res) {
          console.log(res.data);
          that.setData({
            inputValue: res.data.substring(0, res.data.length-1)
          });
        },
        fail: function () {
          console.log("语音识别失败");
        }
      })
    }
    );
  },

  longPress: function () {
    console.log('longPress....')
  },

  touchStart: function () {
    console.log('touchStart....')
    this.start()
  },


  touchEnd: function () {
    console.log('touchEnd....')
    this.stop();
  },  
  formSubmit: function (e) {
    var that = this;
    var keyword = null;
    if (e.detail.value.book) {
      keyword = e.detail.value.book;
      that.search(keyword);
    } else {
      wx.showToast({
        title: '您没有输入哦',
        icon: 'success',
        duration: 10000
      })
      setTimeout(function () {
        wx.hideToast()
      }, 1000)
      return false;
    }
  },

  enterSubmit: function (e) {
    var that = this;
    var keyword = null;
    if (e.detail.value) {
      keyword = e.detail.value;
      that.search(keyword);
    } else {
      wx.showToast({
        title: '您没有输入哦',
        icon: 'success',
        duration: 10000
      })
      setTimeout(function () {
        wx.hideToast()
      }, 1000)
      return false;
    }
  }

  
  }


})

后台函数代码

/**
	 * 语音识别
	 * @param request
	 * @return 
	 * @throws Exception 
	 */
    @ResponseBody
	@RequestMapping("/speechRecognition")
	public void speechRecognition(HttpServletRequest request, HttpServletResponse response) throws Exception {
		log.info("---------进入speechRecognition函数---------");
		
//		response.setContentType("text/html;charset=utf-8");          
//	    response.setHeader("Access-Control-Allow-Origin", "*");  
//	    response.setHeader("Access-Control-Allow-Methods", "GET,POST"); 
	        
		MultipartFile  file = ((MultipartHttpServletRequest) request).getFile("speechFile");
		byte[] pcmBytes = mp3Convertpcm(file.getInputStream());
	
		JSONObject res = speech_client.asr(pcmBytes, "pcm", 16000, null);
		String result = res.getJSONArray("result").get(0).toString().split(",")[0];
		Writer out = response.getWriter(); 
		out.write(result);
		out.flush();   
	}

	private byte[] mp3Convertpcm(InputStream mp3Stream) throws Exception {
		BufferedInputStream zipTest=new BufferedInputStream(mp3Stream);
		AudioInputStream mp3audioStream = AudioSystem.getAudioInputStream(zipTest);
		AudioInputStream pcmaudioStream = AudioSystem.getAudioInputStream(AudioFormat.Encoding.PCM_SIGNED,mp3audioStream);
		byte[] pcmBytes = IOUtils.toByteArray(pcmaudioStream);
		pcmaudioStream.close();
	    mp3audioStream.close();
		return pcmBytes;
	}

关于如何实现mp3Convertpcm()函数

我们需要在maven的pom文件里面加入一个依赖


		<!-- MP3转PCM -->
		<dependency>
			<groupId>com.googlecode.soundlibs</groupId>
   	 		<artifactId>mp3spi</artifactId>
    		<version>1.9.5.4</version>
		</dependency>

我调试时碰到的问题

回到最前面,大家也看到了我的控制台报错情况了。
java.io.IOException: mark/reset not supported
当时mp3Convertpcm()函数里面是没有第一行这行封装代码的,当然我也是通过加入这一行来解决了这个bug。

BufferedInputStream zipTest=new BufferedInputStream(mp3Stream);

可我很困惑的是之前在学长的Windows上测试的时候本就没有这一步操作,却能够正常进行语音识别,而我这边调试的时候就又挂了,不明白为啥。
另外我其实对这个IO异常并不了解,即使bug改过来了,但是没怎么搞明白是怎么一回事,原理方面仍旧没有搞懂。