WebSocket简介,利用WebSocket发送音频数据

目录

一、简介:

二、WebSocket的特点:

三、WebSocket基本流程:

四、 WebSocket基本使用

1、webScoket实例对象常用属性和方法的介绍 

2、代码解析:

2、1 : connectWs() : 进行webSocket连接,并获取服务器返回的结果( onMessage()方法中设置一个全局变量,在此方法中不断去检测这个全局变量是否有值,有值则返回,没值则继续等待 )

2、2 : onOpen():websocket连接成功后的回调方法

2、3 : sendAudio() : 发送音频数据

2、4 : sendEof() : 发送结束表示给ws服务器

2、5 : onClose() : 连接关闭时的回调方法

2、6 : onError(): 异常时的回调方法

3、整体代码


一、简介:

WebSocket是一种在Web浏览器和服务器之间进行全双工通信的协议。它允许服务器主动向客户端推送数据,而不需要客户端发起请求。相比传统的HTTP请求-响应模式,WebSocket提供了更低的延迟和更高的实时性。

WebSocket协议基于TCP协议,通过在HTTP握手阶段升级到WebSocket连接来实现。在握手完成后,客户端和服务器之间的连接将保持打开状态,双方可以随时发送消息。

二、WebSocket的特点:

  1. 实时性:WebSocket提供了低延迟的双向通信,使得服务器可以实时向客户端推送数据。
  2. 高效性:WebSocket使用二进制帧传输数据,相比文本协议如HTTP,可以减少数据传输的大小和带宽消耗。
  3. 跨域支持:WebSocket支持跨域通信,可以在不同域名下的客户端和服务器之间建立连接。
  4. 可扩展性:WebSocket协议可以通过扩展来支持更多的功能和协议。

三、WebSocket基本流程:

  1. 客户端发起WebSocket连接请求。
  2. 服务器接受连接请求,并进行握手。
  3. 握手成功后,客户端和服务器之间建立起WebSocket连接。
  4. 双方可以通过发送消息进行实时通信。
  5. 连接关闭时,客户端和服务器都可以发送关闭消息来关闭连接。

四、 WebSocket基本使用

1、webScoket实例对象常用属性和方法的介绍 

属性说明
url当前连接的websocket接口地址
readyState当前连接的状态: 0:正在链接中 1:已经链接并且可以通讯 2:连接正在关闭 3;连接已关闭或者没有链接成功
onopen连接成功的回调函数
onerror连接失败的回调函数
onmessage从服务端接受到信息的回调函数
onclose连接关闭的回调函数
binaryType使用二进制的数据类型连接
protocol服务器选择的下属协议
bufferedAmount未发送至服务器的二进制字节数
close()关闭当前连接
send(data)发送消息到服务器

2、代码解析:

2、1 : connectWs() : 进行webSocket连接,并获取服务器返回的结果( onMessage()方法中设置一个全局变量,在此方法中不断去检测这个全局变量是否有值,有值则返回,没值则继续等待 )
public static String connectWs(String host, String port, String url) throws URISyntaxException, InterruptedException {
        try {
            if (StringUtils.isBlank(host) || StringUtils.isBlank(port) || StringUtils.isBlank(url)) {
                logger.info("传入字段存在空值,当前host为【" + host + "】,port为【" + port + "】,url为【" + url + "】");
                return "";
            }
            String str = "--host " + host + " --port " + port + " --mode offline --audio_in " + url;
            String[] args = str.split(" ");
            // 设置命令行的相关参数
            ArgumentParser parser = ArgumentParsers.newArgumentParser("ws client").defaultHelp(true);
            // 设置端口号
            parser
                    .addArgument("--port")
                    .help("Port on which to listen.")
                    .setDefault("8889")
                    .type(String.class)
                    .required(false);
            // 设置服务器IP
            parser
                    .addArgument("--host")
                    .help("the IP address of server.")
                    .setDefault("127.0.0.1")
                    .type(String.class)
                    .required(false);
            // 设置音频数据地址
            parser
                    .addArgument("--audio_in")
                    .help("wav path for decoding.")
                    .setDefault("asr_example.wav")
                    .type(String.class)
                    .required(false);
            // 设置线程数
            parser
                    .addArgument("--num_threads")
                    .help("num of threads for test.")
                    .setDefault(1)
                    .type(Integer.class)
                    .required(false);
            // 设置分块大小
            parser
                    .addArgument("--chunk_size")
                    .help("chunk size for asr.")
                    .setDefault("5, 10, 5")
                    .type(String.class)
                    .required(false);
            // 设置分块间隔
            parser
                    .addArgument("--chunk_interval")
                    .help("chunk for asr.")
                    .setDefault(10)
                    .type(Integer.class)
                    .required(false);

            /** 音频识别系统(ASR)的状态参数
             * online:在线模式,音频数据实时传输到服务器进行处理,然后服务器实时返回识别结果
             * offline:离线模式,音频数据先存储在本地,然后一次性传输到服务器进行处理,服务器处理完成后一次性返回识别结果
             * hybrid:部分处理可以在本地进行,而另一部分可以再服务器端进行,以实现更好的性能和用户体验
             */
            parser
                    .addArgument("--mode")
                    .help("mode for asr.")
                    .setDefault("offline")
                    .type(String.class)
                    .required(false);
            // 热词
            parser
                    .addArgument("--hotwords")
                    .help("hotwords, splited by space, hello 30 nihao 40")
                    .setDefault("")
                    .type(String.class)
                    .required(false);
            // ws的ip
            String srvIp = "";
            // ws的端口
            String srvPort = "";
            // 音频路径
            String wavPath = "";
            // 线程数
            int numThreads = 1;
            // 分块大小
            String chunk_size = "";
            // 分块间隔
            int chunk_interval = 10;
            // 状态:默认为离线状态
            String strmode = "offline";
            // 热词
            String hot = "";
            try {
                Namespace ns = parser.parseArgs(args);
                srvIp = ns.get("host");
                srvPort = ns.get("port");
                wavPath = ns.get("audio_in");
                numThreads = ns.get("num_threads");
                chunk_size = ns.get("chunk_size");
                chunk_interval = ns.get("chunk_interval");
                strmode = ns.get("mode");
                hot = ns.get("hotwords");
                System.out.println(srvPort);
    
            } catch (ArgumentParserException ex) {
                ex.getParser().handleError(ex);
                return "";
            }

            WsSendDataUtils.strChunkSize = chunk_size;
            WsSendDataUtils.chunkInterval = chunk_interval;
            WsSendDataUtils.wavPath = wavPath;
            WsSendDataUtils.mode = strmode;
            WsSendDataUtils.hotwords = hot;

            System.out.println(
                    "serIp="
                            + srvIp
                            + ",srvPort="
                            + srvPort
                            + ",wavPath="
                            + wavPath
                            + ",strChunkSize"
                            + strChunkSize);
            // 设置音频采样率为16000Hz
            int RATE = 16000;
            //
            String[] chunkList = strChunkSize.split(",");
            // 音频分块大小
            int int_chunk_size = 60 * Integer.valueOf(chunkList[1].trim()) / chunkInterval;
            // 计算每个音频分块的大小,以采样点为单位
            int CHUNK = Integer.valueOf(RATE / 1000 * int_chunk_size);
            // 计算音频分块的步长,以采样点为单位
            int stride =
                    Integer.valueOf(
                            60 * Integer.valueOf(chunkList[1].trim()) / chunkInterval / 1000 * 16000 * 2);
            System.out.println("chunk_size:" + String.valueOf(int_chunk_size));
            System.out.println("CHUNK:" + CHUNK);
            System.out.println("stride:" + String.valueOf(stride));
            // 设置WebSocket客户端发送数据的分块大小
            WsSendDataUtils.sendChunkSize = CHUNK * 2;
            // ws地址
            String wsAddress = "ws://" + srvIp + ":" + srvPort;

            WsSendDataUtils c = new WsSendDataUtils(new URI(wsAddress));
            // 连接WebSocket
            c.connect();
            // 等待ws返回结果
            String wsData = WsSendDataUtils.messageMap.get("receivedWsData");
            while (StringUtils.isEmpty(wsData)) {
                Thread.sleep(3000);
                wsData = WsSendDataUtils.messageMap.get("receivedWsData");
                logger.info("正在获取wsData");
            }
            if (StringUtils.isNotBlank(wsData)) {
                WsSendDataUtils.messageMap.remove("receivedWsData");
                return wsData;
            }
            System.out.println("wsAddress:" + wsAddress);
            return "";
        } catch (Exception e) {
            e.printStackTrace();
            return "";
        }
    }
