首页 > 解决方案 > 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.rcundefined。我在控制台上测试了 Webrtc 方法,它似乎可以工作,但是当我运行此代码时它不起作用。任何帮助,将不胜感激。谢谢你。

标签: django

解决方案


嗨所以我解决了这个问题。第一个我不需要所有的异步和等待。其次,当调用冰候选时,我必须发送信号。

这是代码


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)
    } 
    })  
})

谢谢我!!


推荐阅读