以微薄之力推动正能量 發表於 2025-12-26 09:31:00

语音识别服务funasr搭建

<p><span style="font-size: 16px">本文讨论语音识别功能,使用的是阿里的开源语音识别项目FunASR,<span class="ne-text">含两种部署方式,社区windows版和docker容器化部署,windows社区版的可以用于本地开发使用,生产环境建议使用容器版。</span></span></p>
<h2><span class="ne-text" style="font-size: 16px">1、windows社区版部署</span></h2>
<h3><span class="ne-text" style="font-size: 16px">  1.1、环境安装</span></h3>
<p><span class="ne-text" style="font-size: 16px">    软件需要Visual Studio 2022 c++环境,</span>如果没有Visual Studio 2022 c++运行环境,双击 VC_redist.x64(2022).exe 安装 Visual Studio 2022环境下编译的C++程序运行所需要的库。</p>
<h3>   1.2、<span class="ne-text">下载windows社区软件包<br></span></h3>
<p><span class="ne-text">    </span><span class="ne-text">https://www.modelscope.cn/models/iic/funasr-runtime-win-cpu-x64/files</span></p>
<p>    <img alt="image" width="1253" height="478" loading="lazy" src="https://img2024.cnblogs.com/blog/1607557/202512/1607557-20251226091034169-345184089.png" class="lazyload"></p>
<p>    <span class="ne-text">随便选个版本的下载,这里选择的是0.2.0版本</span></p>
<h3><span class="ne-text">   1.3、</span><span class="ne-text">下载所需模型</span></h3>
<div class="cnblogs_code">
<pre>git clone https://www.modelscope.cn/damo/speech_fsmn_vad_zh-cn-16k-common-<span style="color: rgba(0, 0, 0, 1)">onnx.git;

git clone https:</span>//www.modelscope.cn/damo/speech_paraformer-large-vad-punc_asr_nat-zh-cn-16k-common-vocab8404-<span style="color: rgba(0, 0, 0, 1)">onnx.git;

git clone https:</span>//www.modelscope.cn/damo/speech_ngram_lm_zh-cn-ai-wesp-<span style="color: rgba(0, 0, 0, 1)">fst.git;

git clone https:</span>//www.modelscope.cn/damo/punc_ct-transformer_cn-en-common-vocab471067-large-<span style="color: rgba(0, 0, 0, 1)">onnx.git;

