HZRecorder+科大讯飞语音转换文字-程序员宅基地

技术标签: web app  java  html5  语音转文字  

最近项目在做一个微信公众号,但是用的jsp+js+java,没法调用wx自带的接口,所以就找了科大讯飞的接口调用,遇到了不少波折,这里记录一下过程

注册科大讯飞账户,得到认证信息

科大讯飞语音转换文字
注册页面
控制台

下载demo

demo、webapi文档
在这里插入图片描述
1、下载好demo文档、音频样例之后,用IDEA或者Eclipse启动就能成功
2、html的话原先在百度找了个浏览器支持Media​Recorder API的技术,最后发现用这个技术得到的音频文件科大讯飞的webapi不能识别,好难受~~~
3、最后好不容易找到了HZRecorder.js
4、直接把这俩文件拷贝出去放在一起就能实现浏览器录音

html

<!DOCTYPE html>
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
    <meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
    <title></title>
</head>
<body>
    <div>
        <audio controls autoplay></audio>
        <input onclick="startRecording()" type="button" value="录音" />
        <input onclick="stopRecording()" type="button" value="停止" />
        <input onclick="playRecording()" type="button" value="播放" />
        <input onclick="uploadAudio()" type="button" value="提交" />
    </div>

    <script type="text/javascript" src="HZRecorder.js"></script>


    <script>
        var recorder;
        var audio = document.querySelector('audio');
        function startRecording() {
     
            HZRecorder.get(function (rec) {
     
                recorder = rec;
                recorder.start();
            });
        }
        function stopRecording() {
     
            recorder.stop();
        }
        function playRecording() {
     
            recorder.play(audio);
        }
        function uploadAudio() {
     
            recorder.upload("Handler1.ashx", function (state, e) {
     
                switch (state) {
     
                    case 'uploading':
                        var percentComplete = Math.round(e.loaded * 100 / e.total) + '%';
                        break;
                    case 'ok':
                        alert("上传成功");
                        break;
                    case 'error':
                        alert("上传失败");
                        break;
                    case 'cancel':
                        alert("上传被取消");
                        break;
                }
            });
        }
		
    </script>
</body>
</html>

js

