我正在编写一个 javascript web 客户端,我想在我的客户端播放从 UDP 流(原始 RTP)编码为 PCM 的音频(我可以自由更改流的目标主机和端口)。如何做呢?
我阅读了 Howler,但找不到任何 UDP 侦听选项或 PCM 支持。我还查看了 WebRTC,但它似乎不支持 PCM(如果我理解正确的话)。
非常感谢!
所以我终于做到了!我写了一个小的 python 服务器来将 UDP 转换为 websocket。我使用 Quart 编写它,它就像一个异步烧瓶,以使 websocket 和 UDP 选择更容易:
import json
import struct
import socket
import asyncio
from quart import Quart, websocket
app = Quart(__name__)
class PcmServerProtocol:
def __init__(self, queue: asyncio.Queue):
self._queue = queue
def connection_made(self, transport):
self.transport = transport
def datagram_received(self, data, addr):
pcm_chunks = struct.unpack(
# Convert the data to pulses
"<" + "h" * (len(data) // struct.calcsize("h")),
data
)
self._queue.put_nowait(json.dumps(pcm_chunks))
async def sending(queue: asyncio.Queue):
while True:
data = await queue.get()
await websocket.send(data)
@app.websocket("/sound")
async def sound():
sock = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
sock.bind(("127.0.0.1", 15000))
pcm_queue = asyncio.Queue()
streamer = asyncio.create_task(sending(pcm_queue))
pcm_receiver = asyncio.create_task(
asyncio.get_event_loop().create_datagram_endpoint(
lambda: PcmServerProtocol(pcm_queue), sock=sock
)
)
await asyncio.gather(streamer, pcm_receiver)
if __name__ == "__main__":
app.run()
现在我们只需要连接一个网络套接字并从 javascript 播放声音,为此我使用了网络音频 API:
let audioCtx = new AudioContext();
let ws = new WebSocket('ws://' + document.domain + ':' + location.port + '/sound');
ws.onmessage = function (event) {
let pcm_chunks = JSON.parse(event.data);
let node = audioCtx.createBufferSource();
let buffer = audioCtx.createBuffer(1, pcm_chunks.length, 44100);
let data = buffer.getChannelData(0);
for (let i = 0; i < pcm_chunks.length; i++) {
// Normalize to between -1.0 and 1.0, my PCM was signed 16bit
data[i] = pcm_chunks[i] / 32768;
}
node.buffer = buffer;
node.loop = false;
node.connect(audioCtx.destination);
node.start(0);
};
我发现的一个缺点是通过网络进行操作会使声音滞后,即使在 localhost 上设置它时效果很好。
显然,我们非常欢迎您发表评论并提出其他想法。
编辑:
我实际上找到了使用 vlc(或 cvlc)更好的解决方案。看起来 vlc 可以采用 rtp 流并通过几种操作重新传输它。
cvlc rtp://source_ip:source_port --sout '#transcode{acodec=mp3}:standard{access=http,mux=mp3,dst=dest_ip:dest_port}'
启动该进程时,客户端可以是最简单的 HTML5 音频标签:
<audio controls autoplay>
<source src="http://dest_ip:dest_port" type="audio/mp3">
</audio>
本文收集自互联网,转载请注明来源。
如有侵权,请联系[email protected] 删除。
我来说两句