git clone https:</span>//www.modelscope.cn/thuduj12/fst_itn_zh.git</pre>
</div>
<h3>   1.4、<span class="ne-text">启动服务</span></h3>
<p>&nbsp;    <span class="ne-text">将上面下载的windows社区软件包解压后,打开powershell,进入到解压后的目录,执行下面的命令</span></p>
<div class="cnblogs_code">
<pre>./funasr-wss-<span style="color: rgba(0, 0, 0, 1)">server.exe
</span>--vad-dir D:/developTest/funasr-runtime-resources/models/speech_fsmn_vad_zh-cn-16k-common-<span style="color: rgba(0, 0, 0, 1)">onnx
</span>--model-dir D:/developTest/funasr-runtime-resources/models/speech_paraformer-large-vad-punc_asr_nat-zh-cn-16k-common-vocab8404-<span style="color: rgba(0, 0, 0, 1)">onnx
</span>--lm-dir D:/developTest/funasr-runtime-resources/models/speech_ngram_lm_zh-cn-ai-wesp-<span style="color: rgba(0, 0, 0, 1)">fst
</span>--punc-dir D:/developTest/funasr-runtime-resources/models/punc_ct-transformer_cn-en-common-vocab471067-large-<span style="color: rgba(0, 0, 0, 1)">onnx
</span>--itn-dir D:/developTest/funasr-runtime-resources/models/<span style="color: rgba(0, 0, 0, 1)">fst_itn_zh
</span>--certfile 0</pre>
</div>
<p>    参数说明:</p>
<div class="cnblogs_code">
<pre>--model-<span style="color: rgba(0, 0, 0, 1)">dirmodelscope model ID 或者 本地模型路径
</span>--vad-<span style="color: rgba(0, 0, 0, 1)">dirmodelscope model ID 或者 本地模型路径
</span>--punc-<span style="color: rgba(0, 0, 0, 1)">dirmodelscope model ID 或者 本地模型路径
</span>--lm-<span style="color: rgba(0, 0, 0, 1)">dir modelscope model ID 或者 本地模型路径
</span>--itn-<span style="color: rgba(0, 0, 0, 1)">dir modelscope model ID 或者 本地模型路径
</span>--certfilessl的证书文件,如果需要关闭ssl,参数设置为0</pre>
</div>
<h3>   1.5、<span class="ne-text">客户端调用</span></h3>
<p><span class="ne-text">    </span><span class="ne-text">在windows社区版的解压目录下有客户端执行文件<span class="ne-text">funasr-wss-client.exe</span></span></p>
<div class="cnblogs_code">
<pre>./funasr-wss-client.exe --server-ip 127.0.0.1 --port 10095 --wav-path asr_example_zh.wav</pre>
</div>
<p>    <span class="ne-text">服务默认端口是10095,--wav-path指定音频文件地址</span></p>
<h2><span class="ne-text">2、docker容器化部署</span></h2>
<h3><span class="ne-text">   2.1、</span><span class="ne-text">拉取docker镜像</span></h3>
<div class="cnblogs_code">
<pre>docker pull registry.cn-hangzhou.aliyuncs.com/funasr_repo/funasr:funasr-runtime-sdk-cpu-0.4.6</pre>
</div>
<h3>   2.2、<span class="ne-text">启动容器</span></h3>
<p><span class="ne-text">    </span><span class="ne-text">在宿主机创建模型目录放置模型,这里的模型建议手动下载,就用上面的git下载下来,如果使用启动命令自动下载会很慢很卡。</span></p>
<div class="cnblogs_code">
<pre>docker run -p 10095:10095 -it --privileged=<span style="color: rgba(0, 0, 255, 1)">true</span> -v D:\developTest\funasr-runtime-resources\models:/workspace/models registry.cn-hangzhou.aliyuncs.com/funasr_repo/funasr:funasr-runtime-sdk-cpu-0.4.6</pre>
</div>
<p>    <span class="ne-text">映射容器端口,挂载之前创建的存放模型目录到容器内部。</span></p>
<h3><span class="ne-text">   2.3、启动服务</span></h3>
<p>    进入容器内部,进到FunASR/runtime目录下</p>
<p>    <img alt="image" loading="lazy" src="https://img2024.cnblogs.com/blog/1607557/202512/1607557-20251226092232599-408304639.png" class="lazyload"></p>
<p>&nbsp;    执行如下命令启动服务</p>
<div class="cnblogs_code">
<pre><span style="color: rgba(0, 0, 0, 1)">nohup bash run_server.sh \
</span>--certfile 0<span style="color: rgba(0, 0, 0, 1)"> \
</span>--vad-dir speech_fsmn_vad_zh-cn-16k-common-<span style="color: rgba(0, 0, 0, 1)">onnx \
</span>--model-dir speech_paraformer-large-vad-punc_asr_nat-zh-cn-16k-common-vocab8404-<span style="color: rgba(0, 0, 0, 1)">onnx   \
</span>--punc-dir punc_ct-transformer_cn-en-common-vocab471067-large-<span style="color: rgba(0, 0, 0, 1)">onnx\
</span>--lm-dir speech_ngram_lm_zh-cn-ai-wesp-<span style="color: rgba(0, 0, 0, 1)">fst \
</span>--itn-dir fst_itn_zh&gt; log.txt 2&gt;&amp;1 &amp;</pre>
</div>
<p>    <span class="ne-text">指定模型目录,这里的模型都是事先下载好的,就不需要通过启动命令下载了,certfile设为0,表示关闭ssl。</span></p>
<h2>3、调用示例</h2>
<p>  这里大致写了两种java调用方式一种是通过<span class="ne-text">ProcessBuilder,一种是</span><span class="ne-text">WebSocketClient,大家可以用来看看。</span></p>
<div class="lake-content">
<ul class="ne-ul">
<li id="u0a0bed12" data-lake-index-type="0"><span class="ne-text">使用ProcessBuilder,运行上面的客户端执行命令,获取执行结果</span></li>
</ul>
<div class="cnblogs_code"><img id="code_img_closed_ee8da724-9620-48b4-9e11-58304394a99c" class="code_img_closed lazyload" data-src="http://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif"><img id="code_img_opened_ee8da724-9620-48b4-9e11-58304394a99c" class="code_img_opened lazyload" style="display: none" data-src="http://images.cnblogs.com/OutliningIndicators/ExpandedBlockStart.gif">
<div id="cnblogs_code_open_ee8da724-9620-48b4-9e11-58304394a99c" class="cnblogs_code_hide">
<pre><span style="color: rgba(0, 0, 255, 1)">public</span><span style="color: rgba(0, 0, 0, 1)"> String localTranslation(MultipartRequest multipartRequest) {
      StringBuffer resultBuffer </span>= <span style="color: rgba(0, 0, 255, 1)">new</span><span style="color: rgba(0, 0, 0, 1)"> StringBuffer();
      </span><span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)"> 需要传递给exe程序的参数</span>
      String exePath = "D:\\developTest\\funasr-runtime-resources\\funasr-runtime-win-cpu-x64\\funasr-runtime-win-cpu-x64-v0.2.0\\funasr-wss-client.exe"<span style="color: rgba(0, 0, 0, 1)">;
      String serveIp </span>= "127.0.0.1"; <span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)"> 假设你想要设置的IP地址</span>
      String port = "10095"<span style="color: rgba(0, 0, 0, 1)">;
      File targetFile </span>= <span style="color: rgba(0, 0, 255, 1)">null</span><span style="color: rgba(0, 0, 0, 1)">;

      </span><span style="color: rgba(0, 0, 255, 1)">try</span><span style="color: rgba(0, 0, 0, 1)"> {
            MultipartFile mFile </span>= multipartRequest.getFile("file"<span style="color: rgba(0, 0, 0, 1)">);
            File dir </span>= <span style="color: rgba(0, 0, 255, 1)">new</span> File("D:\\developTest\\funasr-runtime-resources\\wav"<span style="color: rgba(0, 0, 0, 1)">);
            </span><span style="color: rgba(0, 0, 255, 1)">if</span> (!<span style="color: rgba(0, 0, 0, 1)">dir.exists()) {
                dir.mkdirs();
            }
            targetFile </span>= File.createTempFile("tmp_", ".wav"<span style="color: rgba(0, 0, 0, 1)">, dir);
            mFile.transferTo(targetFile);

            String wavPath </span>= "D:\\developTest\\funasr-runtime-resources\\wav\\"+<span style="color: rgba(0, 0, 0, 1)"> targetFile.getName();
            String[] cmd </span>= <span style="color: rgba(0, 0, 255, 1)">new</span> String[]{exePath, "--server-ip", serveIp, "--port", port, "--wav-path"<span style="color: rgba(0, 0, 0, 1)">, wavPath};
            ProcessBuilder pb </span>= <span style="color: rgba(0, 0, 255, 1)">new</span><span style="color: rgba(0, 0, 0, 1)"> ProcessBuilder();
            pb.command(cmd);

            Process process </span>=<span style="color: rgba(0, 0, 0, 1)"> pb.start();
            </span><span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)">超时时间</span>
            <span style="color: rgba(0, 0, 255, 1)">int</span> timeoutSeconds = 30;<span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)">超时30秒自动断开

            </span><span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)">创建单线程线程池</span>
            ExecutorService executor =<span style="color: rgba(0, 0, 0, 1)"> Executors.newSingleThreadExecutor();
            Future</span>&lt;?&gt; future = executor.submit(() -&gt;<span style="color: rgba(0, 0, 0, 1)"> {
                </span><span style="color: rgba(0, 0, 255, 1)">try</span><span style="color: rgba(0, 0, 0, 1)"> {
                  pb.redirectErrorStream(</span><span style="color: rgba(0, 0, 255, 1)">true</span><span style="color: rgba(0, 0, 0, 1)">);
                  </span><span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)"> 读取外部程序的输出</span>
                  BufferedReader reader = <span style="color: rgba(0, 0, 255, 1)">new</span> BufferedReader(<span style="color: rgba(0, 0, 255, 1)">new</span><span style="color: rgba(0, 0, 0, 1)"> InputStreamReader(process.getInputStream()));
                  String line;
                  </span><span style="color: rgba(0, 0, 255, 1)">while</span> ((line = reader.readLine()) != <span style="color: rgba(0, 0, 255, 1)">null</span><span style="color: rgba(0, 0, 0, 1)">) {
                        System.out.println(line);
                        resultBuffer.append(line);
                  }

                  </span><span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)"> 处理错误输出</span>
                  BufferedReader errorReader = <span style="color: rgba(0, 0, 255, 1)">new</span> BufferedReader(<span style="color: rgba(0, 0, 255, 1)">new</span><span style="color: rgba(0, 0, 0, 1)"> InputStreamReader(process.getErrorStream()));
                  </span><span style="color: rgba(0, 0, 255, 1)">while</span> ((line = errorReader.readLine()) != <span style="color: rgba(0, 0, 255, 1)">null</span><span style="color: rgba(0, 0, 0, 1)">) {
                        System.out.println(line);
                        </span><span style="color: rgba(0, 0, 255, 1)">if</span>(line.contains("on_message"<span style="color: rgba(0, 0, 0, 1)">)){
                            String[] array </span>= line.split("on_message ="<span style="color: rgba(0, 0, 0, 1)">);
                            resultBuffer.append(array[</span>1<span style="color: rgba(0, 0, 0, 1)">]);
                        }
                  }
                  </span><span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)"> 等待程序执行完成</span>