(function (window) {
    
    window.URL = window.URL || window.webkitURL;
    navigator.getUserMedia = navigator.getUserMedia || navigator.webkitGetUserMedia || navigator.mozGetUserMedia || navigator.msGetUserMedia;

    var HZRecorder = function (stream, config) {
    
        config = config || {
    };
        config.sampleBits = config.sampleBits || 16;      //采样数位 8, 16
        config.sampleRate = config.sampleRate || (16000);   // 采样率(1/6 44100)
        var context = new (window.webkitAudioContext || window.AudioContext)();
        var audioInput = context.createMediaStreamSource(stream);
        var createScript = context.createScriptProcessor || context.createJavaScriptNode;
        var recorder = createScript.apply(context, [4096, 1, 1]);
        var audioData = {
    
            size: 0          // 录音文件长度
            , buffer: []     // 录音缓存
            , inputSampleRate: context.sampleRate    // 输入采样率
            , inputSampleBits: 16       // 输入采样数位 
            , outputSampleRate: config.sampleRate    // 输出采样率
            , oututSampleBits: config.sampleBits       // 输出采样数位 
            , input: function (data) {
    
                this.buffer.push(new Float32Array(data));
                this.size += data.length;
            }
            , compress: function () {
     
                //合并
                var data = new Float32Array(this.size);
                var offset = 0;
                for (var i = 0; i < this.buffer.length; i++) {
    
                    data.set(this.buffer[i], offset);
                    offset += this.buffer[i].length;
                }
                //压缩
                var compression = parseInt(this.inputSampleRate / this.outputSampleRate);
                var length = data.length / compression;
                var result = new Float32Array(length);
                var index = 0, j = 0;
                while (index < length) {
    
                    result[index] = data[j];
                    j += compression;
                    index++;
                }
                return result;
            }
            , encodeWAV: function () {
    
                var sampleRate = Math.min(this.inputSampleRate, this.outputSampleRate);
                var sampleBits = Math.min(this.inputSampleBits, this.oututSampleBits);
                var bytes = this.compress();
                var dataLength = bytes.length * (sampleBits / 8);
                var buffer = new ArrayBuffer(44 + dataLength);
                var data = new DataView(buffer);

                var channelCount = 1; // 单声道
                var offset = 0;

                var writeString = function (str) {
    
                    for (var i = 0; i < str.length; i++) {
    
                        data.setUint8(offset + i, str.charCodeAt(i));
                    }
                }
                
                // 资源交换文件标识符 
                writeString('RIFF'); offset += 4;
                // 下个地址开始到文件尾总字节数,即文件大小-8 
                data.setUint32(offset, 36 + dataLength, true); offset += 4;
                // WAV文件标志
                writeString('WAVE'); offset += 4;
                // 波形格式标志 
                writeString('fmt '); offset += 4;
                // 过滤字节,一般为 0x10 = 16 
                data.setUint32(offset, 16, true); offset += 4;
                // 格式类别 (PCM形式采样数据) 
                data.setUint16(offset, 1, true); offset += 2;
                // 通道数 
                data.setUint16(offset, channelCount, true); offset += 2;
                // 采样率,每秒样本数,表示每个通道的播放速度 
                data.setUint32(offset, sampleRate, true); offset += 4;
                // 波形数据传输率 (每秒平均字节数) 单声道×每秒数据位数×每样本数据位/8 
                data.setUint32(offset, channelCount * sampleRate * (sampleBits / 8), true); offset += 4;
                // 快数据调整数 采样一次占用字节数 单声道×每样本的数据位数/8 
                data.setUint16(offset, channelCount * (sampleBits / 8), true); offset += 2;
                // 每样本数据位数 
                data.setUint16(offset, sampleBits, true); offset += 2;
                // 数据标识符 
                writeString('data'); offset += 4;
                // 采样数据总数,即数据总大小-44 
                data.setUint32(offset, dataLength, true); offset += 4;
                // 写入采样数据 
                if (sampleBits === 8) {
    
                    for (var i = 0; i < bytes.length; i++, offset++) {
    
                        var s = Math.max(-1, Math.min(1, bytes[i]));
                        var val = s < 0 ? s * 0x8000 : s * 0x7FFF;
                        val = parseInt(255 / (65535 / (val + 32768)));
                        data.setInt8(offset, val, true);
                    }
                } else {
    
                    for (var i = 0; i < bytes.length; i++, offset += 2) {
    
                        var s = Math.max(-1, Math.min(1, bytes[i]));
                        data.setInt16(offset, s < 0 ? s * 0x8000 : s * 0x7FFF, true);
                    }
                }

                return new Blob([data], {
     type: 'audio/wav' });
            }
        };

        // 开始录音
        this.start = function () {
    
            audioInput.connect(recorder);
            recorder.connect(context.destination);
        }

        // 暂停
        this.stop = function () {
    
            recorder.disconnect();
        }

        // 获取音频文件
        this.getBlob = function () {
    
            this.stop();
            return audioData.encodeWAV();
        }

        // 播放
        this.play = function (audio) {
    
            audio.src = window.URL.createObjectURL(this.getBlob());
        }

        // 上传
        this.upload = function (url, callback) {
    
            var fd = new FormData();
            fd.append("audioData", this.getBlob());
            var xhr = new XMLHttpRequest();
            if (callback) {
    
                xhr.upload.addEventListener("progress", function (e) {
    
                    callback('uploading', e);
                }, false);
                xhr.addEventListener("load", function (e) {
    
                    callback('ok', e);
                }, false);
                xhr.addEventListener("error", function (e) {
    
                    callback('error', e);
                }, false);
                xhr.addEventListener("abort", function (e) {
    
                    callback('cancel', e);
                }, false);
            }
            xhr.open("POST", url);
            xhr.send(fd);
        }

        // 音频采集
        recorder.onaudioprocess = function (e) {
    
            audioData.input(e.inputBuffer.getChannelData(0));
        }

    };
    // 抛出异常
    HZRecorder.throwError = function (message) {
    
        alert(message);
        throw new function () {
     this.toString = function () {
     return message; } }
    }
    // 是否支持录音
    HZRecorder.canRecording = (navigator.getUserMedia != null);
    // 获取录音机
    HZRecorder.get = function (callback, config) {
    
        if (callback) {
    
            if (navigator.getUserMedia) {
    
                navigator.getUserMedia(
                    {
     audio: true } // 启用音频
                    , function (stream) {
    
                        var rec = new HZRecorder(stream, config);
                        callback(rec);
                    }
                    , function (error) {
    
                        switch (error.code || error.name) {
    
                            case 'PERMISSION_DENIED':
                            case 'PermissionDeniedError':
                                console.log('用户拒绝提供信息。');
                                break;
                            case 'NOT_SUPPORTED_ERROR':
                            case 'NotSupportedError':
                                console.log('浏览器不支持硬件设备。');
                                break;
                            case 'MANDATORY_UNSATISFIED_ERROR':
                            case 'MandatoryUnsatisfiedError':
                                console.log('无法发现指定的硬件设备。');
                                break;
                            default:
                                console.log('无法打开麦克风。异常信息:' + (error.code || error.name));
                                break;
                        }
                    });
            } else {
    
                console.log('当前浏览器不支持录音功能。');
                return;
            }
        }
    }
    window.HZRecorder = HZRecorder;
})(window);

