当前位置: 首页 > 知识库问答 >
问题:

Java客户端发送音频到UDP服务器

汪胤
2023-03-14

我正在寻找一些关于如何实现一个能够将音频发送到服务器的Java客户端的链接/源代码/教程(见下文)。它将能够发送一个音频文件,然后由服务器接收并通过计算机扬声器播放。

我还想问,对于这种情况,使用UDP或TCP服务器会更好吗?因为我将开发一个android应用程序,它可以录制声音,然后通过电脑扬声器将声音发送到服务器进行实时播放。

package com.datagram;

import java.io.ByteArrayInputStream;
import java.net.DatagramPacket;
import java.net.DatagramSocket;

import javax.sound.sampled.AudioFormat;
import javax.sound.sampled.AudioInputStream;
import javax.sound.sampled.AudioSystem;
import javax.sound.sampled.DataLine;
import javax.sound.sampled.FloatControl;
import javax.sound.sampled.SourceDataLine;

class Server {

AudioInputStream audioInputStream;
static AudioInputStream ais;
static AudioFormat format;
static boolean status = true;
static int port = 50005;
static int sampleRate = 44100;

public static void main(String args[]) throws Exception {

    DatagramSocket serverSocket = new DatagramSocket(50005);
    byte[] receiveData = new byte[4000];

    format = new AudioFormat(sampleRate, 16, 1, true, false);

    while (status == true) {    

        DatagramPacket receivePacket = new DatagramPacket(receiveData,
                receiveData.length);

        serverSocket.receive(receivePacket);
        System.out.println("It works");

        ByteArrayInputStream baiss = new ByteArrayInputStream(
                receivePacket.getData());

        ais = new AudioInputStream(baiss, format, receivePacket.getLength());

        toSpeaker(receivePacket.getData());


    }
}

public static void toSpeaker(byte soundbytes[]) {
    try {

        DataLine.Info dataLineInfo = new DataLine.Info(SourceDataLine.class, format);
        SourceDataLine sourceDataLine = (SourceDataLine) AudioSystem.getLine(dataLineInfo);

        sourceDataLine.open(format);

        FloatControl volumeControl = (FloatControl) sourceDataLine.getControl(FloatControl.Type.MASTER_GAIN);
        volumeControl.setValue(100.0f);

        sourceDataLine.start();
        sourceDataLine.open(format);

        sourceDataLine.start();

        System.out.println("format? :" + sourceDataLine.getFormat());

        sourceDataLine.write(soundbytes, 0, soundbytes.length);
        System.out.println(soundbytes.toString());
        sourceDataLine.drain();
        sourceDataLine.close();
    } catch (Exception e) {
        System.out.println("Not working in speakers...");
        e.printStackTrace();
    }
}
}

共有1个答案

梁泰
2023-03-14

首先,一个小小的澄清:你想做的事情是音频流(只是让你知道-它将帮助你与任何未来的谷歌搜索)。

好的,一次回答一个问题:

>