<span style="color: rgba(0, 0, 0, 1)">                  process.waitFor();
                } </span><span style="color: rgba(0, 0, 255, 1)">catch</span><span style="color: rgba(0, 0, 0, 1)"> (Exception e) {
                  e.printStackTrace();
                }</span><span style="color: rgba(0, 0, 255, 1)">finally</span><span style="color: rgba(0, 0, 0, 1)"> {
                  </span><span style="color: rgba(0, 0, 255, 1)">if</span><span style="color: rgba(0, 0, 0, 1)">(process.isAlive()){
                        process.destroy();
                  }
                }
            });
            </span><span style="color: rgba(0, 0, 255, 1)">try</span><span style="color: rgba(0, 0, 0, 1)"> {
                </span><span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)"> 等待进程完成或超时</span>
<span style="color: rgba(0, 0, 0, 1)">                future.get(timeoutSeconds, TimeUnit.SECONDS);
                System.out.println(</span>"进程在规定时间内完成。"<span style="color: rgba(0, 0, 0, 1)">);
            } </span><span style="color: rgba(0, 0, 255, 1)">catch</span><span style="color: rgba(0, 0, 0, 1)"> (Exception e) {
                System.out.println(</span>"超时预警: 进程可能挂起。"<span style="color: rgba(0, 0, 0, 1)">);
                resultBuffer.append(</span>"timeout"<span style="color: rgba(0, 0, 0, 1)">);
            } </span><span style="color: rgba(0, 0, 255, 1)">finally</span><span style="color: rgba(0, 0, 0, 1)"> {
                </span><span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)">关闭连接</span>
                <span style="color: rgba(0, 0, 255, 1)">if</span><span style="color: rgba(0, 0, 0, 1)">(process.isAlive()){
                  process.destroy();
                }
                executor.shutdownNow(); </span><span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)"> 取消任务并关闭线程池</span>
<span style="color: rgba(0, 0, 0, 1)">            }
      } </span><span style="color: rgba(0, 0, 255, 1)">catch</span><span style="color: rgba(0, 0, 0, 1)"> (Exception e) {
            e.printStackTrace();
            resultBuffer.append(</span>"error"<span style="color: rgba(0, 0, 0, 1)">);
      }</span><span style="color: rgba(0, 0, 255, 1)">finally</span><span style="color: rgba(0, 0, 0, 1)"> {
            </span><span style="color: rgba(0, 0, 255, 1)">if</span><span style="color: rgba(0, 0, 0, 1)"> (targetFile.exists()) {
                targetFile.delete();
            }
      }
      System.out.println(resultBuffer.toString());
      </span><span style="color: rgba(0, 0, 255, 1)">return</span><span style="color: rgba(0, 0, 0, 1)"> resultBuffer.toString();
    }</span></pre>
</div>
<span class="cnblogs_code_collapse">View Code</span></div>
<div class="lake-content">
<ul class="ne-ul">
<li id="u199a6f15" data-lake-index-type="0"><span class="ne-text">使用WebSocketClient直接调用FunASR服务</span></li>
</ul>
<p><span class="ne-text">  </span><span class="ne-text">Client工具类</span></p>
<div class="cnblogs_code"><img id="code_img_closed_b0c7855c-8229-4a70-a43a-7df98e723287" class="code_img_closed lazyload" data-src="http://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif"><img id="code_img_opened_b0c7855c-8229-4a70-a43a-7df98e723287" class="code_img_opened lazyload" style="display: none" data-src="http://images.cnblogs.com/OutliningIndicators/ExpandedBlockStart.gif">
<div id="cnblogs_code_open_b0c7855c-8229-4a70-a43a-7df98e723287" class="cnblogs_code_hide">
<pre><span style="color: rgba(0, 0, 255, 1)">package</span><span style="color: rgba(0, 0, 0, 1)"> com.example.demo1.web;