5、上传至服务端
上传

6、var xhr = new XMLHttpRequest(); 回显

var jsondata = JSON.parse(xhr.responseText);

7、服务端接收上传文件

@RequestMapping(value = "/getAnswerInfo")
    @ResponseBody
    public Object getAnswerInfo(HttpServletRequest request, HttpServletResponse response) throws Exception {
    
    	//接收参数
        Map<String,Object> map = new HashMap<>();
        String openo = request.getParameter("openo");
        String personid = request.getParameter("personid");
        String recid = get32UUID();
        String flag = request.getParameter("flag");
        File file = null;
        String keywords = "";
        //判断
        if (!StringUtil.isEmpty(flag) && "1".equals(flag)) {
    
            keywords = request.getParameter("keywords");
            map = lybZnwdService.selectByExampleByLybZsk(keywords,openo,recid,personid,getUser());
        } else if (!StringUtil.isEmpty(flag) && "2".equals(flag)){
    
        //这一段是接收音频文件,然后转成File文件
            MultipartHttpServletRequest multiRequest = (MultipartHttpServletRequest) request;
            Iterator<String> iter = multiRequest.getFileNames();
            while (iter.hasNext()) {
    
                List<MultipartFile> files = multiRequest.getFiles(iter.next());
                if (files != null && files.size() > 0) {
    
                    for (MultipartFile multipartFile : files) {
    
                        file = WebIATWS.transferToFile(multipartFile);
                        keywords = WebIATWS.sendStart(file);
                        if (!StringUtil.isEmpty(keywords)) {
    
                            map = lybZnwdService.selectByExampleByLybZsk(keywords.replace("。",""),openo,recid,personid,getUser());
                        } 
                        System.out.println("result=="+keywords);
                    }
                }
            }
        }
        return map;
    }

8、音频文件转成文字

package com.yawei.es.wechat.Utils;

import com.google.gson.Gson;
import com.google.gson.JsonObject;
import okhttp3.*;
import org.springframework.web.multipart.MultipartFile;

import javax.crypto.Mac;
import javax.crypto.spec.SecretKeySpec;
import java.io.*;
import java.net.URL;
import java.nio.charset.Charset;
import java.text.SimpleDateFormat;
import java.util.*;

/**
 * 语音听写流式 WebAPI 接口调用示例 接口文档(必看):https://doc.xfyun.cn/rest_api/语音听写(流式版).html
 * webapi 听写服务参考帖子(必看):http://bbs.xfyun.cn/forum.php?mod=viewthread&tid=38947&extra=
 * 语音听写流式WebAPI 服务,热词使用方式:登陆开放平台https://www.xfyun.cn/后,找到控制台--我的应用---语音听写---个性化热词,上传热词
 * 注意:热词只能在识别的时候会增加热词的识别权重,需要注意的是增加相应词条的识别率,但并不是绝对的,具体效果以您测试为准。
 * 错误码链接:https://www.xfyun.cn/document/error-code (code返回错误码时必看)
 * 语音听写流式WebAPI 服务,方言或小语种试用方法:登陆开放平台https://www.xfyun.cn/后,在控制台--语音听写(流式)--方言/语种处添加
 * 添加后会显示该方言/语种的参数值
 * @author iflytek
 */

