- iOS/Objective-C 元类和类别
- objective-c - -1001 错误,当 NSURLSession 通过 httpproxy 和/etc/hosts
- java - 使用网络类获取 url 地址
- ios - 推送通知中不播放声音
我正在尝试创建 Speex Voip 客户端和服务器。我掌握了基础知识,并且它通过 UDP 在本地机器上工作正常。我正在使用 JSpeex 来实现可移植性。我正在寻找有关创建客户端和服务器的技巧。你有什么想法?
JSpeex 库每次调用只能编码 320 个字节,因此发送到服务器的数据包很小(在我的例子中约为 244 个字节)。客户端等待大约 1 或 2 KB 的编码数据在发送之前准备好或让服务器处理缓冲数据包会更好吗?
此外,任何关于如何实现缓冲数据的帮助都会很好。
我拥有的一些可以在本地机器上运行的东西。
客户:
public void run() {
int nBytesToRead = (m_inputAudioFormat.getFrameSize() * 160);
int nAvailable = 0;
byte[] abPCMData = new byte[nBytesToRead];
byte[] abSpeexData = null;
UserSpeexPacket userSpeexPacket = new UserSpeexPacket("Xiphias3", "TheLounge", null, 0);
while (m_captureThread != null) {
nAvailable = m_line.available();
如果(nAvailable >= nBytesToRead){
int nBytesRead = m_line.read(abPCMData, 0, nBytesToRead);
如果(nBytesRead == -1)中断;
如果(nBytesRead < nBytesToRead)
Arrays.fill(abPCMData, nBytesRead, abPCMData.length, (byte) 0);
abSpeexData = createSpeexPacketFromPCM(abPCMData, 0, abPCMData.length);
//DatagramPacket packet = new DatagramPacket(abSpeexData, 0, abSpeexData.length, m_connection.getInetAddress(), m_nServerPort);
userSpeexPacket.setSpeexData(abSpeexData);
userSpeexPacket.incrementPacketNumber();
DatagramPacket packet = UserSpeexPacket.userSpeexPacketToDatagramPacket(m_connection.getInetAddress(), m_connection.getPort(), userSpeexPacket);
尝试 {
m_connection.send(数据包);
}
catch (IOException iox){
System.out.println("与服务器的连接丢失:"+ iox.getMessage());
休息;
}
}
}
关闭线();
断开();
}
public byte[] createSpeexPacketFromPCM(byte[] abPCMData, int nOffset, int nLength)
{
byte[] abEncodedData = null;
m_speexEncoder.processData(abPCMData, nOffset, nLength);
abEncodedData = new byte[m_speexEncoder.getProcessedDataByteSize()];
m_speexEncoder.getProcessedData(abEncodedData, 0);
返回 abEncodedData;
}
服务器:
DatagramPacket packet = new DatagramPacket(new byte[2048], 0, 2048);
byte[] abPCMData = null;
long lPrevVolPrintTime = 0;
而(m_bServerRunning){
尝试 {
m_serverSocket.receive(数据包);
//System.out.println("数据包大小为"+ packet.getData().length);
//System.out.println("Got packet from "+ packet.getAddress().getHostAddress());
//abPCMData = decodeSpeexPacket(packet.getData(), 0, packet.getLength());
UserSpeexPacket usp = UserSpeexPacket.datagramPacketToUserSpeexPacket(数据包);
abPCMData = decodeSpeexPacket(usp.getSpeexData(), 0, usp.getSpeexData().length);
m_srcDataLine.write(abPCMData, 0, abPCMData.length);
如果 (System.currentTimeMillis() >= (lPrevVolPrintTime + 500)) {
//System.out.println("当前音量:"+ AudioUtil.getVolumeLevelForPCM22050Hz16Bit1Channel(abPCMData, 0, abPCMData.length));
lPrevVolPrintTime = System.currentTimeMillis();
}
}
catch (IOException iox){
如果(m_bServerRunning){
System.out.println("服务器套接字中断:"+ iox.getMessage());
停止服务器();
}
}
}
最佳答案
我正在做一个类似的项目。从我读过的所有内容和个人经验来看,您最好的选择是使用少量数据并尽快发送它们。您希望在接收器端完成任何抖动缓冲。
VoIP 应用程序通常每秒发送 50-100 个数据包。对于 8000Hz 的 uLaw 编码,这将导致数据包大小为 80-160 字节。这样做的原因是一些数据包不可避免地会被丢弃,而您希望对接收方的影响尽可能小。因此,对于每个数据包 10 毫秒或 20 毫秒的音频数据,丢失的数据包可能会导致小问题,但远没有丢失 2k 音频数据(~250 毫秒)那么严重。
此外,对于较大的数据包,您必须在发送之前在发送方收集所有数据。因此,给定一个典型的 50 毫秒网络延迟,每个数据包有 20 毫秒的音频数据,接收方至少在 70 毫秒内不会听到发送方所说的内容。现在想象一次发送 250 毫秒的音频时会发生什么。发送方说话和接收方播放该音频之间将经过 270 毫秒。
用户似乎更能容忍某些地方的数据包丢失,这会导致音频质量低于标准,因为大多数电话的音频质量本来就不是很好。然而,用户也习惯于现代电话电路的极低延迟,因此即使引入 250 毫秒的往返延迟也会令人非常沮丧。
现在,就实现缓冲而言,我找到了一个使用队列的好策略(糟糕,这里使用 .NET :)),然后将其包装在一个类中,该类跟踪所需的最小和最大数据包数队列。使用严格的锁定,因为您很可能会从多个线程访问它。如果队列“触底”并且其中有零个数据包(缓冲区欠载),请设置一个标志并返回空值,直到数据包计数达到您想要的最小值。但是,您的消费者将必须检查是否返回 null 并且不将任何内容排队到输出缓冲区中。或者,您的消费者可以跟踪最后一个数据包并重复将其排队,这可能会导致循环音频,但在某些情况下,这可能“听起来”比静音更好。您将不得不这样做,直到生产者将足够的数据包放入队列以达到最小值。这将为用户带来更长的静默期,但这通常比短而频繁的静默期(断断续续)更容易接受。如果您收到大量数据包并且生产者填满了队列(达到所需的最大值),您可以开始忽略新数据包,或者从队列前面丢弃足够多的数据包以返回到最小值。
虽然选择这些最小/最大值很困难。您正在尝试平衡流畅的音频(无欠载)与发送方和接收方之间的最小延迟。 VoIP 很有趣,但它确实令人沮丧!祝你好运!
关于java - 帮助创建 Speex Voip 服务器和客户端,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/3799795/
关闭。这个问题不满足Stack Overflow guidelines .它目前不接受答案。 想改善这个问题吗?更新问题,使其成为 on-topic对于堆栈溢出。 7年前关闭。 Improve thi
在 VOIP 和与 VOIP 系统的集成方面,我非常陌生。 这是我正在尝试做的事情: 来电者呼入,接线员接听电话。 1.1。开始将调用者的音频流式传输到云中的分析服务。 一旦执行了音频分析(通常在几秒
*** Terminating app due to uncaught exception 'NSInternalInconsistencyException', reason: 'PushKit a
我想在推送通知到来时将我的本地数据库与服务器同步,但我无法使用静默通知来同步,因为 application:didReceiveRemoteNotification:fetchCompletionHa
我在应用商店中有一个使用静默推送通知的应用,新版本将改为使用 Voip 推送。 以前,我已经能够连接开发推送证书和产品推送证书,然后在发送推送的服务器代码中使用该组合证书。这样做的好处是,如果服务器代
我正在使用 voip 推送通知制作 ios 应用程序。 我想从 Node js 发送 voip 推送通知,但不是很好。 我阅读了本教程 CallKit iOS Swift Tutorial for V
在请求带有CXEndCallAction的CXTransaction时,事务失败并显示错误代码 错误Domain = com.apple.CallKit.error.requesttransactio
我有一堆 RTP 数据包,我想将它们重新组合成音频流。对于每个数据包,我都有序列号、SSRC、时间戳和一个表示数据本身的字节数组。 目前,我通过它们的 SSRC 获取每个数据包子集,然后按时间戳对它们
关闭。这个问题不满足Stack Overflow guidelines .它目前不接受答案。 想改善这个问题吗?更新问题,使其成为 on-topic对于堆栈溢出。 5年前关闭。 Improve thi
我必须计算 RTP 流中数据包之间的时间偏移。对于使用 Theora 编解码器编码的视频流,我有时间戳字段,如 2856000 2940000 3024000 ... 所以我假设传输偏移量是
当调用从队列转移到代理时,是否有一种简单的方法可以将代理扩展捕获到 Asterisk 变量中? 编辑:我们正在使用动态代理。座席接听电话后,将电话转接到另一分机。在该扩展的上下文中,我们需要使用一个
Closed. This question does not meet Stack Overflow guidelines 。它目前不接受答案。 想改善这个问题吗?更新问题,使其成为 Stack Ov
我想用 SIP 协议(protocol)实现一个 Voip 应用程序。我已使用 tutorial 管理接收和拨号.我遇到的问题是,我的应用程序在关闭时不会接听来电。我曾尝试使用服务,但没有帮助我解决问
我正在做一个在 android 中录制 VOIP 通话的项目,我没有找到任何解决方案,有很多应用程序支持手机上的 VOIP 录音。我找不到任何教程和帮助。 Cube Call Recorder是提供此
我刚刚编写了我的 Twilio 应用程序,以便向我在印度尼西亚的电话号码进行出站语音调用。 当我接听语音电话时,在第一个音频播放之前大约有 3-5 秒的延迟,无论是使用 或使用 动词。 你们知道为什么
我正在尝试在 ubuntu 上安装 mod_java。 我已经安装了最新的 java(1.6)。 我在 module.conf.xml 中配置了启用 mod_java 模块的 freeswitch 然
我正在开发一个需要定期(经常)在后台执行某些工作的应用程序,即使该应用程序本身未显示。我已经宣布它为VOIP应用程序,使其启动,甚至在10分钟(600秒)后自动重新启动。该应用程序不适用于App St
我有用 Java/SWT 编写的独立应用程序。现在我需要在这个应用程序中实现软件电话功能。有没有完全用 java 编写的现成可用的 VOIP 框架,它可以让我快速开发软件电话,而不会弄乱低级 sip/
我正在使用 iOS 版本 9 和 swift。我可以在应用程序处于事件状态时接听电话,但当应用程序关闭或在后台时,我遇到了一个问题,它只收到通知,而不是完整的铃声(我正在使用 SinchService
我正在开发一个通过 Wi-Fi 与非 iOS 设备通信的 iPhone 应用程序。我的应用程序正在使用 VOIP。我已经配置了流并将必要的 UIBackgroundModes 添加到我的 plist
我是一名优秀的程序员,十分优秀!