</span><span style="color: rgba(0, 0, 255, 1)">import</span> java.io.*<span style="color: rgba(0, 0, 0, 1)">;
</span><span style="color: rgba(0, 0, 255, 1)">import</span><span style="color: rgba(0, 0, 0, 1)"> java.net.URI;
</span><span style="color: rgba(0, 0, 255, 1)">import</span><span style="color: rgba(0, 0, 0, 1)"> java.util.Map;
</span><span style="color: rgba(0, 0, 255, 1)">import</span><span style="color: rgba(0, 0, 0, 1)"> org.java_websocket.client.WebSocketClient;
</span><span style="color: rgba(0, 0, 255, 1)">import</span><span style="color: rgba(0, 0, 0, 1)"> org.java_websocket.drafts.Draft;
</span><span style="color: rgba(0, 0, 255, 1)">import</span><span style="color: rgba(0, 0, 0, 1)"> org.java_websocket.handshake.ServerHandshake;
</span><span style="color: rgba(0, 0, 255, 1)">import</span><span style="color: rgba(0, 0, 0, 1)"> org.json.simple.JSONArray;
</span><span style="color: rgba(0, 0, 255, 1)">import</span><span style="color: rgba(0, 0, 0, 1)"> org.json.simple.JSONObject;
</span><span style="color: rgba(0, 0, 255, 1)">import</span><span style="color: rgba(0, 0, 0, 1)"> org.json.simple.parser.JSONParser;
</span><span style="color: rgba(0, 0, 255, 1)">import</span><span style="color: rgba(0, 0, 0, 1)"> org.slf4j.Logger;
</span><span style="color: rgba(0, 0, 255, 1)">import</span><span style="color: rgba(0, 0, 0, 1)"> org.slf4j.LoggerFactory;
</span><span style="color: rgba(0, 0, 255, 1)">import</span><span style="color: rgba(0, 0, 0, 1)"> java.util.regex.Matcher;
</span><span style="color: rgba(0, 0, 255, 1)">import</span><span style="color: rgba(0, 0, 0, 1)"> java.util.regex.Pattern;