public class WebIATWS extends WebSocketListener {
    
    private static final String hostUrl = "https://iat-api.xfyun.cn/v2/iat"; //中英文,http url 不支持解析 ws/wss schema
    // private static final String hostUrl = "https://iat-niche-api.xfyun.cn/v2/iat";//小语种
    private static final String apiKey = "xxx"; //在控制台-我的应用-语音听写(流式版)获取
    private static final String apiSecret = "xxx"; //在控制台-我的应用-语音听写(流式版)获取
    private static final String appid = "xxx"; //在控制台-我的应用获取
//    private static final String file = "C:\\Users\\lihao\\Desktop\\luyin\\777.wav"; // 中文     resource\\iat\\16k_10.pcm
    private static File file = null;
    public static final int StatusFirstFrame = 0;
    public static final int StatusContinueFrame = 1;
    public static final int StatusLastFrame = 2;
    public static final Gson json = new Gson();
    Decoder decoder = new Decoder();
    // 开始时间
    private static Date dateBegin = new Date();
    // 结束时间
    private static Date dateEnd = new Date();
    private static final SimpleDateFormat sdf = new SimpleDateFormat("yyy-MM-dd HH:mm:ss.SSS");
    private static String result = "";
    /**
     * 连接
     * @param webSocket
     * @param response
     */
    @Override
    public void onOpen(WebSocket webSocket, Response response) {
    
        super.onOpen(webSocket, response);
        new Thread(()->{
    
            //连接成功,开始发送数据
            int frameSize = 1280; //每一帧音频的大小,建议每 40ms 发送 122B
            int intervel = 40;
            int status = 0;  // 音频的状态
            try (FileInputStream fs = new FileInputStream(file)) {
    
                byte[] buffer = new byte[frameSize];
                // 发送音频
                end:
                while (true) {
    
                    int len = fs.read(buffer);
                    if (len == -1) {
    
                        status = StatusLastFrame;  //文件读完,改变status 为 2
                    }
                    switch (status) {
    
                        case StatusFirstFrame:   // 第一帧音频status = 0
                            JsonObject frame = new JsonObject();
                            JsonObject business = new JsonObject();  //第一帧必须发送
                            JsonObject common = new JsonObject();  //第一帧必须发送
                            JsonObject data = new JsonObject();  //每一帧都要发送
                            // 填充common
                            common.addProperty("app_id", appid);
                            //填充business
                            business.addProperty("language", "zh_cn");
                            //business.addProperty("language", "en_us");//英文
                            //business.addProperty("language", "ja_jp");//日语,在控制台可添加试用或购买
                            //business.addProperty("language", "ko_kr");//韩语,在控制台可添加试用或购买
                            //business.addProperty("language", "ru-ru");//俄语,在控制台可添加试用或购买
                            business.addProperty("domain", "iat");
                            business.addProperty("accent", "mandarin");//中文方言请在控制台添加试用,添加后即展示相应参数值
                            //business.addProperty("nunum", 0);
                            //business.addProperty("ptt", 0);//标点符号
                            //business.addProperty("rlang", "zh-hk"); // zh-cn :简体中文(默认值)zh-hk :繁体香港(若未授权不生效,在控制台可免费开通)
                            //business.addProperty("vinfo", 1);
                            business.addProperty("dwa", "wpgs");//动态修正(若未授权不生效,在控制台可免费开通)
                            //business.addProperty("nbest", 5);// 句子多候选(若未授权不生效,在控制台可免费开通)
                            //business.addProperty("wbest", 3);// 词级多候选(若未授权不生效,在控制台可免费开通)
                            //填充data
                            data.addProperty("status", StatusFirstFrame);
                            data.addProperty("format", "audio/L16;rate=16000");
                            data.addProperty("encoding", "raw");
                            data.addProperty("audio", Base64.getEncoder().encodeToString(Arrays.copyOf(buffer, len)));
                            //填充frame
                            frame.add("common", common);
                            frame.add("business", business);
                            frame.add("data", data);
                            webSocket.send(frame.toString());
                            status = StatusContinueFrame;  // 发送完第一帧改变status 为 1
                            break;
                        case StatusContinueFrame:  //中间帧status = 1
                            JsonObject frame1 = new JsonObject();
                            JsonObject data1 = new JsonObject();
                            data1.addProperty("status", StatusContinueFrame);
                            data1.addProperty("format", "audio/L16;rate=16000");
                            data1.addProperty("encoding", "raw");
                            data1.addProperty("audio", Base64.getEncoder().encodeToString(Arrays.copyOf(buffer, len)));
                            frame1.add("data", data1);
                            webSocket.send(frame1.toString());
                            // System.out.println("send continue");
                            break;
                        case StatusLastFrame:    // 最后一帧音频status = 2 ,标志音频发送结束
                            JsonObject frame2 = new JsonObject();
                            JsonObject data2 = new JsonObject();
                            data2.addProperty("status", StatusLastFrame);
                            data2.addProperty("audio", "");
                            data2.addProperty("format", "audio/L16;rate=16000");
                            data2.addProperty("encoding", "raw");
                            frame2.add("data", data2);
                            webSocket.send(frame2.toString());
                            System.out.println("sendlast");
                            break end;
                    }
                    Thread.sleep(intervel); //模拟音频采样延时
                }
                System.out.println("all data is send");
            } catch (FileNotFoundException e) {
    
                e.printStackTrace();
            } catch (IOException e) {
    
                e.printStackTrace();
            } catch (InterruptedException e) {
    
                e.printStackTrace();
            }
        }).start();
    }

