jjzjj

JAVA(发送音频流 一服务器四客户端同机)

coder 2023-09-19 原文

我之前问过:https://stackoverflow.com/questions/35344535/dcom-alternative-for-java-sending-audio-streaming-in-the-same-machine

我想使用一台服务器从我的麦克风中捕获音频并发送给客户端(0 或 4)...

PD:我正在检查这个问题:Sending audio stream over TCP, UnsupportedAudioFileException但面向 One server with One Client 解决方案。 其他问题:Java - Broadcast voice over Java sockets Streaming audio from microphone with Java

我正在考虑使用 TCP(服务器/客户端模型),但服务器和 4 个客户端将接收数据(音频流),我不知道是否可以实现此替代方案(我担心港口管理)...

这里是我的初步(它仍然没有用,因为我有疑问,我在想如何解决我的顾虑)

变量:

static boolean bThreadCapture = false;
static boolean bThreadServer = false;
static ByteArrayOutputStream myByteArrayOutStream;
ExecutorService myServerPool = Executors.newFixedThreadPool(4);
static Thread myThreadServer = null;

现在我头疼

  final int iServerPort = 2370;
  final AudioFormat myAudioFormat = new AudioFormat(8000,8,1,false, true);
  final DataLine.Info myDataLineInfo = new DataLine.Info(TargetDataLine.class, myAudioFormat);
  if (!AudioSystem.isLineSupported(myDataLineInfo)) {
    System.out.println("Line not supported");
    System.exit(0);
  }
  try {
    final TargetDataLine myTargetDataLine = (TargetDataLine) AudioSystem.getLine(myDataLineInfo);
    myTargetDataLine.open(myAudioFormat);
    myByteArrayOutStream = null;

    //BEGIN definition Thread for CAPTURING AUDIO FROM MIC
    Runnable runnAudioCapture = new Runnable() {
      int bufferSize = (int) myAudioFormat.getSampleRate()* myAudioFormat.getFrameSize();
      byte buffer[] = new byte[bufferSize];
      public void run() {
        myByteArrayOutStream = new ByteArrayOutputStream();
        bThreadCapture = true;
        while (bThreadCapture) {
          try {
            int count = myTargetDataLine.read(buffer, 0, buffer.length);
            if (count > 0) {
              myByteArrayOutStream.write(buffer, 0, count);
              //  HERE: I need to send the bytes of Sound to all active Threads Client (from 1 until 4)
              //  But, How to know what (how much and which) are active threads client?
              //  How to access to each Executor?
            }
          } catch (IllegalArgumentException | ArrayIndexOutOfBoundsException e) {
            System.err.println("TargetDataLine problems: " + e);
          }
        }
        try {
          if (myByteArrayOutStream != null) myByteArrayOutStream.close();
        } catch (IOException e) {  }
      }
    };
    //END definition Thread for CAPTURING AUDIO FROM MIC


    //BEGIN definition Thread for ATTENDANT SERVER CLIENT (Still not defined) 
    myThreadServer = new Thread() {
      @Override
      public void run() {
        try {
          SrvrSocketProducer = new ServerSocket(iServerPort);
          System.out.println("Server Listening on port number: "+iServerPort);
        } catch (IOException e) {
          System.out.println("Could not listen on port: "+iServerPort);
        }
        new Thread(runnAudioCapture).start();  //BEGIN AUDIO CAPTURE
        while(bThreadServer) {
          Socket clientSocket = null;
          try {
            clientSocket = SrvrSocketProducer.accept(); 
          } catch (IOException e) {
            if(!bThreadServer) {
              System.out.println("Server Stopped.") ;
              break;
            }
            throw new RuntimeException("Error accepting client connection", e);
          }
          myServerPool.execute(new runnWorkerListener(clientSocket,myAudioFormat));
        }
        myServerPool.shutdown();
        bThreadCapture = false;  //STOP AUDIO CAPTURE
      }
    };
    //END definition Thread for ATTENDANT SERVER CLIENT (Still not defined) 
    myThreadServer.start();
  } catch (LineUnavailableException ex) {
    System.out.println(ex.toString());
  }

问题:

(合并到runnAudioCapture代码中定位帮助)

1. HERE: I need to send the bytes of Sound to all ACTIVE Threads Client (from 1 until 4)
2. But, How to know what (how much and which) are active threads client?
3. How to access to each Executor?