</span><span style="color: rgba(0, 0, 255, 1)">public</span> <span style="color: rgba(0, 0, 255, 1)">class</span> FunasrWsClient <span style="color: rgba(0, 0, 255, 1)">extends</span><span style="color: rgba(0, 0, 0, 1)"> WebSocketClient {

    </span><span style="color: rgba(0, 0, 255, 1)">private</span> <span style="color: rgba(0, 0, 255, 1)">static</span> <span style="color: rgba(0, 0, 255, 1)">final</span> Logger logger = LoggerFactory.getLogger(FunasrWsClient.<span style="color: rgba(0, 0, 255, 1)">class</span><span style="color: rgba(0, 0, 0, 1)">);

    </span><span style="color: rgba(0, 0, 255, 1)">private</span> <span style="color: rgba(0, 0, 255, 1)">boolean</span> iseof = <span style="color: rgba(0, 0, 255, 1)">false</span><span style="color: rgba(0, 0, 0, 1)">;
    </span><span style="color: rgba(0, 0, 255, 1)">private</span> <span style="color: rgba(0, 0, 255, 1)">static</span><span style="color: rgba(0, 0, 0, 1)"> String wavPath;
    </span><span style="color: rgba(0, 0, 255, 1)">private</span> <span style="color: rgba(0, 0, 255, 1)">static</span> String mode = "offline"<span style="color: rgba(0, 0, 0, 1)">;
    </span><span style="color: rgba(0, 0, 255, 1)">private</span> <span style="color: rgba(0, 0, 255, 1)">static</span> String strChunkSize = "5,10,5"<span style="color: rgba(0, 0, 0, 1)">;
    </span><span style="color: rgba(0, 0, 255, 1)">private</span> <span style="color: rgba(0, 0, 255, 1)">static</span> <span style="color: rgba(0, 0, 255, 1)">int</span> chunkInterval = 10<span style="color: rgba(0, 0, 0, 1)">;
    </span><span style="color: rgba(0, 0, 255, 1)">private</span> <span style="color: rgba(0, 0, 255, 1)">static</span> <span style="color: rgba(0, 0, 255, 1)">int</span> sendChunkSize = 1920<span style="color: rgba(0, 0, 0, 1)">;
    </span><span style="color: rgba(0, 0, 255, 1)">private</span> <span style="color: rgba(0, 0, 255, 1)">static</span> String hotwords=""<span style="color: rgba(0, 0, 0, 1)">;
    </span><span style="color: rgba(0, 0, 255, 1)">private</span> <span style="color: rgba(0, 0, 255, 1)">static</span> String fsthotwords=""<span style="color: rgba(0, 0, 0, 1)">;
    </span><span style="color: rgba(0, 0, 255, 1)">private</span> String wavName = "javatest"<span style="color: rgba(0, 0, 0, 1)">;
    </span><span style="color: rgba(0, 0, 255, 1)">private</span><span style="color: rgba(0, 0, 0, 1)"> MyCallBack callBack;

    </span><span style="color: rgba(0, 0, 255, 1)">public</span><span style="color: rgba(0, 0, 0, 1)"> FunasrWsClient(URI serverUri,MyCallBack callBack) {
      </span><span style="color: rgba(0, 0, 255, 1)">super</span><span style="color: rgba(0, 0, 0, 1)">(serverUri);
      </span><span style="color: rgba(0, 0, 255, 1)">this</span>.callBack =<span style="color: rgba(0, 0, 0, 1)"> callBack;
    }

    </span><span style="color: rgba(0, 0, 255, 1)">public</span><span style="color: rgba(0, 0, 0, 1)"> FunasrWsClient(URI serverUri,String wavPath,MyCallBack callBack) {
      </span><span style="color: rgba(0, 0, 255, 1)">super</span><span style="color: rgba(0, 0, 0, 1)">(serverUri);
      </span><span style="color: rgba(0, 0, 255, 1)">this</span>.callBack =<span style="color: rgba(0, 0, 0, 1)"> callBack;
      </span><span style="color: rgba(0, 0, 255, 1)">this</span>.wavPath =<span style="color: rgba(0, 0, 0, 1)"> wavPath;
    }

    </span><span style="color: rgba(0, 0, 255, 1)">public</span> FunasrWsClient(URI serverUri,String strChunkSize,<span style="color: rgba(0, 0, 255, 1)">int</span><span style="color: rgba(0, 0, 0, 1)"> chunkInterval,String mode,String hotwords,String wavPath,MyCallBack callBack) {
      </span><span style="color: rgba(0, 0, 255, 1)">super</span><span style="color: rgba(0, 0, 0, 1)">(serverUri);
      </span><span style="color: rgba(0, 0, 255, 1)">this</span>.callBack =<span style="color: rgba(0, 0, 0, 1)"> callBack;
      </span><span style="color: rgba(0, 0, 255, 1)">this</span>.strChunkSize =<span style="color: rgba(0, 0, 0, 1)"> strChunkSize;
      </span><span style="color: rgba(0, 0, 255, 1)">this</span>.chunkInterval =<span style="color: rgba(0, 0, 0, 1)"> chunkInterval;
      </span><span style="color: rgba(0, 0, 255, 1)">this</span>.mode =<span style="color: rgba(0, 0, 0, 1)"> mode;
      </span><span style="color: rgba(0, 0, 255, 1)">this</span>.fsthotwords =<span style="color: rgba(0, 0, 0, 1)"> hotwords;
      </span><span style="color: rgba(0, 0, 255, 1)">this</span>.wavPath =<span style="color: rgba(0, 0, 0, 1)"> wavPath;

      </span><span style="color: rgba(0, 0, 255, 1)">int</span> RATE = 16000<span style="color: rgba(0, 0, 0, 1)">;
      String[] chunkList </span>= strChunkSize.split(","<span style="color: rgba(0, 0, 0, 1)">);
      </span><span style="color: rgba(0, 0, 255, 1)">int</span> int_chunk_size = 60 * Integer.valueOf(chunkList.trim()) /<span style="color: rgba(0, 0, 0, 1)"> chunkInterval;
      </span><span style="color: rgba(0, 0, 255, 1)">int</span> CHUNK = Integer.valueOf(RATE / 1000 *<span style="color: rgba(0, 0, 0, 1)"> int_chunk_size);
      </span><span style="color: rgba(0, 0, 255, 1)">this</span>.sendChunkSize = CHUNK * 2<span style="color: rgba(0, 0, 0, 1)">;
    }

    </span><span style="color: rgba(0, 0, 255, 1)">public</span> <span style="color: rgba(0, 0, 255, 1)">class</span> RecWavThread <span style="color: rgba(0, 0, 255, 1)">extends</span><span style="color: rgba(0, 0, 0, 1)"> Thread {
      </span><span style="color: rgba(0, 0, 255, 1)">private</span><span style="color: rgba(0, 0, 0, 1)"> FunasrWsClient funasrClient;

      </span><span style="color: rgba(0, 0, 255, 1)">public</span><span style="color: rgba(0, 0, 0, 1)"> RecWavThread(FunasrWsClient funasrClient) {
            </span><span style="color: rgba(0, 0, 255, 1)">this</span>.funasrClient =<span style="color: rgba(0, 0, 0, 1)"> funasrClient;
      }

      </span><span style="color: rgba(0, 0, 255, 1)">public</span> <span style="color: rgba(0, 0, 255, 1)">void</span><span style="color: rgba(0, 0, 0, 1)"> run() {
            </span><span style="color: rgba(0, 0, 255, 1)">this</span><span style="color: rgba(0, 0, 0, 1)">.funasrClient.recWav();
      }
    }

    </span><span style="color: rgba(0, 0, 255, 1)">public</span><span style="color: rgba(0, 0, 0, 1)"> FunasrWsClient(URI serverUri, Draft draft) {
      </span><span style="color: rgba(0, 0, 255, 1)">super</span><span style="color: rgba(0, 0, 0, 1)">(serverUri, draft);
    }

    </span><span style="color: rgba(0, 0, 255, 1)">public</span><span style="color: rgba(0, 0, 0, 1)"> FunasrWsClient(URI serverURI) {

      </span><span style="color: rgba(0, 0, 255, 1)">super</span><span style="color: rgba(0, 0, 0, 1)">(serverURI);
    }

    </span><span style="color: rgba(0, 0, 255, 1)">public</span> FunasrWsClient(URI serverUri, Map&lt;String, String&gt;<span style="color: rgba(0, 0, 0, 1)"> httpHeaders) {
      </span><span style="color: rgba(0, 0, 255, 1)">super</span><span style="color: rgba(0, 0, 0, 1)">(serverUri, httpHeaders);
    }

    </span><span style="color: rgba(0, 0, 255, 1)">public</span> <span style="color: rgba(0, 0, 255, 1)">void</span><span style="color: rgba(0, 0, 0, 1)"> getSslContext(String keyfile, String certfile) {
      </span><span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)"> TODO</span>
      <span style="color: rgba(0, 0, 255, 1)">return</span><span style="color: rgba(0, 0, 0, 1)">;
    }


    </span><span style="color: rgba(0, 0, 255, 1)">public</span> <span style="color: rgba(0, 0, 255, 1)">void</span><span style="color: rgba(0, 0, 0, 1)"> sendJson(
      String mode, String strChunkSize, </span><span style="color: rgba(0, 0, 255, 1)">int</span> chunkInterval, String wavName, <span style="color: rgba(0, 0, 255, 1)">boolean</span><span style="color: rgba(0, 0, 0, 1)"> isSpeaking,String suffix) {
      </span><span style="color: rgba(0, 0, 255, 1)">try</span><span style="color: rgba(0, 0, 0, 1)"> {

            JSONObject obj </span>= <span style="color: rgba(0, 0, 255, 1)">new</span><span style="color: rgba(0, 0, 0, 1)"> JSONObject();
            obj.put(</span>"mode"<span style="color: rgba(0, 0, 0, 1)">, mode);
            JSONArray array </span>= <span style="color: rgba(0, 0, 255, 1)">new</span><span style="color: rgba(0, 0, 0, 1)"> JSONArray();
            String[] chunkList </span>= strChunkSize.split(","<span style="color: rgba(0, 0, 0, 1)">);
            </span><span style="color: rgba(0, 0, 255, 1)">for</span> (<span style="color: rgba(0, 0, 255, 1)">int</span> i = 0; i &lt; chunkList.length; i++<span style="color: rgba(0, 0, 0, 1)">) {
                array.add(Integer.valueOf(chunkList.trim()));
            }

            obj.put(</span>"chunk_size"<span style="color: rgba(0, 0, 0, 1)">, array);
            obj.put(</span>"chunk_interval", <span style="color: rgba(0, 0, 255, 1)">new</span><span style="color: rgba(0, 0, 0, 1)"> Integer(chunkInterval));
            obj.put(</span>"wav_name"<span style="color: rgba(0, 0, 0, 1)">, wavName);

            </span><span style="color: rgba(0, 0, 255, 1)">if</span>(FunasrWsClient.hotwords.trim().length()&gt;0<span style="color: rgba(0, 0, 0, 1)">)
            {
                String regex </span>= "\\d+"<span style="color: rgba(0, 0, 0, 1)">;
                JSONObject jsonitems </span>= <span style="color: rgba(0, 0, 255, 1)">new</span><span style="color: rgba(0, 0, 0, 1)"> JSONObject();
                String[] items</span>=FunasrWsClient.hotwords.trim().split(" "<span style="color: rgba(0, 0, 0, 1)">);
                Pattern pattern </span>=<span style="color: rgba(0, 0, 0, 1)"> Pattern.compile(regex);
                String tmpWords</span>=""<span style="color: rgba(0, 0, 0, 1)">;
                </span><span style="color: rgba(0, 0, 255, 1)">for</span>(<span style="color: rgba(0, 0, 255, 1)">int</span> i=0;i&lt;items.length;i++<span style="color: rgba(0, 0, 0, 1)">)
                {

                  Matcher matcher </span>=<span style="color: rgba(0, 0, 0, 1)"> pattern.matcher(items);

                  </span><span style="color: rgba(0, 0, 255, 1)">if</span><span style="color: rgba(0, 0, 0, 1)"> (matcher.matches()) {

                        jsonitems.put(tmpWords.trim(), items.trim());
                        tmpWords</span>=""<span style="color: rgba(0, 0, 0, 1)">;
                        </span><span style="color: rgba(0, 0, 255, 1)">continue</span><span style="color: rgba(0, 0, 0, 1)">;
                  }
                  tmpWords</span>=tmpWords+items+" "<span style="color: rgba(0, 0, 0, 1)">;

                }



                obj.put(</span>"hotwords"<span style="color: rgba(0, 0, 0, 1)">, jsonitems.toString());
            }

            </span><span style="color: rgba(0, 0, 255, 1)">if</span>(suffix.equals("wav"<span style="color: rgba(0, 0, 0, 1)">)){
                suffix</span>="pcm"<span style="color: rgba(0, 0, 0, 1)">;
            }
            obj.put(</span>"wav_format"<span style="color: rgba(0, 0, 0, 1)">, suffix);
            </span><span style="color: rgba(0, 0, 255, 1)">if</span><span style="color: rgba(0, 0, 0, 1)"> (isSpeaking) {
                obj.put(</span>"is_speaking", <span style="color: rgba(0, 0, 255, 1)">new</span> Boolean(<span style="color: rgba(0, 0, 255, 1)">true</span><span style="color: rgba(0, 0, 0, 1)">));
            } </span><span style="color: rgba(0, 0, 255, 1)">else</span><span style="color: rgba(0, 0, 0, 1)"> {
                obj.put(</span>"is_speaking", <span style="color: rgba(0, 0, 255, 1)">new</span> Boolean(<span style="color: rgba(0, 0, 255, 1)">false</span><span style="color: rgba(0, 0, 0, 1)">));
            }
            logger.info(</span>"sendJson: " +<span style="color: rgba(0, 0, 0, 1)"> obj);
            </span><span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)"> return;</span>
<span style="color: rgba(0, 0, 0, 1)">
            send(obj.toString());

            </span><span style="color: rgba(0, 0, 255, 1)">return</span><span style="color: rgba(0, 0, 0, 1)">;
      } </span><span style="color: rgba(0, 0, 255, 1)">catch</span><span style="color: rgba(0, 0, 0, 1)"> (Exception e) {
            e.printStackTrace();
      }
    }


    </span><span style="color: rgba(0, 0, 255, 1)">public</span> <span style="color: rgba(0, 0, 255, 1)">void</span><span style="color: rgba(0, 0, 0, 1)"> sendEof() {
      </span><span style="color: rgba(0, 0, 255, 1)">try</span><span style="color: rgba(0, 0, 0, 1)"> {
            JSONObject obj </span>= <span style="color: rgba(0, 0, 255, 1)">new</span><span style="color: rgba(0, 0, 0, 1)"> JSONObject();

            obj.put(</span>"is_speaking", <span style="color: rgba(0, 0, 255, 1)">new</span> Boolean(<span style="color: rgba(0, 0, 255, 1)">false</span><span style="color: rgba(0, 0, 0, 1)">));

            logger.info(</span>"sendEof: " +<span style="color: rgba(0, 0, 0, 1)"> obj);
            </span><span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)"> return;</span>
<span style="color: rgba(0, 0, 0, 1)">
            send(obj.toString());
            iseof </span>= <span style="color: rgba(0, 0, 255, 1)">true</span><span style="color: rgba(0, 0, 0, 1)">;
            </span><span style="color: rgba(0, 0, 255, 1)">return</span><span style="color: rgba(0, 0, 0, 1)">;
      } </span><span style="color: rgba(0, 0, 255, 1)">catch</span><span style="color: rgba(0, 0, 0, 1)"> (Exception e) {
            e.printStackTrace();
      }
    }

   
    </span><span style="color: rgba(0, 0, 255, 1)">public</span> <span style="color: rgba(0, 0, 255, 1)">void</span><span style="color: rgba(0, 0, 0, 1)"> recWav() {
      String fileName</span>=<span style="color: rgba(0, 0, 0, 1)">FunasrWsClient.wavPath;
      String suffix</span>=fileName.split("\\.");
      sendJson(mode, strChunkSize, chunkInterval, wavName, </span><span style="color: rgba(0, 0, 255, 1)">true</span><span style="color: rgba(0, 0, 0, 1)">,suffix);
      File file </span>= <span style="color: rgba(0, 0, 255, 1)">new</span><span style="color: rgba(0, 0, 0, 1)"> File(FunasrWsClient.wavPath);

      </span><span style="color: rgba(0, 0, 255, 1)">int</span> chunkSize =<span style="color: rgba(0, 0, 0, 1)"> sendChunkSize;
      </span><span style="color: rgba(0, 0, 255, 1)">byte</span>[] bytes = <span style="color: rgba(0, 0, 255, 1)">new</span> <span style="color: rgba(0, 0, 255, 1)">byte</span><span style="color: rgba(0, 0, 0, 1)">;

      </span><span style="color: rgba(0, 0, 255, 1)">int</span> readSize = 0<span style="color: rgba(0, 0, 0, 1)">;
      </span><span style="color: rgba(0, 0, 255, 1)">try</span> (FileInputStream fis = <span style="color: rgba(0, 0, 255, 1)">new</span><span style="color: rgba(0, 0, 0, 1)"> FileInputStream(file)) {
            </span><span style="color: rgba(0, 0, 255, 1)">if</span> (FunasrWsClient.wavPath.endsWith(".wav"<span style="color: rgba(0, 0, 0, 1)">)) {
                fis.read(bytes, </span>0, 44<span style="color: rgba(0, 0, 0, 1)">);
            }
            readSize </span>= fis.read(bytes, 0<span style="color: rgba(0, 0, 0, 1)">, chunkSize);
            </span><span style="color: rgba(0, 0, 255, 1)">while</span> (readSize &gt; 0<span style="color: rgba(0, 0, 0, 1)">) {
                </span><span style="color: rgba(0, 0, 255, 1)">if</span> (readSize ==<span style="color: rgba(0, 0, 0, 1)"> chunkSize) {
                  send(bytes);

                } </span><span style="color: rgba(0, 0, 255, 1)">else</span><span style="color: rgba(0, 0, 0, 1)"> {
                  </span><span style="color: rgba(0, 0, 255, 1)">byte</span>[] tmpBytes = <span style="color: rgba(0, 0, 255, 1)">new</span> <span style="color: rgba(0, 0, 255, 1)">byte</span><span style="color: rgba(0, 0, 0, 1)">;
                  </span><span style="color: rgba(0, 0, 255, 1)">for</span> (<span style="color: rgba(0, 0, 255, 1)">int</span> i = 0; i &lt; readSize; i++<span style="color: rgba(0, 0, 0, 1)">) {
                        tmpBytes </span>=<span style="color: rgba(0, 0, 0, 1)"> bytes;
                  }
                  send(tmpBytes);
                }
               
                </span><span style="color: rgba(0, 0, 255, 1)">if</span> (!mode.equals("offline"<span style="color: rgba(0, 0, 0, 1)">)) {
                  Thread.sleep(Integer.valueOf(chunkSize </span>/ 32<span style="color: rgba(0, 0, 0, 1)">));
                }

                readSize </span>= fis.read(bytes, 0<span style="color: rgba(0, 0, 0, 1)">, chunkSize);
            }

            </span><span style="color: rgba(0, 0, 255, 1)">if</span> (!mode.equals("offline"<span style="color: rgba(0, 0, 0, 1)">)) {
                Thread.sleep(</span>2000<span style="color: rgba(0, 0, 0, 1)">);
                sendEof();
                Thread.sleep(</span>3000<span style="color: rgba(0, 0, 0, 1)">);
                close();
            } </span><span style="color: rgba(0, 0, 255, 1)">else</span><span style="color: rgba(0, 0, 0, 1)"> {
                sendEof();
            }

      } </span><span style="color: rgba(0, 0, 255, 1)">catch</span><span style="color: rgba(0, 0, 0, 1)"> (Exception e) {
            e.printStackTrace();
      }
    }

    @Override
    </span><span style="color: rgba(0, 0, 255, 1)">public</span> <span style="color: rgba(0, 0, 255, 1)">void</span><span style="color: rgba(0, 0, 0, 1)"> onOpen(ServerHandshake handshakedata) {

      RecWavThread thread </span>= <span style="color: rgba(0, 0, 255, 1)">new</span> RecWavThread(<span style="color: rgba(0, 0, 255, 1)">this</span><span style="color: rgba(0, 0, 0, 1)">);
      thread.start();
    }

    @Override
    </span><span style="color: rgba(0, 0, 255, 1)">public</span> <span style="color: rgba(0, 0, 255, 1)">void</span><span style="color: rgba(0, 0, 0, 1)"> onMessage(String message) {
      JSONObject jsonObject </span>= <span style="color: rgba(0, 0, 255, 1)">new</span><span style="color: rgba(0, 0, 0, 1)"> JSONObject();
      JSONParser jsonParser </span>= <span style="color: rgba(0, 0, 255, 1)">new</span><span style="color: rgba(0, 0, 0, 1)"> JSONParser();
      logger.info(</span>"received: " +<span style="color: rgba(0, 0, 0, 1)"> message);
      </span><span style="color: rgba(0, 0, 255, 1)">try</span><span style="color: rgba(0, 0, 0, 1)"> {
            jsonObject </span>=<span style="color: rgba(0, 0, 0, 1)"> (JSONObject) jsonParser.parse(message);
            logger.info(</span>"text: " + jsonObject.get("text"<span style="color: rgba(0, 0, 0, 1)">));
            callBack.callBack(jsonObject.get(</span>"text"<span style="color: rgba(0, 0, 0, 1)">));
            </span><span style="color: rgba(0, 0, 255, 1)">if</span>(jsonObject.containsKey("timestamp"<span style="color: rgba(0, 0, 0, 1)">))
            {
                logger.info(</span>"timestamp: " + jsonObject.get("timestamp"<span style="color: rgba(0, 0, 0, 1)">));
            }
      } </span><span style="color: rgba(0, 0, 255, 1)">catch</span><span style="color: rgba(0, 0, 0, 1)"> (org.json.simple.parser.ParseException e) {
            e.printStackTrace();
      }
      </span><span style="color: rgba(0, 0, 255, 1)">if</span> (iseof &amp;&amp; mode.equals("offline") &amp;&amp; !jsonObject.containsKey("is_final"<span style="color: rgba(0, 0, 0, 1)">)) {
            close();
      }

      </span><span style="color: rgba(0, 0, 255, 1)">if</span> (iseof &amp;&amp; mode.equals("offline") &amp;&amp; jsonObject.containsKey("is_final") &amp;&amp; jsonObject.get("is_final").equals("false"<span style="color: rgba(0, 0, 0, 1)">)) {
            close();
      }
    }

    @Override
    </span><span style="color: rgba(0, 0, 255, 1)">public</span> <span style="color: rgba(0, 0, 255, 1)">void</span> onClose(<span style="color: rgba(0, 0, 255, 1)">int</span> code, String reason, <span style="color: rgba(0, 0, 255, 1)">boolean</span><span style="color: rgba(0, 0, 0, 1)"> remote) {

      logger.info(
                </span>"Connection closed by "
                        + (remote ? "remote peer" : "us"<span style="color: rgba(0, 0, 0, 1)">)
                        </span>+ " Code: "
                        +<span style="color: rgba(0, 0, 0, 1)"> code
                        </span>+ " Reason: "
                        +<span style="color: rgba(0, 0, 0, 1)"> reason);
    }

    @Override
    </span><span style="color: rgba(0, 0, 255, 1)">public</span> <span style="color: rgba(0, 0, 255, 1)">void</span><span style="color: rgba(0, 0, 0, 1)"> onError(Exception ex) {
      logger.info(</span>"ex: " +<span style="color: rgba(0, 0, 0, 1)"> ex);
      ex.printStackTrace();
    }

}</span></pre>
</div>
<span class="cnblogs_code_collapse">View Code</span></div>
<div class="lake-content"><span class="ne-text">  调用工具类</span></div>
<div class="lake-content">
<div class="cnblogs_code"><img id="code_img_closed_2af70ca2-29d6-46e7-92ec-d8fd7d13b2df" class="code_img_closed lazyload" data-src="http://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif"><img id="code_img_opened_2af70ca2-29d6-46e7-92ec-d8fd7d13b2df" class="code_img_opened lazyload" style="display: none" data-src="http://images.cnblogs.com/OutliningIndicators/ExpandedBlockStart.gif">
<div id="cnblogs_code_open_2af70ca2-29d6-46e7-92ec-d8fd7d13b2df" class="cnblogs_code_hide">
<pre><span style="color: rgba(0, 0, 255, 1)">public</span> <span style="color: rgba(0, 0, 255, 1)">static</span> <span style="color: rgba(0, 0, 255, 1)">void</span> main(String[] args) <span style="color: rgba(0, 0, 255, 1)">throws</span><span style="color: rgba(0, 0, 0, 1)"> URISyntaxException {
    String srvIp </span>= "localhost"<span style="color: rgba(0, 0, 0, 1)">;
    String srvPort </span>= "10095"<span style="color: rgba(0, 0, 0, 1)">;
    String wavPath </span>= "D:\\developTest\\funasr-runtime-resources\\wav\\tmp_84677349854990998.wav"<span style="color: rgba(0, 0, 0, 1)">;
    Object lock </span>= <span style="color: rgba(0, 0, 255, 1)">new</span><span style="color: rgba(0, 0, 0, 1)"> Object();

    StringBuffer text </span>= <span style="color: rgba(0, 0, 255, 1)">new</span><span style="color: rgba(0, 0, 0, 1)"> StringBuffer();
    ExecutorService executor </span>=<span style="color: rgba(0, 0, 0, 1)"> Executors.newSingleThreadExecutor();
    Future</span>&lt;?&gt; future = executor.submit(()-&gt;<span style="color: rgba(0, 0, 0, 1)">{
      </span><span style="color: rgba(0, 0, 255, 1)">try</span><span style="color: rgba(0, 0, 0, 1)"> {
            String wsAddress </span>= "ws://" + srvIp + ":" +<span style="color: rgba(0, 0, 0, 1)"> srvPort;

            FunasrWsClient c </span>= <span style="color: rgba(0, 0, 255, 1)">new</span> FunasrWsClient(<span style="color: rgba(0, 0, 255, 1)">new</span> URI(wsAddress),wavPath,<span style="color: rgba(0, 0, 255, 1)">new</span><span style="color: rgba(0, 0, 0, 1)"> MyCallBack(){
                @Override
                </span><span style="color: rgba(0, 0, 255, 1)">public</span> <span style="color: rgba(0, 0, 255, 1)">void</span><span style="color: rgba(0, 0, 0, 1)"> callBack(Object obj){
                  text.append(obj.toString());
                  </span><span style="color: rgba(0, 0, 255, 1)">synchronized</span><span style="color: rgba(0, 0, 0, 1)"> (lock){
                        </span><span style="color: rgba(0, 0, 255, 1)">try</span><span style="color: rgba(0, 0, 0, 1)"> {
                            lock.notify();
                        }</span><span style="color: rgba(0, 0, 255, 1)">catch</span><span style="color: rgba(0, 0, 0, 1)"> (Exception e){
                            e.printStackTrace();
                        }
                  }
                }
            });

            </span><span style="color: rgba(0, 0, 255, 1)">synchronized</span><span style="color: rgba(0, 0, 0, 1)"> (lock){
                c.connect();
                lock.wait();
            }
      }</span><span style="color: rgba(0, 0, 255, 1)">catch</span><span style="color: rgba(0, 0, 0, 1)"> (Exception e){
            </span><span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)"> e.printStackTrace();</span>
<span style="color: rgba(0, 0, 0, 1)">      }
    });
    </span><span style="color: rgba(0, 0, 255, 1)">try</span><span style="color: rgba(0, 0, 0, 1)"> {
      future.get(</span>10<span style="color: rgba(0, 0, 0, 1)">, TimeUnit.SECONDS);
      System.out.println(</span>"规定时间内完成"<span style="color: rgba(0, 0, 0, 1)">);
    }</span><span style="color: rgba(0, 0, 255, 1)">catch</span><span style="color: rgba(0, 0, 0, 1)"> (Exception e){
      </span><span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)"> e.printStackTrace();</span>
      System.out.println("任务超时"<span style="color: rgba(0, 0, 0, 1)">);
      text.append(</span>"任务超时"<span style="color: rgba(0, 0, 0, 1)">);
    }</span><span style="color: rgba(0, 0, 255, 1)">finally</span><span style="color: rgba(0, 0, 0, 1)"> {
      executor.shutdownNow(); </span><span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)"> 取消任务并关闭线程池</span>
<span style="color: rgba(0, 0, 0, 1)">    }
    System.out.println(text.toString());
}</span></pre>
</div>
<span class="cnblogs_code_collapse">View Code</span></div>
<p>&nbsp;</p>
</div>
<div class="lake-content">
<p>&nbsp;</p>
</div>
</div>
</div>
<p>&nbsp;</p><br><br>
来源:https://www.cnblogs.com/zhouyun-yx/p/19402607
頁: [1]
查看完整版本: 语音识别服务funasr搭建