    /**
     * 结果
     * @param webSocket
     * @param text
     */
    @Override
    public void onMessage(WebSocket webSocket, String text) {
    
        super.onMessage(webSocket, text);
        //System.out.println(text);
        ResponseData resp = json.fromJson(text, ResponseData.class);
        if (resp != null) {
    
            if (resp.getCode() != 0) {
    
                System.out.println( "code=>" + resp.getCode() + " error=>" + resp.getMessage() + " sid=" + resp.getSid());
                System.out.println( "错误码查询链接:https://www.xfyun.cn/document/error-code");
                return;
            }
            if (resp.getData() != null) {
    
                if (resp.getData().getResult() != null) {
    
                    Text te = resp.getData().getResult().getText();
                    //System.out.println(te.toString());
                    try {
    
                        decoder.decode(te);
                        System.out.println("中间识别结果 ==》" + decoder.toString());
                    } catch (Exception e) {
    
                        e.printStackTrace();
                    }
                }
                if (resp.getData().getStatus() == 2) {
    
                    // todo  resp.data.status ==2 说明数据全部返回完毕,可以关闭连接,释放资源
                    System.out.println("session end ");
                    dateEnd = new Date();
                    System.out.println(sdf.format(dateBegin) + "开始");
                    System.out.println(sdf.format(dateEnd) + "结束");
                    System.out.println("耗时:" + (dateEnd.getTime() - dateBegin.getTime()) + "ms");
                    System.out.println("最终识别结果 ==》" + decoder.toString());
                    System.out.println("本次识别sid ==》" + resp.getSid());
                    result = decoder.toString();
                    System.out.println("resultweb--->"+result);
                    decoder.discard();
                    webSocket.close(1000, "");
                } else {
    
                    // todo 根据返回的数据处理
                }
            }
        }
    }

    /**
     * 异常
     * @param webSocket
     * @param t
     * @param response
     */
    @Override
    public void onFailure(WebSocket webSocket, Throwable t, Response response) {
    
        super.onFailure(webSocket, t, response);
        try {
    
            if (null != response) {
    
                int code = response.code();
                System.out.println("onFailure code:" + code);
                System.out.println("onFailure body:" + response.body().string());
                if (101 != code) {
    
                    System.out.println("connection failed");
                    System.exit(0);
                }
            }
        } catch (IOException e) {
    
            // TODO Auto-generated catch block
            e.printStackTrace();
        }
    }