现在工作线程--

  class runnWorkerListener implements Runnable {
    Socket innerClientSocket = null;
    AudioFormat innerAdfmt = null;
    public runnWorkerListener(Socket clientSocket, AudioFormat audioFormat) {
      innerClientSocket = clientSocket;
      innerAdfmt = audioFormat;
    }
    public void run() {
      try {
        InputStream input  = innerClientSocket.getInputStream();
        OutputStream output = innerClientSocket.getOutputStream();
        // Now How Can I to Comunicate with runnAudioCapture?
        while (RunningClientAttender /*This variable still is not defined*/) {
          // I need to send (thread client here Not defined) EACH bytes from runnAudioCapture
        }
        output.close();
        input.close();
        System.out.println("Request processed: ");
      } catch (IOException e) {
        //report exception somewhere.
        e.printStackTrace();
      }
    }
  }

问题:

(合并到runnWorkerListener代码中定位帮助)

1. Now How Can I to Comunicate with runnAudioCapture?
2. I need to send (thread client here Not defined) EACH bytes from runnAudioCapture

我的疑问与: 一个专用于音频捕获的线程 一个线程专用于使用 Pool 接收客户端(1、2、3 或 4)并创建线程 worker (一个线程 worker 与“远程”客户端通信)

我不知道 Capturer 线程 Capturer 与每个 Worker 线程的句柄同步...

谢谢...

最佳答案

不幸的是,在 Java 中,流一次只能由一个人使用。您有一个流 myByteArrayOutStream,并且您希望在 4 个 TCP 连接之间共享它。

我建议您将音频数据写入文件。每次客户端连接时,您都会将文件的所有内容流式传输到该客户端(您可以打开文件,跳到最后,如果需要,只流式传输新内容)。为此,您需要为每个客户创建一个新线程。

如果您希望在 Java 中构建类似 Skype 音频的东西,那么这比仅使用 TCP 稍微复杂一些。 TCP 是一种从 A 到 B 获取数据的方法,可靠。对于音频,您通常希望它实时从 A 传输到 B。如果您在此过程中丢失了一个数据包,您不想返回并重新传输它,因为那样会给调用引入延迟。 TCP 的替代方案(可能更适合您的情况)是 UDP。它发送单个数据包,并且不保证它们会按顺序到达,甚至根本不保证。但它不会停下来等待丢失的数据包。

关于JAVA(发送音频流 一服务器四客户端同机),我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/35491848/

有关JAVA(发送音频流 一服务器四客户端同机)的更多相关文章

  1. ruby - 使用 ruby​​ 和 savon 的 SOAP 服务 - 2

    我正在尝试使用ruby​​和Savon来使用网络服务。测试服务为http://www.webservicex.net/WS/WSDetails.aspx?WSID=9&CATID=2require'rubygems'require'savon'client=Savon::Client.new"http://www.webservicex.net/stockquote.asmx?WSDL"client.get_quotedo|soap|soap.body={:symbol=>"AAPL"}end返回SOAP异常。检查soap信封,在我看来soap请求没有正确的命名空间。任何人都可以建议我

  2. 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..

  3. 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/

  4. 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

  5. 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

  6. ruby - 用 Ruby 编写一个简单的网络服务器 - 2

    我想在Ruby中创建一个用于开发目的的极其简单的Web服务器(不,不想使用现成的解决方案)。代码如下:#!/usr/bin/rubyrequire'socket'server=TCPServer.new('127.0.0.1',8080)whileconnection=server.acceptheaders=[]length=0whileline=connection.getsheaders想法是从命令行运行这个脚本,提供另一个脚本,它将在其标准输入上获取请求,并在其标准输出上返回完整的响应。到目前为止一切顺利,但事实证明这真的很脆弱,因为它在第二个请求上中断并出现错误:/usr/b

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

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

  8. jquery - 我的 jquery AJAX POST 请求无需发送 Authenticity Token (Rails) - 2

    rails中是否有任何规定允许站点的所有AJAXPOST请求在没有authenticity_token的情况下通过?我有一个调用Controller方法的JqueryPOSTajax调用,但我没有在其中放置任何真实性代码,但调用成功。我的ApplicationController确实有'request_forgery_protection'并且我已经改变了config.action_controller.consider_all_requests_local在我的environments/development.rb中为false我还搜索了我的代码以确保我没有重载ajaxSend来发送

  9. 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

  10. 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)我

随机推荐