[英]How can I reduce delay when sending audio over UDP?
我已經編寫了一個小型Java程序(pc)和android應用,旨在將音頻從pc傳輸到手機。 我正在通過UDP發送音頻數據,無法確定發生延遲的原因。 從客戶端到服務器,在處理數據包之前大約需要1.5-2秒。
我的程序緩沖512個字節以發送給客戶端,該字節在接收到后立即播放。
我測試了一些不同的配置,任何(基本上)高於此值的配置,延遲只會增加。 使用較低的值,在延遲方面沒有明顯的改善,但是卻存在明顯的質量損失。
根據窗口,設備之間的ping時間僅為3毫秒,因此我認為網絡連接不是問題,盡管我不是很肯定。
我的客戶(PC)的代碼如下所示。
byte[] buffer = new byte[512];
while (true) {
try {
audioInput.read(buffer, 0, buffer.length);
DatagramPacket data = new DatagramPacket(buffer, buffer.length, address, port);
dout.send(data);
System.out.println("Sent Packet #" + i++);
} catch (IOException e) {
e.printStackTrace();
}
}
服務器(電話)的代碼如下。
byte[] buffer = new byte[512];
DatagramPacket incomingPacket = new DatagramPacket(buffer, buffer.length);
while (true) {
try {
dgs.receive(incomingPacket);
buffer = incomingPacket.getData();
audioOutput.write(buffer, 0, buffer.length);
} catch (IOException e) {
e.printStackTrace();
}
}
我期望數據包以接近5ms的網絡延遲的速度到達,但實際上只有在1500ms之后才接收到它們。
我希望你們中的一些人可能對這種問題有經驗。 我知道Discord和Skype之類的應用程序以更高的比特率傳輸流,具有更高的延遲,但是延遲卻低得多,所以我希望可能會錯過一些東西。
您正在嘗試進行實時流式傳輸。 讓我們看看整個過程中的延遲預算。
首先,您使用512字節的緩沖區-假設樣本為float
且樣本率為44.1k
,則每次處理128
樣本,這將提供~2.9ms
的緩沖時間。
在此緩沖區大小下,您可以獲得的最佳值為~7.5ms
。
控制流程:
1:音頻輸入硬件生成樣本並將其存儲在緩沖區中。 在預定數量的樣本之后,操作系統將中斷以提供音頻。 該緩沖時間可能明顯長於128個樣本。 這是T1
2:操作系統安排音頻守護程序進程運行。 它在運行之前等待S1
3:音頻守護程序運行,處理音頻,將其寫入緩沖區,然后向操作系統發出信號,指出可以讀取樣本。 這段時間短得可以忽略不計。
4:操作系統通過audioInput.read(buffer, 0, buffer.length);
對audioInput.read(buffer, 0, buffer.length);
的調用來調度您的輸入進程audioInput.read(buffer, 0, buffer.length);
。 它在計划之前等待S2
。
5:您調用System.out.println()
。 這可能會阻塞-尤其是在您每秒寫入約350次時-可能直到安排了另一個不相關的進程為止。 S3
6:將UDP寫入網絡套接字。 操作系統可能將其排隊等待發送-稍后發生的時間可能會微不足道
7:通過網絡傳輸。 T2
接收方幾乎與上述相反。
因此總延遲為
2 * (T1 + S1 + S2 + S3 + T2)
我想您的大多數延遲是發送和接收T1
的硬件緩沖時間。 如果您得到的值遠低於10ms
,則S1,S2,S3
將開始變得有意義。
注意:
S1
, S2
是運行調度延遲,並且取決於系統負載和調度程序策略。 音頻渲染處理程序通常以實時威脅優先級運行。 S3
。 此延遲特別不可預測。 真正降低延遲的方法是:
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.