    /**
     * main方法
     * @param args
     * @throws Exception
     */
    public static void main(String[] args) throws Exception {
    
        String authUrl = getAuthUrl(hostUrl, apiKey, apiSecret);
        OkHttpClient client = new OkHttpClient.Builder().build();
        String url = authUrl.toString().replace("http://", "ws://").replace("https://", "wss://");
        Request request = new Request.Builder().url(url).build();
        WebSocket webSocket = client.newWebSocket(request, new WebIATWS());
    }



    /**
     * 鉴权URL
     * @param hostUrl
     * @param apiKey
     * @param apiSecret
     * @return
     * @throws Exception
     */
    public static String getAuthUrl(String hostUrl, String apiKey, String apiSecret) throws Exception {
    
        URL url = new URL(hostUrl);
        SimpleDateFormat format = new SimpleDateFormat("EEE, dd MMM yyyy HH:mm:ss z", Locale.US);
        format.setTimeZone(TimeZone.getTimeZone("GMT"));
        String date = format.format(new Date());
        StringBuilder builder = new StringBuilder("host: ").append(url.getHost()).append("\n").//
                append("date: ").append(date).append("\n").//
                append("GET ").append(url.getPath()).append(" HTTP/1.1");
        System.out.println(builder);
        Charset charset = Charset.forName("UTF-8");
        Mac mac = Mac.getInstance("hmacsha256");
        SecretKeySpec spec = new SecretKeySpec(apiSecret.getBytes(charset), "hmacsha256");
        mac.init(spec);
        byte[] hexDigits = mac.doFinal(builder.toString().getBytes(charset));
        String sha = Base64.getEncoder().encodeToString(hexDigits);

        //System.out.println(sha);
        String authorization = String.format("api_key=\"%s\", algorithm=\"%s\", headers=\"%s\", signature=\"%s\"", apiKey, "hmac-sha256", "host date request-line", sha);
        System.out.println(authorization);
        HttpUrl httpUrl = HttpUrl.parse("https://" + url.getHost() + url.getPath()).newBuilder().//
                addQueryParameter("authorization", Base64.getEncoder().encodeToString(authorization.getBytes(charset))).//
                addQueryParameter("date", date).//
                addQueryParameter("host", url.getHost()).//
                build();
        return httpUrl.toString();
    }
    public static class ResponseData {
    
        private int code;
        private String message;
        private String sid;
        private Data data;
        public int getCode() {
    
            return code;
        }
        public String getMessage() {
    
            return this.message;
        }
        public String getSid() {
    
            return sid;
        }
        public Data getData() {
    
            return data;
        }
    }
    public static class Data {
    
        private int status;
        private Result result;
        public int getStatus() {
    
            return status;
        }
        public Result getResult() {
    
            return result;
        }
    }
    public static class Result {
    
        int bg;
        int ed;
        String pgs;
        int[] rg;
        int sn;
        Ws[] ws;
        boolean ls;
        JsonObject vad;
        public Text getText() {
    
            Text text = new Text();
            StringBuilder sb = new StringBuilder();
            for (Ws ws : this.ws) {
    
                sb.append(ws.cw[0].w);
            }
            text.sn = this.sn;
            text.text = sb.toString();
            text.sn = this.sn;
            text.rg = this.rg;
            text.pgs = this.pgs;
            text.bg = this.bg;
            text.ed = this.ed;
            text.ls = this.ls;
            text.vad = this.vad==null ? null : this.vad;
            return text;
        }
    }
    public static class Ws {
    
        Cw[] cw;
        int bg;
        int ed;
    }
    public static class Cw {
    
        int sc;
        String w;
    }
    public static class Text {
    
