i am creating a link so that any user who enters it can talk to each other via audio. according to the webrtc documentation, i managed to write a code, but the sound is not transmitted between users. i would appreciate it if you could tell me what the problem with my code is.
I get this error:
DOMException failed (in promise): Failed to execute ‘addIceCandidate’ on ‘RTCPeerConnection’: The remote description was empty.
main.py
from flask import Flask, render_template
from flask_socketio import SocketIO, emit
app = Flask(__name__)
socketio = SocketIO(app)
@app.route('/')
def index():
return render_template('index.html')
@socketio.on('sdp')
def handle_sdp(data):
emit('sdp', data, broadcast=True, include_self=False)
@socketio.on('ice')
def handle_ice(data):
emit('ice', data, broadcast=True, include_self=False)
if __name__ == '__main__':
socketio.run(app, debug=True)
index.html
<html>
<head>
<title>Voice Chat</title>
</head>
<body>
<audio id="remote_audio" autoplay playsinline></audio>
<button onclick="start(true)">caller</button>
<button onclick="start(false)">calee</button>
</body>
<script src="https://cdn.socket.io/4.7.5/socket.io.min.js"></script>
<script>
let pc;
let local_stream;
const remote_audio = document.getElementById('remote_audio');
const socket = io();
const PEER_CONNECTION_CONFIG = {
'iceServers': [
{'urls': 'stun:stun.l.google.com:19302'},
{'urls': 'stun:stun.stunprotocol.org:3478'}
]
};
pc = new RTCPeerConnection(PEER_CONNECTION_CONFIG);
pc.ontrack = got_remote_stream;
pc.onicecandidate = got_ice_candidate;
async function start(is_caller){
try {
local_stream = await navigator.mediaDevices.getUserMedia({audio: true});
} catch(error) {
console.log('Error accessing media devices', error);
}
local_stream.getTracks().forEach(track => pc.addTrack(track, local_stream));
if (is_caller){
pc.createOffer()
.then(created_description)
.catch(console.log);
}
}
function got_ice_candidate(event) {
if(event.candidate != null) {
socket.emit('ice', event.candidate);
}
}
function created_description(description){
pc.setLocalDescription(description)
.then(() => {socket.emit('sdp', pc.localDescription)})
.catch(console.log);
}
socket.on('ice', async (ice) => {
pc.addIceCandidate(new RTCIceCandidate(ice));
});
socket.on('sdp', async (sdp) => {
pc.setRemoteDescription(new RTCSessionDescription(sdp)).then(() => {
if (sdp.type == 'offer') {
pc.createAnswer()
.then(created_description)
.catch(console.log);
}
});
});
function got_remote_stream(event) {
console.log('got remote stream', remote_audio, event.streams[0]);
remote_audio.srcObject = event.streams[0];
}
</script>
</html>
Amir Arya is a new contributor to this site. Take care in asking for clarification, commenting, and answering.
Check out our Code of Conduct.