>

  • TCP协议的细节使得它不是流的好选择(除非你知道如何正确使用它,这不容易,但可能)。TCP不好的原因是重传机制的存在。当数据包在网络中损坏或丢失时,TCP协议要求重传该数据包(这是模型的简化,但对于解释目的来说已经足够好了)。当传输需要实时播放的音频数据时,重传效果不佳。想象一下,你正在听某人的声音,突然声音停止了,然后又开始了(有延迟)。

    基本上UDP是更好的,但是你必须意识到这样一个事实,即UDP协议不能保证数据报(UDP协议的消息)将以与发送者相同的顺序到达接收者。因此,您必须确保丢弃任何顺序错误的数据报,或者缓冲传入的数据报,并重新建立正确的顺序。你还必须记住,UDP协议没有提供任何机制来保护传输——我的意思是你不能确定数据报会安全地通过网络(它们可能会丢失,UDP协议无法控制它)。

    最好的办法是不使用它们。您应该尝试实现RTP协议。

    “如何创建能够向上述服务器发送音频的android客户端?”

    >

  • 如我所见,您正在使用AudioFormat作为处理音频的工具。

    你需要做的是找到一些可以从Android麦克风中获取音频的东西,其格式与服务器应用程序中的音频格式相同。

    从AudioFormat文档中,我可以看到您使用的是特定的采样率(变量sampleRate),您使用的是默认编码,即PCM、16位采样大小、有符号值和小端位约定。

    在Android系统中,你应该关注的是AudioRecord,它可以从麦克风中获取原始音频帧。有很多关于如何使用录音的例子,大多数都使用PCM 16编码。他们中的大多数人会将音频写入文件,但没有什么能阻止你将其推送到某种网络插座。只需谷歌一下。

    只需记住,使用音频记录的采样率与您在服务器中使用的采样率相同。

    最后需要澄清的是持久性。端性取决于cpu体系结构。大多数Android设备使用Little Endian约定,因此您不必更改服务器代码中的任何内容。不过,您应该知道,有些设备可能正在使用Big-Endian。这里有更多解释。

  •  类似资料:
    • 从server-A(可通过静态IP全局访问)开始,我将UDP套接字绑定到0.0.0.0:25000。 然后,在(住宅)NAT 后面使用客户端 A,我将 UDP 套接字绑定到 0.0.0.0:25000。然后,客户端 A 将数据包发送到服务器 A。 服务器 A 接收数据包。服务器 A 记录远程套接字 K,数据包从中 NAT 开始。服务器 A 向 K 发送数据包,目的是 NAT 将数据包转发到客户端

    • 我正在创建我的产品,并与这个问题。有一天,我设置了Socket.io,一切都很好。第二天,我将服务器和客户端从http迁移到HTTPS。迁移后客户端和服务器端仍然连接,但不能从客户端发射到服务器,从服务器发射到客户端。 我的ssl证书位于和中,它们加载正确。运行在上的服务器 我的示例react组件。我的react应用程序运行在上。HTTPS连接良好,工作良好。 我该怎么办?也许我在中错误地使用了s

    • 我正在Unity中制作一个游戏,我试图将数据从客户端发送到服务器并返回到客户端(试图保存实例),但当我收到数据并尝试将数据发送回客户端时,它表示udp客户端未连接。 它成功地将数据从我的Unity客户端发送到服务器,但一旦它到达那里,套接字就会断开连接,我就无法返回任何内容。正如你所看到的,我试图设置一些多播选项,但它似乎不能正常工作。 客户: 服务器: 因此,服务器中UdpClient的实例会保

    • 我对使用UDP协议的服务器和客户端之间的通信有一个非常奇怪的问题。客户端是用Mono2x编写的(我使用Unity 3D作为我的客户端)并创建Udp客户端类实例: 我的服务器是 UWP 应用程序,我想在使用 DatagramSocket 的 Raspberry Pi 上运行: 我将数据从客户端发送到服务器,但运气不佳。我用TCPView检查了数据是从我的客户端应用程序发送的,但从未到达服务器。现在是

    • 我正在编写一个基于UDP的客户端服务器,并且已经获得了很多代码,但是我对UDP服务器如何将响应发送回UDP客户端感到困惑,这是我到目前为止的理解: 假设UDP客户端希望与UDP服务器通信,因此它将向UDP服务器发送请求(使用在客户端打开的UDP套接字),现在这将到达UDP服务器上的UDP模块,其中UDP模块将使用端口号标识UDP服务,并将该请求发送到该UDP服务/服务器 我的困惑是,在服务器端,有

    • 我需要有一个实时直播音频流从一个客户端到一个服务器到多个侦听器客户端。 目前,我已经从客户端录制工作和流通过套接字的音频。将io发送到服务器。服务器接收此数据,并且必须流式传输音频(也通过socket.io?)发送给希望侦听此流的客户端。它必须尽可能实时(尽量减少延迟)。 我正在使用GetUserMedia录制麦克风(浏览器兼容性在这里并不重要)。我希望客户端使用HTML5音频标签来收听流。在服务