草庐IT

java - 将音频从客户端流式传输到服务器再到多个客户端 Java

coder 2023-12-20 原文

正如标题所示,我正在制作一个应用程序,将音频从客户端流式传输到我存储音频的服务器,然后将其分发给多个客户端进行播放。在音频存储之前,我已经做好了一切工作,但我似乎无法将音频流式传输到多个客户端。

这是我的尝试:

服务器代码:

class Server {

    static int port = 50005;
    static int listen = 50010;
    static int listenerPort = 50015;
    static DatagramSocket serverSocket, listenSocket,
                            broadcastSocket;
    static byte[] receiveData, listenData;
    static DatagramPacket receivePacket, listenPacket;
    static DataOutputStream out;
    static ArrayList<String> listeners = new ArrayList<String>();
    static File file = new File("recording.bin");
    static boolean active = true;


    public static void main(String args[]) throws Exception {
        //Define the Receiving Datagram Socket
        serverSocket = new DatagramSocket(port);
        //Define the Timeout of the socket
        serverSocket.setSoTimeout(10000);
        //Define the listening socket
        listenSocket = new DatagramSocket(listen);
        listenSocket.setSoTimeout(10000);
        //Define Broadcasting socket
        broadcastSocket = new DatagramSocket();

        //Define data size, 1400 is best sound rate so far
        receiveData = new byte[1400];
        listenData = new byte[256];

        //Define the DatagramPacket object
        receivePacket = new DatagramPacket(receiveData, receiveData.length);
        listenPacket = new DatagramPacket(listenData, listenData.length);

        //Prepare the DataOutputStream to write to file.
        out = new DataOutputStream(new FileOutputStream(file));
        //Write and Broadcast on a separate thread
        Thread t = new Thread() {
            @Override public void run() {
                getPackets();
            }
        };
        t.start();
        //Set up Connection Listener on a separate thread
        Thread l = new Thread() {
            @Override public void run() {
                listen();
            }
        };
        l.start();
    }

    /***
     * Function that gets the audio data packets
     * saves them, and outputs the audio to the speakers.
     */
    public static void getPackets() {
        while (active) {
            try {
                //Wait until packet is received
                serverSocket.receive(receivePacket);
                System.out.println("Receiving Data");
                //Write to Binary file
                out.write(receiveData, 0, receiveData.length);
                //Send data
                sendData(receivePacket.getData());
            } catch (IOException e) {
                active = false;
                //If connection times out close it
                try {
                    out.close();
                } catch (IOException t) {
                    //Do nothing
                }
                System.out.println("Converting to audio");
                //Convert audio file
                new Convert().toWAV();
            }
        }
    }

    /***
     * Function that listens if there are any connections made to
     * the listener port and creates a datagram socket to stream audio
     * to anyone who connects
     */
    public static void listen() {
        while (active) {
            try {
                //Wait until packet is received
                listenSocket.receive(listenPacket);
                listeners.add(listenPacket.getAddress().getHostAddress());
                System.out.println("Client received");

            } catch (IOException e) {
                if(active) {
                    listen();
                }
            }
        }
    }

    public static void sendData(byte[] data) {
        try {
            for (int i = 0; i < listeners.size(); i++) {
                InetAddress destination = InetAddress.getByName(listeners.get(i));
                broadcastSocket.send(new DatagramPacket(data, data.length, destination, listenerPort));
                System.out.println("Sending Data");
            }
        } catch (Exception e) {
            //If it failed to send don't do anything
            e.printStackTrace();
        }
    }
}

这是我在多个客户端上运行的代码:

class Receiver {

    static AudioInputStream ais;
    static AudioFormat format;
    static boolean active = true;
    static int port = 50015;
    static DatagramSocket serverSocket, socket;
    static byte[] receiveData;
    static DatagramPacket receivePacket, packet;
    static ByteArrayInputStream bais;
    static int sampleRate = 8000;
    static int time = 10;

    static DataLine.Info dataLineInfo;
    static SourceDataLine sourceDataLine;

