two way audio over one link
This commit is contained in:
@@ -101,8 +101,25 @@
|
||||
|
||||
// connect to websocket
|
||||
callWebsocket = new WebSocket(location.origin.replace(/^http/, 'ws') + "/call/initiate/" + destinationHash);
|
||||
callWebsocket.onopen = () => {
|
||||
console.log("connected to websocket");
|
||||
callWebsocket.onmessage = async function(event) {
|
||||
|
||||
// get encoded codec2 bytes from websocket message
|
||||
const encoded = await event.data.arrayBuffer();
|
||||
|
||||
// decode codec2 audio
|
||||
const decoded = await Codec2Lib.runDecode(codecModeElement.value, encoded);
|
||||
|
||||
// convert decoded codec2 to wav audio
|
||||
const wavAudio = await Codec2Lib.rawToWav(decoded);
|
||||
|
||||
// play wav audio buffer
|
||||
let audioCtx = new AudioContext()
|
||||
const audioBuffer = await audioCtx.decodeAudioData(wavAudio.buffer);
|
||||
const sampleSource = audioCtx.createBufferSource();
|
||||
sampleSource.buffer = audioBuffer;
|
||||
sampleSource.connect(audioCtx.destination)
|
||||
sampleSource.start(0);
|
||||
|
||||
};
|
||||
|
||||
// record mic to send to websocket
|
||||
@@ -187,6 +204,28 @@
|
||||
|
||||
};
|
||||
|
||||
// record mic to send to websocket
|
||||
await startRecordingMicrophone((encoded) => {
|
||||
|
||||
// do nothing if websocket closed
|
||||
if(listenWebsocket.readyState !== WebSocket.OPEN){
|
||||
return;
|
||||
}
|
||||
|
||||
// do nothing when audio muted
|
||||
if(checkboxMuteMicElement.checked){
|
||||
return;
|
||||
}
|
||||
|
||||
// send encoded audio to websocket
|
||||
listenWebsocket.send(encoded);
|
||||
|
||||
// update stats
|
||||
encodedBytesSent += encoded.length;
|
||||
encodedBytesSentElement.innerText = formatBytes(encodedBytesSent);
|
||||
|
||||
});
|
||||
|
||||
}
|
||||
|
||||
function stopListening() {
|
||||
|
||||
30
web.py
30
web.py
@@ -84,6 +84,8 @@ class ReticulumWebChat:
|
||||
# remember websocket clients
|
||||
self.websocket_clients: List[web.WebSocketResponse] = []
|
||||
|
||||
self.link_call_audio = None
|
||||
|
||||
# web server has shutdown, likely ctrl+c, but if we don't do the following, the script never exits
|
||||
async def shutdown(self, app):
|
||||
|
||||
@@ -193,8 +195,9 @@ class ReticulumWebChat:
|
||||
|
||||
# todo implement
|
||||
def client_packet_received(message, packet):
|
||||
# todo, we don't send anything from the call initiator from the call receiver yet...
|
||||
pass
|
||||
|
||||
# send audio received from call receiver to call initiator websocket
|
||||
asyncio.run(websocket_response.send_bytes(message))
|
||||
|
||||
# create link
|
||||
link = RNS.Link(server_destination)
|
||||
@@ -250,12 +253,14 @@ class ReticulumWebChat:
|
||||
# client connected to us
|
||||
def client_connected(link):
|
||||
print("client connected")
|
||||
self.link_call_audio = link
|
||||
link.set_link_closed_callback(client_disconnected)
|
||||
link.set_packet_callback(server_packet_received)
|
||||
|
||||
# client disconnected from us
|
||||
def client_disconnected(link):
|
||||
print("client disconnected")
|
||||
self.link_call_audio = None
|
||||
|
||||
# client sent us a packet
|
||||
def server_packet_received(message, packet):
|
||||
@@ -275,7 +280,26 @@ class ReticulumWebChat:
|
||||
# handle websocket messages until disconnected
|
||||
async for msg in websocket_response:
|
||||
msg: WSMessage = msg
|
||||
if msg.type == WSMsgType.ERROR:
|
||||
if msg.type == WSMsgType.BINARY:
|
||||
try:
|
||||
|
||||
# drop audio packet if it is too big to send
|
||||
if len(msg.data) > RNS.Link.MDU:
|
||||
print("dropping packet " + str(len(msg.data)) + " bytes exceeds the link packet MDU of " + str(RNS.Link.MDU) + " bytes")
|
||||
continue
|
||||
|
||||
# send codec2 audio received from call receiver on websocket, to call initiator over reticulum link
|
||||
if self.link_call_audio is not None:
|
||||
print("sending bytes to call initiator: {}".format(len(msg.data)))
|
||||
RNS.Packet(self.link_call_audio, msg.data).send()
|
||||
else:
|
||||
print("link to call initiator not available")
|
||||
|
||||
except Exception as e:
|
||||
# ignore errors while handling message
|
||||
print("failed to process client message")
|
||||
print(e)
|
||||
elif msg.type == WSMsgType.ERROR:
|
||||
# ignore errors while handling message
|
||||
print('ws connection error %s' % websocket_response.exception())
|
||||
|
||||
|
||||
Reference in New Issue
Block a user