        int sn;
        int bg;
        int ed;
        String text;
        String pgs;
        int[] rg;
        boolean deleted;
        boolean ls;
        JsonObject vad;
        @Override
        public String toString() {
    
            return "Text{" +
                    "bg=" + bg +
                    ", ed=" + ed +
                    ", ls=" + ls +
                    ", sn=" + sn +
                    ", text='" + text + '\'' +
                    ", pgs=" + pgs +
                    ", rg=" + Arrays.toString(rg) +
                    ", deleted=" + deleted +
                    ", vad=" + (vad==null ? "null" : vad.getAsJsonArray("ws").toString()) +
                    '}';
        }
    }
    //解析返回数据,仅供参考
    public static class Decoder {
    
        private Text[] texts;
        private int defc = 10;
        public Decoder() {
    
            this.texts = new Text[this.defc];
        }
        public synchronized void decode(Text text) {
    
            if (text.sn >= this.defc) {
    
                this.resize();
            }
            if ("rpl".equals(text.pgs)) {
    
                for (int i = text.rg[0]; i <= text.rg[1]; i++) {
    
                    this.texts[i].deleted = true;
                }
            }
            this.texts[text.sn] = text;
        }
        public String toString() {
    
            StringBuilder sb = new StringBuilder();
            for (Text t : this.texts) {
    
                if (t != null && !t.deleted) {
    
                    sb.append(t.text);
                }
            }
            return sb.toString();
        }
        public void resize() {
    
            int oc = this.defc;
            this.defc <<= 1;
            Text[] old = this.texts;
            this.texts = new Text[this.defc];
            for (int i = 0; i < oc; i++) {
    
                this.texts[i] = old[i];
            }
        }
        public void discard(){
    
            for(int i=0;i<this.texts.length;i++){
    
                this.texts[i]= null;
            }
        }
    }

    public static String sendStart (File file_keywords) throws Exception {
    
        file = file_keywords;
        // 构建鉴权url
        String authUrl = getAuthUrl(hostUrl, apiKey, apiSecret);
        OkHttpClient client = new OkHttpClient.Builder().build();
        //将url中的 schema http://和https://分别替换为ws:// 和 wss://
        String url = authUrl.toString().replace("http://", "ws://").replace("https://", "wss://");
        Request request = new Request.Builder().url(url).build();
        // System.out.println(client.newCall(request).execute());
        WebSocket webSocket = client.newWebSocket(request, new WebIATWS());
        Thread.sleep(5000);
        return result;

    }

    /**
     * MultipartFile  转  File
     * @param multipartFile
     * @return
     */
    public static File transferToFile(MultipartFile multipartFile) {
    
        //        选择用缓冲区来实现这个转换即使用java 创建的临时文件 使用 MultipartFile.transferto()方法 。
        File file = null;
        try {
    
            String originalFilename = multipartFile.getOriginalFilename();
            if ("blob".equals(originalFilename)) {
    
                file = File.createTempFile(UUID.randomUUID().toString(), ".wav");
            }
            multipartFile.transferTo(file);
            file.deleteOnExit();
        } catch (IOException e) {
    
            e.printStackTrace();
        }
        return file;
    }

}

好啦,到此就结束啦,有疑问再沟通

版权声明:本文为博主原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。
本文链接:https://blog.csdn.net/weixin_40745445/article/details/108468013

智能推荐

Linux用户管理详解_linux登录qq是什么意思-程序员宅基地

文章浏览阅读448次。Linux用户管理用户基本概念什么是用户用户指的是能够正常登录Linux或Windows系统,比如:登录QQ的用户、登入王者荣耀的用户、等等[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-nz1edsjq-1626145230283)(C:\Users\李开开\AppData\Roaming\Typora\typora-user-images\image-20210712171546940.png)]为什么需要用户系统上的每一个进程(运行的程序),都_linux登录qq是什么意思

Unity中协程里Animator获取状态一些笔记_getanimatortransitioninfo-程序员宅基地

文章浏览阅读4.5k次,点赞4次,收藏7次。最近用Animator获取状态各种获取错误,所以记一下笔记Animator中可以获取三种不同的状态:GetCurrentAnimatorStateInfo 获取正确的状态机状态GetNextAnimatorStateInfo 获取下一个状态机的状态GetAnimatorTransitionInfo 获取状态机的过渡状态动画同步是在帧最前,而协程是在帧的最后调用。所以切换状态后在协程获取状..._getanimatortransitioninfo