    public static void main(String args[]) throws Exception {
        socket = new DatagramSocket();
        InetAddress destination = InetAddress.getByName("server ip address");
        byte[] temp = new byte[256];
        //putting buffer in the packet
        packet = new DatagramPacket(temp, temp.length, destination, 50010);

        socket.send(packet);

        //Define the Receiving Datagram Socket
        serverSocket = new DatagramSocket(port);

        //Define data size, 1400 is best sound rate so far
        receiveData = new byte[1400];
        //Define the format sampleRate, Sample Size in Bits, Channels (Mono), Signed, Big Endian
        format = new AudioFormat(sampleRate, 16, 1, true, false);
        //Define the DatagramPacket object
        receivePacket = new DatagramPacket(receiveData, receiveData.length);
        //Prepare the Byte Array Input Stream
        bais = new ByteArrayInputStream(receivePacket.getData());
        //Now concert the Byte Array into an Audio Input Stream
        ais = new AudioInputStream(bais, format, receivePacket.getLength());

        //Define DataLineInfo
        dataLineInfo = new DataLine.Info(SourceDataLine.class, format);
        //Get the current Audio Line from the system
        sourceDataLine = (SourceDataLine) AudioSystem.getLine(dataLineInfo);
        //Open up sourceDataLine and Start it
        sourceDataLine.open(format);
        sourceDataLine.start();

        //Write and play on a separate thread
        Thread t = new Thread() {
            @Override
            public void run() {
                getPackets();
            }
        };
        t.start();
        //Now keep track of time
        while (time > 0) {
            time--;
            Thread.sleep(1000);
            if (time == 0) {
                active = false;
            }
        }
        //Close SourceDataLine
        sourceDataLine.drain();
        sourceDataLine.close();
    }

    /***
     * Function that gets the audio data packets
     * saves them, and outputs the audio to the speakers.
     */
    public static void getPackets() {
        try {
            while (active) {
                System.out.println("Receiving");
                //Wait until packet is received
                serverSocket.receive(receivePacket);
                //Reset time
                time = 10;
                //Send data to speakers
                toSpeaker(receivePacket.getData());
            }
        } catch (IOException e) {
        }
    }

    /***
     * Function that plays the sound bytes with the speakers.
     * @param soundbytes = bytes of sound sent to speakers
     */
    public static void toSpeaker(byte soundbytes[]) {
        try {
            sourceDataLine.write(soundbytes, 0, soundbytes.length);
        } catch (Exception e) {
            System.out.println("Not working in speakers...");
            e.printStackTrace();
        }
    }
}

我已经验证服务器确实收到了我用来获取客户端 ip 地址的初始连接,但客户端似乎没有收到任何数据,而且我在运行时没有收到任何错误。

如有任何帮助,我们将不胜感激。

最佳答案

好吧,在弄乱了一段时间之后,我意识到问题不在于代码,而是建筑物网络的管理员阻止了我。所以我要继续并将其标记为已回答。

关于java - 将音频从客户端流式传输到服务器再到多个客户端 Java,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/28009118/

