- android - 多次调用 OnPrimaryClipChangedListener
- android - 无法更新 RecyclerView 中的 TextView 字段
- android.database.CursorIndexOutOfBoundsException : Index 0 requested, 光标大小为 0
- android - 使用 AppCompat 时,我们是否需要明确指定其 UI 组件(Spinner、EditText)颜色
我的主要目标是通过麦克风创建加密语音聊天的实时流媒体。然后,加密的音频通过网络从一个客户端传输到另一个客户端。问题是运行程序(流式传输)时音频总是变得断断续续。
不幸的是一切都失败了。
为了简单起见,我只包含了通过网络传输音频而不加密所需的代码。
主类 - 发送者和接收者
package com.emaraic.securevoice;
import com.emaraic.securevoice.utils.AES;
import java.net.DatagramPacket;
import java.net.DatagramSocket;
import java.net.InetAddress;
import javax.sound.sampled.*;
public class SecureVoice
{
public static void main(String[] args)
{
Receiver rx = new Receiver();
rx.start();
Transmitter tx = new Transmitter();
tx.start();
}
public static AudioFormat getAudioFormat()
{ //you may change these parameters to fit you mic
float sampleRate = 8000.0f; //8000,11025,16000,22050,44100
int sampleSizeInBits = 16; //8,16
int channels = 1; //1,2
boolean signed = true; //true,false
boolean bigEndian = false; //true,false
return new AudioFormat(sampleRate, sampleSizeInBits, channels, signed, bigEndian);
}
public static final String ANSI_BOLD = "\033[0;1m"; //not working in NetBeans
public static final String ANSI_RESET = "\033[0m";
public static final String ANSI_BLACK = "\033[30m";
public static final String ANSI_RED = "\033[31m";
public static final String ANSI_GREEN = "\033[32;4m";
public static final String ANSI_YELLOW = "\033[33m";
public static final String ANSI_BLUE = "\033[34m";
public static final String ANSI_PURPLE = "\033[35m";
public static final String ANSI_CYAN = "\033[36m";
public static final String ANSI_WHITE = "\033[37m";
}
发件人
package com.emaraic.securevoice;
import com.emaraic.securevoice.utils.AES;
import java.io.*;
import java.io.File;
import java.net.DatagramPacket;
import java.net.DatagramSocket;
import java.net.InetAddress;
import java.text.SimpleDateFormat;
import java.util.Date;
import javax.sound.sampled.AudioFileFormat;
import javax.sound.sampled.AudioFormat;
import javax.sound.sampled.AudioInputStream;
import javax.sound.sampled.AudioSystem;
import javax.sound.sampled.DataLine;
import javax.sound.sampled.Mixer;
import javax.sound.sampled.Port;
import javax.sound.sampled.TargetDataLine;
public class Transmitter extends Thread
{
// these parameters must be copied and used in the Receiver class of the other client
private static final String TX_IP = "10.101.114.179"; //ip to send to
private static final int TX_PORT = 1034;
@Override
public void run()
{
SecureVoice color = new SecureVoice();
Mixer.Info minfo[] = AudioSystem.getMixerInfo();
System.out.println(color.ANSI_BLUE + "Detecting sound card drivers...");
for (Mixer.Info minfo1 : minfo)
{
System.out.println(" " + minfo1);
}
if (AudioSystem.isLineSupported(Port.Info.MICROPHONE))
{
try
{
DataLine.Info dataLineInfo = new DataLine.Info(TargetDataLine.class, SecureVoice.getAudioFormat());
final TargetDataLine line = (TargetDataLine) AudioSystem.getLine(dataLineInfo); //recording from mic
line.open(SecureVoice.getAudioFormat());
line.start(); //start recording
System.out.println(color.ANSI_GREEN + "Recording...");
byte tempBuffer[] = new byte[line.getBufferSize()];
System.out.println(color.ANSI_BLUE + "Buffer size = " + tempBuffer.length + " bytes");
//AudioCapture audio = new AudioCapture(line); //capture the audio into .wav file
//audio.start();
while (true) //AES encryption
{
int read = line.read(tempBuffer, 0, tempBuffer.length);
byte[] encrypt = AES.encrypt(tempBuffer, 0, read);
// sendToUDP(encrypt);
sendToUDP(tempBuffer);
}
}
catch (Exception e)
{
System.out.println(e.getMessage());
System.exit(0);
}
}
}
public static void sendToUDP(byte soundpacket[])
{
try
{
// EncryptedAudio encrypt = new EncryptedAudio(soundpacket);
// encrypt.start();
DatagramSocket sock = new DatagramSocket();
sock.send(new DatagramPacket(soundpacket, soundpacket.length, InetAddress.getByName(TX_IP), TX_PORT));
sock.close();
}
catch (Exception e)
{
System.out.println(e.getMessage());
}
}
}
接收器
package com.emaraic.securevoice;
import com.emaraic.securevoice.utils.AES;
import java.net.DatagramPacket;
import java.net.DatagramSocket;
import java.net.InetAddress;
import java.util.logging.Level;
import java.util.logging.Logger;
import javax.sound.sampled.AudioFormat;
import javax.sound.sampled.AudioSystem;
import javax.sound.sampled.DataLine;
import javax.sound.sampled.SourceDataLine;
public class Receiver extends Thread {
// these parameters must by used in the Transmitter class of the other client
private static final String RX_IP = "localhost";
private static final int RX_PORT = 1034;
@Override
public void run() {
byte b[] = null;
while (true) {
b = rxFromUDP();
speak(b);
}
}
public static byte[] rxFromUDP() {
try {
DatagramSocket sock = new DatagramSocket(RX_PORT);
byte soundpacket[] = new byte[8192];
DatagramPacket datagram = new DatagramPacket(soundpacket, soundpacket.length, InetAddress.getByName(RX_IP), RX_PORT);
sock.receive(datagram);
sock.close();
// return AES.decrypt(datagram.getData(),0,soundpacket.length); // soundpacket ;
return soundpacket; // if you want to hear encrypted form
} catch (Exception e) {
System.out.println(e.getMessage());
return null;
}
}
public static void speak(byte soundbytes[]) {
try {
DataLine.Info dataLineInfo = new DataLine.Info(SourceDataLine.class, SecureVoice.getAudioFormat());
try (SourceDataLine sourceDataLine = (SourceDataLine) AudioSystem.getLine(dataLineInfo)) {
sourceDataLine.open(SecureVoice.getAudioFormat());
sourceDataLine.start();
sourceDataLine.write(soundbytes, 0, soundbytes.length);
sourceDataLine.drain();
}
} catch (Exception e) {
System.out.println(e.getMessage());
}
}
}
额外链接 http://emaraic.com/blog/secure-voice-chat
使用的IDE - Netbeans 11.1
Java JDK版本 - Java 13(Windows) - OpenJDK11(Linux)
最佳答案
两个问题。网络流数据在到达时间上会有抖动。由于操作系统和硬件驱动程序的开销时间,启动和停止音频播放将导致延迟间隙和抖动。还有一个较小的问题是记录和播放系统之间的音频采样率时钟率同步。所有这些都会影响固定速率的连续音频样本流。
为了避免音频启动延迟问题,请不要在网络数据包之间停止音频播放或录制系统,始终准备好音频数据以当前采样率连续播放。为了帮助解决网络抖动问题,请在开始播放之前缓冲一定量的音频数据,这样即使下一个网络数据包稍微延迟,也始终有一些音频可以播放。
您可能需要收集一些有关音频启动和网络延迟以及延迟变化的统计数据,以确定合适的缓冲量。另一种选择是音频丢失隐藏算法,该算法的实现要复杂得多。
关于java - 音频 - 来自 Java 的流音频不稳定,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/59607286/
我一直在为实时流和静态文件(HTTP 上的 MP3)构建网络广播播放器。我选了Howler.js作为规范化 quirks 的后端的 HTML5 Audio (思考:自动播放、淡入/淡出、进度事件)。
vue移动端input上传视频、音频,供大家参考,具体内容如下 html部分 ?
关闭。这个问题需要更多 focused .它目前不接受答案。 想改进这个问题?更新问题,使其仅关注一个问题 editing this post . 7年前关闭。 Improve this questi
我想在我的程序中访问音频和视频。 MAC里面可以吗? 我们的程序在 Windows 上运行,我使用 directshow 进行音频/视频编程。但我想在 MAC 中开发相同的东西。 有没有像direct
我的应用程序(使用 Flutter 制作,但这应该无关紧要)具有类似于计时器的功能,可以定期(10 秒到 3 分钟)发出滴答声。我在我的 Info.plist 中激活了背景模式 Audio、AirPl
我是 ionic 2 的初学者 我使用了音频文件。 import { Component } from '@angular/core'; import {NavController, Alert
我有一个包含ListView和图片的数据库,我想在每个语音数据中包含它们。我已经尝试过,但是有很多错误。以下是我的java和xml。 数据库.java package com.example.data
我在zend framework 2上建立了一个音乐社交网络。您可以想象它与SoundCloud相同,用户上传歌曲,其他用户播放它们,这些是网站上的基本操作。 我知道将要托管该页面的服务器将需要大量带
我正在尝试在android应用中播放音频,但是在代码中AssetFileDescriptor asset1及其下一行存在错误。这是代码: MediaPlayer mp; @Override prote
我对 WordPress Audio Shortcode有问题。我这样使用它: 但是在前面,在HTML代码中我得到了: document.createElement('audio');
我正在做一项关于降低噪音的滤波技术的实验。我在数据集中的样本是音频文件(.wav),因此,我有:原始录制的音频文件,我将它们与噪声混合,因此变得混合(噪声信号),我将这些噪声信号通过滤波算法传递,输出
一个人会使用哪种类型的神经网络架构将声音映射到其他声音?神经网络擅长学习从序列到其他序列,因此声音增强/生成似乎是它们的一种非常流行的应用(但不幸的是,事实并非如此-我只能找到一个(相当古老的)洋红色
这个让我抓狂: 在专用于此声音播放/录制应用程序的 Vista+ 计算机上,我需要我的应用程序确保(默认)麦克风电平被推到最大。我该怎么做? 我找到了 Core Audio lib ,找到了如何将 I
{ "manifest_version": 2, "name": "Kitten Radio Extension", "description": "Listen while browsi
class Main { WaveFileReader reader; short[] sample; Complex[] tmpComplexArray; publi
我正在使用电话录音软件(android),该软件可以记录2个人在电话中的通话。每个电话的输出是一个音频文件,其中包含来自 call 者和被 call 者的声音。 但是,大多数情况下,运行此软件的电话发
我正在构建一个需要语音激活命令的Web应用程序。我正在使用getUserMedia作为音频输入。 对于语音激活命令,该过程是用户将需要通过记录其语音来“校准”命令。例如,对于“停止”命令,用户将说出“
我正在开发一个Cordova应用程序,并将PouchDB用作数据库,当连接可用时,它将所有信息复制到CouchDB。 我成功存储了简单的文本和图像。 我一直在尝试存储视频和音频,但是没有运气。 我存储
我正在开发web application,我必须在其中使用.MP3的地方使用播放声音,但是会发生问题。 声音为play good in chrome, Firefox,但为safari its not
如何减少音频文件的位深?是否忽略了MSB或LSB?两者混合吗? (旁问:这叫什么?) 最佳答案 TL / DR:将音频曲线高度变量右移至较低位深度 可以将音频视为幅度(Y轴)随时间(X轴)的模拟曲线。
我是一名优秀的程序员,十分优秀!