LATEX 中参考文献顺序_spphys.bst-程序员宅基地

文章浏览阅读924次。\bibliography{report} % bibliography data in report.bib\bibliographystyle{unsrt} % makes bibtex use spphys.bstunsrt 表示按照引用的先后顺序进行排序_spphys.bst

Linux下部署maven-web项目,包括JDK安装、TOMCAT安装、MYSQL安装详细解释-程序员宅基地

文章浏览阅读335次。为什么80%的码农都做不了架构师?>>> ..._linux系统搭建maven+tomcat+mysql

effective stl 第18条: 避免使用vector<bool>-程序员宅基地

文章浏览阅读354次。vector不是容器,并且它不存储bool,因为他是按照位来存储的,即一个bool只占一个二进制位。假设有vector v;则&v[0]会引起编译错误。如果不使用&v[0]可以使用vector,否则,可以用deque 和bitset来替代_避免使用vector

Bug的严重程度(缺陷程度)有哪几种。。。。_bug严重程度-程序员宅基地

文章浏览阅读6.8k次,点赞2次,收藏20次。Bug程度分为四种,分别为:致命S0:致命缺陷是指会造成安全问题的各类缺陷。在测试中很少出现,一旦出现立即中止版本测试。系统崩溃,数据丢失,数据毁坏,无法运行等Bug。严重S1:是指可以引起易于纠正的异常情况,可能引起易于修复的故障或对产品外观造成难以接受的缺陷。不影响其他功能的情况下可以继续版本测试。功能和性能不能实现。 次要功能全部丧失。 功能遗漏等等。 一般S2:一般缺陷是指不影响产品的..._bug严重程度

随便推点

《iOS 9 开发指南》——第1章,第1.3节工欲善其事,必先利其器——搭建开发环境...-程序员宅基地

文章浏览阅读202次。本节书摘来自异步社区《iOS 9 开发指南》一书中的第1章,第1.3节工欲善其事,必先利其器——搭建开发环境,作者 管蕾,更多章节内容可以访问云栖社区“异步社区”公众号查看1.3 工欲善其事,必先利其器——搭建开发环境iOS 9 开发指南图片 2 知识点讲解:光盘:视频知识点第1章搭建开发环境.mp4学习iOS 9开发也离不开好的开发工具的帮助,如果使..._(1)下载完成后单击打开下载的“.dmg”格式文件,然后双击xcode文件开始安装。

iView 3.3.2 发布,基于 Vue.js 的企业级 UI 组件库-程序员宅基地

文章浏览阅读115次。开发四年只会写业务代码,分布式高并发都不会还做程序员? iView 3.3.2 发布了,iView 是一套基于 Vue..._iview 3.2.2

详解not in与not exists的区别与用法(not in的性能并不差!)-程序员宅基地

文章浏览阅读93次。2019独角兽企业重金招聘Python工程师标准>>> ..._predicate not in查询

SpringBoot整合Spring Data JPA、MySQL、Druid并使用Mockito实现单元测试_spring jpa mock-程序员宅基地

文章浏览阅读4.7k次,点赞3次,收藏7次。SpringBoot整合Spring Data JPA、MySQL、Druid并使用Mockito实现单元测试_spring jpa mock

java 解析excel金额_java解析Excel(xls、xlsx两种格式)-程序员宅基地

文章浏览阅读441次。package poi;import java.io.FileInputStream;import java.io.FileNotFoundException;import java.io.IOException;import java.io.InputStream;import java.util.ArrayList;import java.util.LinkedHashMap;import j..._java getcellformatvalue

50个漂亮免费的 WordPress 主题(下)_wordpressbo'ke 免费-程序员宅基地

文章浏览阅读170次。50个漂亮免费的 WordPress 主题(上)Minimatica( Demo | Download )Placeholder( Demo | Download )Navly( Demo | Download )Cobera( Demo | Download )The Blog( Demo | Download )Gabi..._wordpressbo'ke 免费

推荐文章

热门文章

相关标签