django - WebRTC 本地和远程描述已设置,但未设置数据通道
问题描述
我正在尝试使用 Django 和 WebRTC 制作视频通话应用程序
这是我的js代码
let video=document.getElementById('video')
let video_container=document.getElementById('video-container')
let video_btn=document.getElementById('video-btn')
let audio_btn=document.getElementById('audio-btn')
let join_btn=document.getElementById('username-btn')
let username_input=document.getElementById('username')
let username=""
//video
navigator.mediaDevices.getUserMedia({'video':true,'audio':true}).then(stream=>{
video.srcObject=stream
video.muted=true
var audiotrack = stream.getAudioTracks()
var videotrack = stream.getVideoTracks()
audiotrack[0].enabled=true
videotrack[0].enabled=true
video_btn.addEventListener('click',e=>{
videotrack[0].enabled=!videotrack[0].enabled
if(videotrack[0].enabled==true)video_btn.innerHTML="Turn Video off"
else video_btn.innerHTML="Turn Video On"
})
audio_btn.addEventListener('click',e=>{
audiotrack[0].enabled=!audiotrack[0].enabled
if(audiotrack[0].enabled==true)audio_btn.innerHTML="Turn audio off"
else audio_btn.innerHTML="Turn audio On"
})
})
//send signal
async function send_signal(user_name,action,etc){
data={
'username':user_name,
'action':action,
'etc':etc
}
await socket.send(JSON.stringify(data))
}
//add video for new peer
function add_video(user_name){
new_video=document.createElement('video')
new_video.autoplay=true
new_video.id="video-"+user_name
video_container.appendChild(new_video)
}
//send offer to specific channel
async function sendoffer(data){
lc =new RTCPeerConnection()
rc =lc.createDataChannel('channel')
await lc.createOffer().then(e=>lc.setLocalDescription(e))
await send_signal(user_name=username,action="new-offer",etc={'sdp':JSON.stringify(lc.localDescription),'channel':data['etc']['channel']})
rc.addEventListener('message',e=>console.log(e.data))
rc.addEventListener('open',e=>console.log('connection opened'))
}
//send Answer to all channels
async function sendanswer(data){
lc = new RTCPeerConnection()
lc.addEventListener("datachannel",ev=>{
console.log("data channel set")
lc.rc=ev.channel
})
await lc.setRemoteDescription(JSON.parse(data['etc']['sdp']))
await lc.createAnswer().then(e=>lc.setLocalDescription(e))
await send_signal(user_name=username,action="new-answer",etc={'sdp':JSON.stringify(lc.localDescription),'channel':data['etc']['channel']})
}
//set answer sdp to local connection
async function setanswer(data){
console.log("setting")
await lc.setRemoteDescription(JSON.parse(data['etc']['sdp']))
}
//Socket Handling
join_btn.addEventListener('click',e=>{
username=username_input.value
join_btn.disabled=true
username_input.disabled=true
socket = new WebSocket("ws://"+window.location.host+"/ws/")
socket.addEventListener('open',async e=>{
console.log("connection opened")
await send_signal(user_name=username,action="new-peer",etc={})
})
socket.addEventListener('close',e=>{
console.log("connection closed")
})
socket.addEventListener('error',e=>{
console.log("connection error")
})
socket.addEventListener('message',async e=>{
data= JSON.parse(e.data)
console.log("message" + e.data)
if(data['username']==username)return
else if (data['action']=='new-peer'){
console.log('new user added')
add_video(data['username'])
await sendoffer(data)
}
else if(data['action']=='new-offer'){
console.log('new offer added')
await sendanswer(data)
}
else if(data['action']=='new-answer'){
console.log('new answer added')
await setanswer(data)
}
})
})
Django 代码
from channels.generic.websocket import AsyncWebsocketConsumer
import json
class videochat(AsyncWebsocketConsumer):
async def connect(self):
self.room_group_name="test"
await self.channel_layer.group_add(
self.room_group_name,
self.channel_name
)
await self.accept()
async def disconnect(self,close_code):
await self.channel_layer.group_discard(
self.room_group_name,
self.channel_name
)
async def receive(self,text_data):
data=json.loads(text_data)
print(data)
data['etc']['channel']=self.channel_name
await self.channel_layer.group_send(
self.room_group_name,
{
'type':"send.sdp",
'data':data
}
)
async def send_sdp(self,event):
print("in_send")
await self.send(json.dumps(event['data']))
我还没有编码视频部分。请忽略视频代码部分。我想做的就是连接两个对等点。我使用 django 通道通过 websockets 发送 sdp。运行此代码后,对等点的本地描述和远程描述都已准确设置(我从开发人员控制台检查)。但“答案”对等方不运行该ondatachannel
方法。因此lc.rc
是undefined
。我在控制台上测试了 Webrtc 方法,它似乎可以工作,但是当我运行此代码时它不起作用。任何帮助,将不胜感激。谢谢你。
解决方案
嗨所以我解决了这个问题。第一个我不需要所有的异步和等待。其次,当调用冰候选时,我必须发送信号。
这是代码
let video=document.getElementById('video')
let video_container=document.getElementById('video-container')
let video_btn=document.getElementById('video-btn')
let audio_btn=document.getElementById('audio-btn')
let join_btn=document.getElementById('username-btn')
let username_input=document.getElementById('username')
let username=""
//video
navigator.mediaDevices.getUserMedia({'video':true,'audio':true}).then(stream=>{
video.srcObject=stream
video.muted=true
var audiotrack = stream.getAudioTracks()
var videotrack = stream.getVideoTracks()
audiotrack[0].enabled=true
videotrack[0].enabled=true
video_btn.addEventListener('click',e=>{
videotrack[0].enabled=!videotrack[0].enabled
if(videotrack[0].enabled==true)video_btn.innerHTML="Turn Video off"
else video_btn.innerHTML="Turn Video On"
})
audio_btn.addEventListener('click',e=>{
audiotrack[0].enabled=!audiotrack[0].enabled
if(audiotrack[0].enabled==true)audio_btn.innerHTML="Turn audio off"
else audio_btn.innerHTML="Turn audio On"
})
})
//send signal
function send_signal(user_name,action,etc){
data={
'username':user_name,
'action':action,
'etc':etc
}
socket.send(JSON.stringify(data))
}
//add video for new peer
function add_video(user_name){
new_video=document.createElement('video')
new_video.autoplay=true
new_video.id="video-"+user_name
video_container.appendChild(new_video)
}
//send offer to specific channel
function sendoffer(data){
lc =new RTCPeerConnection(null)
rc =lc.createDataChannel('channel')
lc.createOffer().then(e=>lc.setLocalDescription(e))
lc.addEventListener('icecandidate',(e)=>{
if(e.candidate)return
send_signal(user_name=username,action="new-offer",
etc={'sdp':JSON.stringify(lc.localDescription),
'channel':data['etc']['channel']})
})
rc.addEventListener('message',e=>console.log(e.data))
rc.addEventListener('open',e=>console.log('connection opened'))
}
//send Answer to all channels
function sendanswer(data){
lc = new RTCPeerConnection(null)
lc.ondatachannel=ev=>{
console.log("Invoked")
lc.rc=ev.channel
}
console.log(data)
lc.setRemoteDescription(JSON.parse(data['etc']['sdp']))
.then(()=>{lc.createAnswer()
.then(e=>lc.setLocalDescription(e))
})
lc.addEventListener('icecandidate',(e)=>{
if(e.candidate)return
send_signal(user_name=username,action="new-answer",
etc={'sdp':JSON.stringify(lc.localDescription),
'channel':data['etc']['channel']})
})
}
//set answer sdp to local connection
function setanswer(data){
console.log("setting")
lc.setRemoteDescription(JSON.parse(data['etc']['sdp']))
}
//Socket Handling
join_btn.addEventListener('click',e=>{
username=username_input.value
join_btn.disabled=true
username_input.disabled=true
socket = new WebSocket("ws://"+window.location.host+"/ws/")
socket.addEventListener('open',e=>{
console.log("websocket connection opened")
send_signal(user_name=username,action="new-peer",etc={})
})
socket.addEventListener('close',e=>{
console.log("connection closed")
})
socket.addEventListener('error',e=>{
console.log("connection error")
})
socket.addEventListener('message',e=>{
data= JSON.parse(e.data)
if(data['username']==username)return
else if (data['action']=='new-peer'){
console.log('new user added')
add_video(data['username'])
sendoffer(data)
}
else if(data['action']=='new-offer'){
console.log('new offer added')
sendanswer(data)
}
else if(data['action']=='new-answer'){
console.log('new answer added')
console.log(JSON.parse(data['etc']['sdp']))
setanswer(data)
}
})
})
谢谢我!!