有关java - 将音频从客户端流式传输到服务器再到多个客户端 Java的更多相关文章

  1. ruby - 具有身份验证的私有(private) Ruby Gem 服务器 - 2

    我想安装一个带有一些身份验证的私有(private)Rubygem服务器。我希望能够使用公共(public)Ubuntu服务器托管内部gem。我读到了http://docs.rubygems.org/read/chapter/18.但是那个没有身份验证-如我所见。然后我读到了https://github.com/cwninja/geminabox.但是当我使用基本身份验证(他们在他们的Wiki中有)时,它会提示从我的服务器获取源。所以。如何制作带有身份验证的私有(private)Rubygem服务器?这是不可能的吗?谢谢。编辑:Geminabox问题。我尝试“捆绑”以安装新的gem..

  2. java - 等价于 Java 中的 Ruby Hash - 2

    我真的很习惯使用Ruby编写以下代码:my_hash={}my_hash['test']=1Java中对应的数据结构是什么? 最佳答案 HashMapmap=newHashMap();map.put("test",1);我假设? 关于java-等价于Java中的RubyHash,我们在StackOverflow上找到一个类似的问题: https://stackoverflow.com/questions/22737685/

  3. ruby-on-rails - 启动 Rails 服务器时 ImageMagick 的警告 - 2

    最近,当我启动我的Rails服务器时,我收到了一长串警告。虽然它不影响我的应用程序,但我想知道如何解决这些警告。我的估计是imagemagick以某种方式被调用了两次?当我在警告前后检查我的git日志时。我想知道如何解决这个问题。-bcrypt-ruby(3.1.2)-better_errors(1.0.1)+bcrypt(3.1.7)+bcrypt-ruby(3.1.5)-bcrypt(>=3.1.3)+better_errors(1.1.0)bcrypt和imagemagick有关系吗?/Users/rbchris/.rbenv/versions/2.0.0-p247/lib/ru

  4. ruby-on-rails - s3_direct_upload 在生产服务器中不工作 - 2

    在Rails4.0.2中,我使用s3_direct_upload和aws-sdkgems直接为s3存储桶上传文件。在开发环境中它工作正常,但在生产环境中它会抛出如下错误,ActionView::Template::Error(noimplicitconversionofnilintoString)在View中,create_cv_url,:id=>"s3_uploader",:key=>"cv_uploads/{unique_id}/${filename}",:key_starts_with=>"cv_uploads/",:callback_param=>"cv[direct_uplo

  5. ruby-on-rails - 在 Rails 中调试生产服务器 - 2

    您如何在Rails中的实时服务器上进行有效调试,无论是在测试版/生产服务器上?我试过直接在服务器上修改文件,然后重启应用,但是修改好像没有生效,或者需要很长时间(缓存?)我也试过在本地做“脚本/服务器生产”,但是那很慢另一种选择是编码和部署,但效率很低。有人对他们如何有效地做到这一点有任何见解吗? 最佳答案 我会回答你的问题,即使我不同意这种热修补服务器代码的方式:)首先,你真的确定你已经重启了服务器吗?您可以通过跟踪日志文件来检查它。您更改的代码显示的View可能会被缓存。缓存页面位于tmp/cache文件夹下。您可以尝试手动删除

  6. java - 从 JRuby 调用 Java 类的问题 - 2

    我正在尝试使用boilerpipe来自JRuby。我看过guide从JRuby调用Java,并成功地将它与另一个Java包一起使用,但无法弄清楚为什么同样的东西不能用于boilerpipe。我正在尝试基本上从JRuby中执行与此Java等效的操作:URLurl=newURL("http://www.example.com/some-location/index.html");Stringtext=ArticleExtractor.INSTANCE.getText(url);在JRuby中试过这个:require'java'url=java.net.URL.new("http://www

  7. java - 我的模型类或其他类中应该有逻辑吗 - 2

    我只想对我一直在思考的这个问题有其他意见,例如我有classuser_controller和classuserclassUserattr_accessor:name,:usernameendclassUserController//dosomethingaboutanythingaboutusersend问题是我的User类中是否应该有逻辑user=User.newuser.do_something(user1)oritshouldbeuser_controller=UserController.newuser_controller.do_something(user1,user2)我

  8. java - 什么相当于 ruby​​ 的 rack 或 python 的 Java wsgi? - 2

    什么是ruby​​的rack或python的Java的wsgi?还有一个路由库。 最佳答案 来自Python标准PEP333:Bycontrast,althoughJavahasjustasmanywebapplicationframeworksavailable,Java's"servlet"APImakesitpossibleforapplicationswrittenwithanyJavawebapplicationframeworktoruninanywebserverthatsupportstheservletAPI.ht

  9. Observability:从零开始创建 Java 微服务并监控它 (二) - 2

    这篇文章是继上一篇文章“Observability:从零开始创建Java微服务并监控它(一)”的续篇。在上一篇文章中,我们讲述了如何创建一个Javaweb应用,并使用Filebeat来收集应用所生成的日志。在今天的文章中,我来详述如何收集应用的指标,使用APM来监控应用并监督web服务的在线情况。源码可以在地址 https://github.com/liu-xiao-guo/java_observability 进行下载。摄入指标指标被视为可以随时更改的时间点值。当前请求的数量可以改变任何毫秒。你可能有1000个请求的峰值,然后一切都回到一个请求。这也意味着这些指标可能不准确,你还想提取最小/

  10. 【Java 面试合集】HashMap中为什么引入红黑树,而不是AVL树呢 - 2

    HashMap中为什么引入红黑树,而不是AVL树呢1.概述开始学习这个知识点之前我们需要知道,在JDK1.8以及之前,针对HashMap有什么不同。JDK1.7的时候,HashMap的底层实现是数组+链表JDK1.8的时候,HashMap的底层实现是数组+链表+红黑树我们要思考一个问题,为什么要从链表转为红黑树呢。首先先让我们了解下链表有什么不好???2.链表上述的截图其实就是链表的结构,我们来看下链表的增删改查的时间复杂度增:因为链表不是线性结构,所以每次添加的时候,只需要移动一个节点,所以可以理解为复杂度是N(1)删:算法时间复杂度跟增保持一致查:既然是非线性结构,所以查询某一个节点的时候

随机推荐