2、2 : onOpen():websocket连接成功后的回调方法
    /**
     * 连接成功后的回调方法
     *
     * @param serverHandshake
     */
    @Override
    public void onOpen(ServerHandshake serverHandshake) {
        // 连接成功后,发送音频数据
        sendAudio();
    }
2、3 : sendAudio() : 发送音频数据
   /**
     * 发送音频数据
     */
    private void sendAudio() {
        String fileName = WsSendDataUtils.wavPath;
        String suffix = fileName.split("\\.")[fileName.split("\\.").length - 1];
        sendJson(mode, strChunkSize, chunkInterval, wavName, true, suffix);
        File file = new File(WsSendDataUtils.wavPath);

        int chunkSize = sendChunkSize;
        byte[] bytes = new byte[chunkSize];

        int readSize = 0;
        try (FileInputStream fis = new FileInputStream(file)) {
            if (WsSendDataUtils.wavPath.endsWith(".wav")) {
                fis.read(bytes, 0, 44); //skip first 44 wav header
            }
            readSize = fis.read(bytes, 0, chunkSize);
            while (readSize > 0) {
                // send when it is chunk size
                if (readSize == chunkSize) {
                    send(bytes); // send buf to server

                } else {
                    // send when at last or not is chunk size
                    byte[] tmpBytes = new byte[readSize];
                    for (int i = 0; i < readSize; i++) {
                        tmpBytes[i] = bytes[i];
                    }
                    send(tmpBytes);
                }
                // if not in offline mode, we simulate online stream by sleep
                if (!mode.equals("offline")) {
                    Thread.sleep(Integer.valueOf(chunkSize / 32));
                }

                readSize = fis.read(bytes, 0, chunkSize);
            }

            if (!mode.equals("offline")) {
                // if not offline, we send eof and wait for 3 seconds to close
                Thread.sleep(2000);
                sendEof();
                Thread.sleep(3000);
                close();
            } else {
                // if offline, just send eof
                sendEof();
            }

        } catch (Exception e) {
            e.printStackTrace();
        }
    }
 public void sendJson(String mode, String strChunkSize, int chunkInterval, String wavName, boolean isSpeaking, String suffix) {
        try {

            JSONObject obj = new JSONObject();
            obj.put("mode", mode);
            JSONArray array = new JSONArray();
            String[] chunkList = strChunkSize.split(",");
            for (int i = 0; i < chunkList.length; i++) {
                array.add(Integer.valueOf(chunkList[i].trim()));
            }

            obj.put("chunk_size", array);
            obj.put("chunk_interval", Integer.valueOf(chunkInterval));
            obj.put("wav_name", wavName);

            if (WsSendDataUtils.hotwords.trim().length() > 0) {
                String regex = "\\d+";
                JSONObject jsonitems = new JSONObject();
                String[] items = WsSendDataUtils.hotwords.trim().split(" ");
                Pattern pattern = Pattern.compile(regex);
                String tmpWords = "";
                for (int i = 0; i < items.length; i++) {

                    Matcher matcher = pattern.matcher(items[i]);

                    if (matcher.matches()) {

                        jsonitems.put(tmpWords.trim(), items[i].trim());
                        tmpWords = "";
                        continue;
                    }
                    tmpWords = tmpWords + items[i] + " ";

                }

                obj.put("hotwords", jsonitems.toString());
            }

            if (suffix.equals("wav")) {
                suffix = "pcm";
            }
            obj.put("wav_format", suffix);
            if (isSpeaking) {
                obj.put("is_speaking", Boolean.valueOf(true));
            } else {
                obj.put("is_speaking", Boolean.valueOf(false));
            }
            logger.info("sendJson: " + obj);
            // return;

            send(obj.toString());

            return;
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
2、4 : sendEof() : 发送结束表示给ws服务器
    /**
     * 发送结束表示给ws服务器
     */
    public void sendEof() {
        try {
            JSONObject obj = new JSONObject();

            obj.put("is_speaking", Boolean.valueOf(false));

            logger.info("sendEof: " + obj);
            // return;

            send(obj.toString());
            iseof = true;
            return;
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
2、5 : onClose() : 连接关闭时的回调方法
    /**
     * @param statusCode:连接关闭的状态码
     * @param reason:连接关闭的附加信息,例如异常关闭时,这个参数可能包含异常的详细描述信息
     * @param flag:连接关闭时是否为远程主机(服务器)发起关闭,如果为true,则表示由远程主机发起的关闭, 如果为false,则表示由本地客户端发起的关闭。
     */
    @Override
    public void onClose(int statusCode, String reason, boolean flag) {
        logger.info("WebSocket返回的状态码为【" + statusCode + "】,连接关闭的附加信息为:"
                + reason + ",是否为远程主机(服务器)发起的关闭:" + flag);
    }
2、6 : onError(): 异常时的回调方法
    @Override
    public void onError(Exception e) {
        e.printStackTrace();
        logger.info("WebSocket发生异常,异常原因为:" + e);
    }

3、整体代码

package com.xinlian.common.utils;

import com.alibaba.excel.util.StringUtils;
import net.sourceforge.argparse4j.ArgumentParsers;
import net.sourceforge.argparse4j.inf.ArgumentParser;
import net.sourceforge.argparse4j.inf.ArgumentParserException;
import net.sourceforge.argparse4j.inf.Namespace;
import org.java_websocket.client.WebSocketClient;
import org.java_websocket.drafts.Draft;
import org.java_websocket.handshake.ServerHandshake;
import org.json.simple.JSONArray;
import org.json.simple.JSONObject;
import org.json.simple.parser.JSONParser;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.io.File;
import java.io.FileInputStream;
import java.net.URI;
import java.net.URISyntaxException;
import java.util.HashMap;
import java.util.Map;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

/**
 * @Author:yaojunjie
 * @Package:com.common.utils
 * @Date:2024/4/27 12:57
 */
public class WsSendDataUtils extends WebSocketClient {

    private boolean iseof = false;
    public static String wavPath;
    static String mode = "online";
    static String strChunkSize = "5,10,5";
    static int chunkInterval = 10;
    static int sendChunkSize = 1920;
    static String hotwords = "";
    String wavName = "javatest";
    static HashMap<String, String> messageMap = new HashMap<>();

    private static final Logger logger = LoggerFactory.getLogger(WsSendDataUtils.class);

    public WsSendDataUtils(URI serverURI) {
        super(serverURI);
    }

    public WsSendDataUtils(URI serverUri, Draft draft) {
        super(serverUri, draft);
    }

    public WsSendDataUtils(URI serverUri, Draft draft, Map<String, String> headers, int connecttimeout) {
        super(serverUri, draft, headers, connecttimeout);
    }

    /**
     * 连接成功后的回调方法
     *
     * @param serverHandshake
     */
    @Override
    public void onOpen(ServerHandshake serverHandshake) {
        // 连接成功后,发送音频数据
        sendAudio();
    }

    /**
     * ws返回数据的回调方法
     * @param message:ws返回的信息
     */
    @Override
    public void onMessage(String message) {
        JSONObject jsonObject = new JSONObject();
        JSONParser jsonParser = new JSONParser();
        logger.info("ws服务器返回的数据为: " + message);
        try {
            jsonObject = (JSONObject) jsonParser.parse(message);
            Object text = jsonObject.get("text");
            messageMap.put("receivedWsData", "" + text);
        } catch (org.json.simple.parser.ParseException e) {
            e.printStackTrace();
        }
        if (iseof && mode.equals("offline") && !jsonObject.containsKey("is_final")) {
            close();
        }

        if (iseof && mode.equals("offline") && jsonObject.containsKey("is_final") && jsonObject.get("is_final") != null && jsonObject.get("is_final").toString().equals("false")) {
            close();
        }
    }

    /**
     * @param statusCode:连接关闭的状态码
     * @param reason:连接关闭的附加信息,例如异常关闭时,这个参数可能包含异常的详细描述信息
     * @param flag:连接关闭时是否为远程主机(服务器)发起关闭,如果为true,则表示由远程主机发起的关闭, 如果为false,则表示由本地客户端发起的关闭。
     */
    @Override
    public void onClose(int statusCode, String reason, boolean flag) {
        logger.info("WebSocket返回的状态码为【" + statusCode + "】,连接关闭的附加信息为:"
                + reason + ",是否为远程主机(服务器)发起的关闭:" + flag);
    }

    @Override
    public void onError(Exception e) {
        e.printStackTrace();
        logger.info("WebSocket发生异常,异常原因为:" + e);
    }

    /**
     * 发送音频数据
     */
    private void sendAudio() {
        String fileName = WsSendDataUtils.wavPath;
        String suffix = fileName.split("\\.")[fileName.split("\\.").length - 1];
        sendJson(mode, strChunkSize, chunkInterval, wavName, true, suffix);
        File file = new File(WsSendDataUtils.wavPath);

        int chunkSize = sendChunkSize;
        byte[] bytes = new byte[chunkSize];

        int readSize = 0;
        try (FileInputStream fis = new FileInputStream(file)) {
            if (WsSendDataUtils.wavPath.endsWith(".wav")) {
                fis.read(bytes, 0, 44); //skip first 44 wav header
            }
            readSize = fis.read(bytes, 0, chunkSize);
            while (readSize > 0) {
                // send when it is chunk size
                if (readSize == chunkSize) {
                    send(bytes); // send buf to server

                } else {
                    // send when at last or not is chunk size
                    byte[] tmpBytes = new byte[readSize];
                    for (int i = 0; i < readSize; i++) {
                        tmpBytes[i] = bytes[i];
                    }
                    send(tmpBytes);
                }
                // if not in offline mode, we simulate online stream by sleep
                if (!mode.equals("offline")) {
                    Thread.sleep(Integer.valueOf(chunkSize / 32));
                }

                readSize = fis.read(bytes, 0, chunkSize);
            }

            if (!mode.equals("offline")) {
                // if not offline, we send eof and wait for 3 seconds to close
                Thread.sleep(2000);
                sendEof();
                Thread.sleep(3000);
                close();
            } else {
                // if offline, just send eof
                sendEof();
            }

        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    /**
     * 发送结束表示给ws服务器
     */
    public void sendEof() {
        try {
            JSONObject obj = new JSONObject();

            obj.put("is_speaking", Boolean.valueOf(false));

            logger.info("sendEof: " + obj);
            // return;

            send(obj.toString());
            iseof = true;
            return;
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    public void sendJson(String mode, String strChunkSize, int chunkInterval, String wavName, boolean isSpeaking, String suffix) {
        try {

            JSONObject obj = new JSONObject();
            obj.put("mode", mode);
            JSONArray array = new JSONArray();
            String[] chunkList = strChunkSize.split(",");
            for (int i = 0; i < chunkList.length; i++) {
                array.add(Integer.valueOf(chunkList[i].trim()));
            }

            obj.put("chunk_size", array);
            obj.put("chunk_interval", Integer.valueOf(chunkInterval));
            obj.put("wav_name", wavName);

            if (WsSendDataUtils.hotwords.trim().length() > 0) {
                String regex = "\\d+";
                JSONObject jsonitems = new JSONObject();
                String[] items = WsSendDataUtils.hotwords.trim().split(" ");
                Pattern pattern = Pattern.compile(regex);
                String tmpWords = "";
                for (int i = 0; i < items.length; i++) {

                    Matcher matcher = pattern.matcher(items[i]);

                    if (matcher.matches()) {

                        jsonitems.put(tmpWords.trim(), items[i].trim());
                        tmpWords = "";
                        continue;
                    }
                    tmpWords = tmpWords + items[i] + " ";

                }

                obj.put("hotwords", jsonitems.toString());
            }

            if (suffix.equals("wav")) {
                suffix = "pcm";
            }
            obj.put("wav_format", suffix);
            if (isSpeaking) {
                obj.put("is_speaking", Boolean.valueOf(true));
            } else {
                obj.put("is_speaking", Boolean.valueOf(false));
            }
            logger.info("sendJson: " + obj);
            // return;

            send(obj.toString());

            return;
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    public static String connectWs(String host, String port, String url) throws URISyntaxException, InterruptedException {
        try {
            if (StringUtils.isBlank(host) || StringUtils.isBlank(port) || StringUtils.isBlank(url)) {
                logger.info("传入字段存在空值,当前host为【" + host + "】,port为【" + port + "】,url为【" + url + "】");
                return "";
            }
            String str = "--host " + host + " --port " + port + " --mode offline --audio_in " + url;
            String[] args = str.split(" ");
            // 设置命令行的相关参数
            ArgumentParser parser = ArgumentParsers.newArgumentParser("ws client").defaultHelp(true);
            // 设置端口号
            parser
                    .addArgument("--port")
                    .help("Port on which to listen.")
                    .setDefault("8889")
                    .type(String.class)
                    .required(false);
            // 设置服务器IP
            parser
                    .addArgument("--host")
                    .help("the IP address of server.")
                    .setDefault("127.0.0.1")
                    .type(String.class)
                    .required(false);
            // 设置音频数据地址
            parser
                    .addArgument("--audio_in")
                    .help("wav path for decoding.")
                    .setDefault("asr_example.wav")
                    .type(String.class)
                    .required(false);
            // 设置线程数
            parser
                    .addArgument("--num_threads")
                    .help("num of threads for test.")
                    .setDefault(1)
                    .type(Integer.class)
                    .required(false);
            // 设置分块大小
            parser
                    .addArgument("--chunk_size")
                    .help("chunk size for asr.")
                    .setDefault("5, 10, 5")
                    .type(String.class)
                    .required(false);
            // 设置分块间隔
            parser
                    .addArgument("--chunk_interval")
                    .help("chunk for asr.")
                    .setDefault(10)
                    .type(Integer.class)
                    .required(false);

            /** 音频识别系统(ASR)的状态参数
             * online:在线模式,音频数据实时传输到服务器进行处理,然后服务器实时返回识别结果
             * offline:离线模式,音频数据先存储在本地,然后一次性传输到服务器进行处理,服务器处理完成后一次性返回识别结果
             * hybrid:部分处理可以在本地进行,而另一部分可以再服务器端进行,以实现更好的性能和用户体验
             */
            parser
                    .addArgument("--mode")
                    .help("mode for asr.")
                    .setDefault("offline")
                    .type(String.class)
                    .required(false);
            // 热词
            parser
                    .addArgument("--hotwords")
                    .help("hotwords, splited by space, hello 30 nihao 40")
                    .setDefault("")
                    .type(String.class)
                    .required(false);
            // ws的ip
            String srvIp = "";
            // ws的端口
            String srvPort = "";
            // 音频路径
            String wavPath = "";
            // 线程数
            int numThreads = 1;
            // 分块大小
            String chunk_size = "";
            // 分块间隔
            int chunk_interval = 10;
            // 状态:默认为离线状态
            String strmode = "offline";
            // 热词
            String hot = "";
            try {
                Namespace ns = parser.parseArgs(args);
                srvIp = ns.get("host");
                srvPort = ns.get("port");
                wavPath = ns.get("audio_in");
                numThreads = ns.get("num_threads");
                chunk_size = ns.get("chunk_size");
                chunk_interval = ns.get("chunk_interval");
                strmode = ns.get("mode");
                hot = ns.get("hotwords");
                System.out.println(srvPort);

            } catch (ArgumentParserException ex) {
                ex.getParser().handleError(ex);
                return "";
            }

            WsSendDataUtils.strChunkSize = chunk_size;
            WsSendDataUtils.chunkInterval = chunk_interval;
            WsSendDataUtils.wavPath = wavPath;
            WsSendDataUtils.mode = strmode;
            WsSendDataUtils.hotwords = hot;

            System.out.println(
                    "serIp="
                            + srvIp
                            + ",srvPort="
                            + srvPort
                            + ",wavPath="
                            + wavPath
                            + ",strChunkSize"
                            + strChunkSize);
            // 设置音频采样率为16000Hz
            int RATE = 16000;
            //
            String[] chunkList = strChunkSize.split(",");
            // 音频分块大小
            int int_chunk_size = 60 * Integer.valueOf(chunkList[1].trim()) / chunkInterval;
            // 计算每个音频分块的大小,以采样点为单位
            int CHUNK = Integer.valueOf(RATE / 1000 * int_chunk_size);
            // 计算音频分块的步长,以采样点为单位
            int stride =
                    Integer.valueOf(
                            60 * Integer.valueOf(chunkList[1].trim()) / chunkInterval / 1000 * 16000 * 2);
            System.out.println("chunk_size:" + String.valueOf(int_chunk_size));
            System.out.println("CHUNK:" + CHUNK);
            System.out.println("stride:" + String.valueOf(stride));
            // 设置WebSocket客户端发送数据的分块大小
            WsSendDataUtils.sendChunkSize = CHUNK * 2;
            // ws地址
            String wsAddress = "ws://" + srvIp + ":" + srvPort;

            WsSendDataUtils c = new WsSendDataUtils(new URI(wsAddress));
            // 连接WebSocket
            c.connect();
            // 等待ws返回结果
            String wsData = WsSendDataUtils.messageMap.get("receivedWsData");
            while (StringUtils.isEmpty(wsData)) {
                Thread.sleep(3000);
                wsData = WsSendDataUtils.messageMap.get("receivedWsData");
                logger.info("正在获取wsData");
            }
            if (StringUtils.isNotBlank(wsData)) {
                WsSendDataUtils.messageMap.remove("receivedWsData");
                return wsData;
            }
            System.out.println("wsAddress:" + wsAddress);
            return "";
        } catch (Exception e) {
            e.printStackTrace();
            return "";
        }
    }
}

  • 26
    点赞
  • 11
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
Java WebSocket是一种用于实时双向通信的技术。在传输音频数据时,可以使用Java WebSocket来实现实时的音频数据传输。下面是使用Java WebSocket实现实时音频数据传输的步骤: 首先,需要建立WebSocket连接。使用Java WebSocket API提供的相关类和方法,可以轻松地建立WebSocket连接。可以在客户端和服务器端分别实现WebSocket连接的相关逻辑。 然后,在客户端准备要传输的音频数据音频数据可以通过录音设备或者音频文件来获取。可以使用Java的音频处理库,如javax.sound.sampled包来实现音频数据的获取和处理。 接下来,在客户端将音频数据发送给服务器。通过WebSocket连接,可以将音频数据以字节或者字符串的形式发送给服务器。在发送数据时,可以使用WebSocket的相关方法来实现。 在服务器端接收到音频数据后,可以对音频数据进行处理。例如,可以对音频数据进行解码、压缩、提取等操作。可以使用Java的音频处理库来实现对音频数据的处理逻辑。 最后,在服务器端将经过处理的音频数据发送回客户端。通过WebSocket连接,可以将处理后的音频数据以字节或者字符串的形式发送给客户端。客户端可以接收到音频数据后,采取相应的操作进行播放或者其他处理。 总结来说,使用Java WebSocket可以方便地实现实时音频数据传输。通过建立WebSocket连接,准备音频数据发送数据给服务器,处理音频数据发送处理后的数据给客户端等步骤,可以完成实时音频数据的传输和处理。
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值