繁体   English   中英

如何通过 Django Channels 实现视频通话?

[英]How to implement video calls over Django Channels?

我想创建一个应用程序,使用户能够进行视频通话。 我在这里找到了一些见解,但不幸的是,答案既没有解释可以使用哪些第三方服务,也没有解释集成 WebRTC 的任何有意义的见解。

我已经设法使用 Channels 创建了一个基于 Django WebSocket 的实时聊天,并且我想到了“获取用户媒体”。 但我完全被 Peer2Peer 连接淹没了。

如何通过 Django Channels 集成 WebRTC? 或者我可以使用更简单的方法/第三方服务吗?

我的消费者.py:

from channels.generic.websocket import AsyncWebsocketConsumer
from channels.consumer import AsyncConsumer
import json

class ChatConsumer(AsyncWebsocketConsumer):
    async def connect(self):
        self.room_name = self.scope['url_route']['kwargs']['room_name']
        self.room_group_name = 'chat_%s' % self.room_name
        self.user = self.scope["user"].username

        # Join room group
        await self.channel_layer.group_add(
            self.room_group_name,
            self.channel_name
        )

        await self.accept()

    async def disconnect(self, close_code):
        # Leave room group
        await self.channel_layer.group_discard(
            self.room_group_name,
            self.channel_name
        )

    # Receive message from WebSocket
    async def receive(self, text_data):
        text_data_json = json.loads(text_data)
        message = text_data_json['message']
        user = text_data_json['user']

        # Send message to room group
        await self.channel_layer.group_send(
            self.room_group_name,
            {
                'type': 'chat_message',
                'message': message,
                'user': user
            }
        )

    # Receive message from room group
    async def chat_message(self, event):
        message = event['message'],
        user = event['user']

        # Send message to WebSocket
        await self.send(text_data=json.dumps({
            'message': message,
            'user': user
        }))

我的聊天室:

 {% extends 'main/header.html' %}

{% block content %}

<!-- chat/templates/chat/room.html -->
<!DOCTYPE html>

<body>

<div class="container">
    <textarea id="chat-log"  class="materialize-textarea" ></textarea><br/>

<div class="input-field col s12 ">
    <input id="chat-message-input" type="text" />
    <a class="waves-effect waves-light btn prefix" id="chat-message-submit"><i class="material-icons right">send</i></a>

</div>

</div>

</body>
<script>
    var roomName = "{{ room_name|escapejs }}";

    var chatSocket = new WebSocket(
        'ws://' + window.location.host +
        '/ws/chat/' + roomName + '/');

    chatSocket.onmessage = function(e) {
        var data = JSON.parse(e.data);
        console.info(e)
        var message = data['message'];
        var user = data['user'];
        document.querySelector('#chat-log').value += (user +": " + message + '\n');
        elem = document.getElementById("chat-log")
        M.textareaAutoResize(elem);
    };

    chatSocket.onclose = function(e) {
        console.error('Chat socket closed unexpectedly');
    };

    document.querySelector('#chat-message-input').focus();
    document.querySelector('#chat-message-input').onkeyup = function(e) {
        if (e.keyCode === 13) {  // enter, return
            document.querySelector('#chat-message-submit').click();
        }
    };

    document.querySelector('#chat-message-submit').onclick = function(e) {
        var messageInputDom = document.querySelector('#chat-message-input');
        var message = messageInputDom.value;
        var user = "{{user.username}}"
        chatSocket.send(JSON.stringify({
            'message': message,
            'user': user

        }));

        messageInputDom.value = '';
    };
</script>

{% endblock  %}

我的客户端.js:

window.onload = function () {
   var constraints = { audio: true, video: { width: 1280, height: 720 } }; 

navigator.mediaDevices.getUserMedia(constraints)
.then(function(mediaStream) {
var video = document.querySelector('video');
video.srcObject = mediaStream;
video.onloadedmetadata = function(e) {
video.play();
};
})
.catch(function(err) { console.log(err.name + ": " + err.message); });
};

我的视频窗口:

<html>
 {% load static %}
   <head> 
      <meta charset = "utf-8"> 
      <script src = "{% static 'main/js/client.js' %}"></script>
   </head>

   <body> 
      <video controls="" id = 'video-player' name = 'video-player' autoplay></video> 

   </body> 

</html> 

无需媒体传输的简单实时聊天应用程序可以仅使用WebSockets来实现,而实时媒体传输(音频、视频)则需要完全不同的协议。

所有现代浏览器都原生支持WebRTC ,可用于实时媒体传输。

虽然 webRTC 可用于传输媒体,但设备之间的握手必须在此之外发生。

尽管任何类型的 api/http 请求都可以实现,但 websockets 的实时数据传输能力还是不错的。

说了这么多,既然你已经选择了 django-channels,你可以用它来进行握手。

要建立 WebRTC 连接,客户端 A 需要使用其SDP (会话描述协议)生成报价并将其发送给客户端 B,客户端 B 必须将其 SDP 作为答复发回给客户端。

此时,两个客户端都将知道在传输数据时要使用哪些编解码器和编解码器参数。 然而,两个客户端都不知道或确定需要使用什么网络设置或数据本身需要如何传输。

这就是ICE (交互式连接建立)谈判出现的地方。 双方客户将来回发送从高到低的谈判,直到他们达成一致。 这就是媒体流开始流动的地方。

以上只是沧海一粟,但是,如果您遵循MDN关于信令和视频通话主题,不难得到一个工作原型。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM