webrtc-m79-测试peerconnectionserver的webclient-p2p-demo

news2024/11/17 22:31:19

1 背景

webrtc的代码中有peerconnectionclient和peerconnectionserver的例子,但是没有对应的web端的例子,这里简单的写了一个测试例子,具体如下:

2 具体操作

2.1 操作流程

2.2 测试效果

使用webclient与peerconnectionclient的测试效果如下:

3 前端代码

<html>
<head>
    <title>webclient p2p demo</title>
    <meta charset="utf-8">
    <style>
        .left_part {
            width: 50%;
            float: left;
        }
        .right_part {
            width: 50%;
            float: right;
            overflow-y: scroll;
        }
    </style>

    <script src="https://code.jquery.com/jquery-3.6.0.min.js"></script>
</head>

<body>
    <div class="right_part" id="left_part_container">
        <div>
            SignalServer:
            <input type="text" id="signal_url" value="127.0.0.1:8888">
            <button id="btn_sign_in">登入</button>
            <button id="btn_sign_out">登出</button><br>

            <input type="text" id="selected_peerid_for_p2p" disabled value="不允许修改的文本">
            <button id="btn_start_p2p" disabled>start_p2p</button>
        </div>
        <br>

        <table id="PeersTable">
            <thead>
                <tr>
                    <th>Name</th>
                    <th>PeerId</th>
                    <th>Status</th>
                </tr>
            </thead>
        </table>
    </div>

    <div class="left_part" id="left_part_container">
        <video controls autoplay id="rtc_video_play" height="500" style="width:100%"></video>
    </div>

    <script type="text/javascript">
        var myselfPeerId = -1;
        var pc = new RTCPeerConnection({ "offerExtmapAllowMixed": false });
        var datachannel = null;
        var stream = new MediaStream();

        async function initPC() {
            pc.addTransceiver("audio", {direction: "recvonly"});
            pc.addTransceiver("video", {direction: "recvonly"});

            pc.onconnectionstatechange = function(event){
                console.log("connection state change: ", pc.connectionState);
            };
            
            pc.onicecandidate = async (ev) => {
                console.log('=======>' + JSON.stringify(ev.candidate));        
            };

            pc.ontrack = function(event) {
                stream.addTrack(event.track);                         
            };
            
            datachannel = pc.createDataChannel('chat');

            datachannel.onopen = function(event) {
                console.log("datachannel onopen: ", event.data);
            }

            datachannel.onmessage = function(event) {
              console.log("receive message: ", event.data);
            }

            datachannel.onerror = function(event) {
              console.log("datachannel error: ", event.data);
            }

            datachannel.onclose = function(event) {
              console.log("datachannel close: ");
            }                    
        }


        async function startP2P(signal_url) {
            initPC();

            var offer = await pc.createOffer();
            await pc.setLocalDescription(offer);

            let sendOfferPromise = await fetch(signal_url, {
                "method": "POST",
                "body": JSON.stringify(offer)
            });

            if (sendOfferPromise.ok) {
                console.log("send offer: " + JSON.stringify(offer));                         
            } else {
                alert("HTTP-Error: " + sendOfferPromise.status);
            }               
        }   

        async function nfyFromSignal(nfyPromise) {
            let nfyString = await nfyPromise.text();
            if (nfyString.includes("answer")) {
                console.log("receive answer: " + nfyString);
                pc.setRemoteDescription(new RTCSessionDescription(JSON.parse(nfyString)));
            } else if (nfyString.includes("candidate")) {
                console.log("receive candidate: " + nfyString);
                pc.addIceCandidate(new RTCIceCandidate(JSON.parse(nfyString)));
            } else {
                let peersString = nfyString;
                // console.log("rsp: ", peersString)
                let peersChunk = peersString.split("\n");
                for (let i=0; i<peersChunk.length && peersChunk[i].length>0; ++i) {
                  const peerColumns = peersChunk[i].split(",");
                  // console.log("index: " + i + ", data: " + peerColumns)

                  // for example: kevin@home-pc,36,1
                  // peerColumns[0]: peer_name
                  // peerColumns[1]: peer_id
                  // peerColumns[2]: peer_status
                  // table's column index starts from 1, not 0
                  const row_find_peer_id = $("#PeersTable tr:has(td:nth-child(2):contains('" + peerColumns[1] + "'))");
                  if (row_find_peer_id.length > 0) {
                    console.log("peerid:" + peerColumns[1] + ", status change from " + row_find_peer_id.find('td:nth-child(3)').text() + " to " + peerColumns[2]);
                    row_find_peer_id.find('td:nth-child(3)').text(peerColumns[2]);
                    continue;
                  }

                  const row_find_peer_name = $("#PeersTable tr:has(td:nth-child(1):contains('" + peerColumns[0] + "'))");
                  if (row_find_peer_name.length > 0) {
                    console.log("peerid:" + peerColumns[1] + ", status change from " + row_find_peer_name.find('td:nth-child(3)').text() + " to " + peerColumns[2]);
                    row_find_peer_name.find('td:nth-child(2)').text(peerColumns[1]);
                    row_find_peer_name.find('td:nth-child(3)').text(peerColumns[2]);
                    continue;
                  }                  

                  const row_peer = $("<tr>");
                  row_peer.append($("<td>").text(peerColumns[0]));
                  row_peer.append($("<td>").text(peerColumns[1]));
                  row_peer.append($("<td>").text(peerColumns[2]));
                  $("#PeersTable").append(row_peer);
                }                
            }
        }

        async function pendingWait(myself_peerid) {
            const signal_url = document.getElementById("signal_url").value;
            while (true) {
                let v = await fetch(`http://${signal_url}/wait?peer_id=${myself_peerid}`);
                nfyFromSignal(v);
            }
        }

        $('#btn_sign_in').on('click', async () => {
            const signal_url = document.getElementById("signal_url").value;
            let signinResultPromise = await fetch(`http://${signal_url}/sign_in`);
            if (signinResultPromise.ok) {
                myselfPeerId = parseInt(signinResultPromise.headers.get("Pragma"));
                console.log("my peerid is: " + myselfPeerId);
                nfyFromSignal(signinResultPromise);
                pendingWait(myselfPeerId);               
            } else {
                alert("HTTP-Error: " + signinResultPromise.status);
            }
        })        

        $('#btn_sign_out').on('click', async () => {
            $("#PeersTable tbody").empty();
            const signal_url = document.getElementById("signal_url").value;
            let signoutResultPromise = await fetch(`http://${signal_url}/sign_out?peer_id=${myselfPeerId}`);
            if (signoutResultPromise.ok) {
                console.log("sign_out: " + myselfPeerId + " successful");       
            } else {
                alert("HTTP-Error: " + signoutResultPromise.status);
            }
        })

        $('#PeersTable').on('click', 'tr', function() {
            const row_selected = $(this);
            const row_selected_peer_id = parseInt(row_selected.find('td:nth-child(2)').text());
            
            if (row_selected_peer_id === myselfPeerId) {
                console.log("You should not choose yourself [" + myselfPeerId + "] to start p2p");
                $("#btn_start_p2p").prop("disabled", true);
                return;
            }

            const row_selected_peer_id_status = parseInt(row_selected.find('td:nth-child(3)').text());
            if (row_selected_peer_id_status === 1) {
                console.log("selected peerid: " + row_selected_peer_id);
                $('#selected_peerid_for_p2p').val(row_selected_peer_id);
                $("#btn_start_p2p").prop("disabled", false);                
            } else {
                console.log("The peer [" + row_selected_peer_id + "] you choose is offline");
                $("#btn_start_p2p").prop("disabled", true);
            }
        })

        $('#btn_start_p2p').on('click', async () => {
            const signal_url = document.getElementById("signal_url").value;
            const remote_peer_id = $('#selected_peerid_for_p2p').val();
            const sendmsg_url = `http://${signal_url}/message?peer_id=${myselfPeerId}&to=${remote_peer_id}`;
            console.log("sendmsg url: " + sendmsg_url);

            // $('#rtc_video_play').show();
            // $('#rtc_video_play').prop('muted', false);
            $('#rtc_video_play').prop('srcObject', stream);

            console.log("Start P2P from [" + myselfPeerId + "] to [" + remote_peer_id + "]");
            startP2P(sendmsg_url);
        })

    </script>
</body>
</html>

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1001821.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

Windows安装MySQL8.0完整教程

很多朋友在安装MySQL的时候&#xff0c;总会遇到各种各样的问题。本文来教你怎样正确安装MySQL。 一、 下载MySQL 如果已经下载好了可以忽略&#xff0c;我下面提供两个版本的下载链接 阿里云盘 夸克云盘 链接&#xff1a;https://pan.quark.cn/s/1894623c2e6a 提取码&…

Go入门教程

什么是Go语言&#xff1f; Go&#xff08;又称 Golang&#xff09;是 Google 的 Robert Griesemer&#xff0c;Rob Pike 及 Ken Thompson 开发的一种静态强类型、编译型语言。Go 语言语法与 C 相近&#xff0c;但功能上有&#xff1a;内存安全&#xff0c;GC&#xff08;垃圾回…

BGP感想

BGP 边界网关协议 属于外部或域间路由协议&#xff0c;距离矢量路由协议。 AS(自治系统)&#xff0c;在一个自治系统内运行osfp,is-is,rip,vlan等,实现AS内网络互通。 BGP做什么&#xff0c;为处于不同自治系统&#xff08;AS&#xff09;中的路由器之间进行“路由信息通信…

视频推流测试——使用ffmpeg进行推流生成rtsp视频流

在我们完成开发工作之后,需要通过推流的形式来验证能否正确接收视频流,并送入视频检测程序。笔者在这里使用的是业内最为常用的ffmpeg。具体方法如下。 1、安装ffmpeg 访问ffmpeg的官网,地址为https://ffmpeg.org/download.html,按照如下途中来选择下载。 下载完成后,会…

LeetCode(力扣)53. 最大子数组和Python

LeetCode53. 最大子数组和 题目链接代码 题目链接 https://leetcode.cn/problems/maximum-subarray/ 代码 class Solution:def maxSubArray(self, nums: List[int]) -> int:result float(-inf)count 0for i in range(len(nums)):count nums[i]if count > result:res…

华为云云耀云服务器L实例评测|华为云云耀云服务器docker部署srs并调优,可使用webrtc与rtmp

华为云云耀云服务器L实例评测&#xff5c;华为云云耀云服务器docker部署srs并调优&#xff0c;可使用webrtc与rtmp 什么是华为云云耀云L实例 云耀云服务器L实例&#xff0c;面向初创企业和开发者打造的全新轻量应用云服务器。提供丰富严选的应用镜像&#xff0c;实现应用一键…

BUUCTF Reverse/[2019红帽杯]childRE

查看信息 分析代码 int __cdecl main(int argc, const char **argv, const char **envp) {__int64 v3; // rax_QWORD *v4; // raxconst CHAR *v5; // r11__int64 v6; // r10int v7; // er9const CHAR *v8; // r10__int64 v9; // rcx__int64 v10; // raxunsigned int v12; // ec…

基于人工智能与边缘计算Aidlux的工业表面缺陷检测

一&#xff1a;训练yolov8得到onnx模型&#xff08;相关教程有很多&#xff09; 二&#xff1a;模型转化&#xff1a; 网站&#xff1a; https://aimo.aidlux.com/ 输入试用账号和密码: 账号:AIMOTC001&#xff0c;密码:AIMOTC001 我们选择 TensorFlowLite 一步步完成转化 …

自然语言处理应用(二):自然语言推断

自然语言推断 自然语言推断&#xff08;Natural Language Inference&#xff09;是指通过对自然语言文本进行逻辑推理和推断&#xff0c;判断两个句子之间的关系&#xff0c;通常包括三种关系&#xff1a;蕴含&#xff08;entailment&#xff09;、矛盾&#xff08;contradict…

Java通过http请求的方式调用他人的接口

本功能的实现&#xff0c;去不参数于这篇博客&#xff0c;给这位大神点赞 基于Spring Boot使用Java调用http请求的6种方式 文章目录 业务背景第一步&#xff0c;配置url第二步&#xff0c;封装请求体&#xff0c;RequestBody第三步&#xff0c;使用HttpURLConnection调用服务…

机器学习(8)---数据预处理

文章目录 一、数据预处理1.1 数据无量纲化1.2 数据归一化1.3 数据标准化1.4 处理选择 二、缺失值2.1 填补的类和参数2.2 用Pandas和Numpy进行填补 三、处理分类型特征&#xff1a;编码与哑变量3.1 编码3.2 哑变量&#xff08;独热编码&#xff09; 一、数据预处理 1.1 数据无量…

【java】【SSM框架系列】【二】SpringMVC

目录 一、SpringMVC简介 1.1 SpringMVC概述 1.2 入门案例 1.3 入门案例工作流程分析 1.4 Conrtoller加载控制与业务BEAN加载控制 1.5 PostMan 二、请求与响应 2.1 请求映射路径 2.2 请求参数 2.2.1 Get 2.2.2 Post 2.2.3 SpringMVC解决post请求中文乱码处理 2.2.4 …

有效回文字符串(Valid palindrome)

题目描述 思路分析 代码实践 java: public class Solutation1 {//定义一个方法&#xff0c;判断是否是有效数字或者字母private static boolean isValid(char c) {//如果不是字母或者数字&#xff0c;那就返回一个flase//这里调用了Character类里面的方法return Character.i…

openwrt开启SSH远程访问与开启WEB远程访问——三种方法

openwrt 开启SSH远程访问 首先&#xff0c;你的电脑用网线连接路由器LAN口是可以访问WEB页面和SSH连接的。 例如&#xff0c;电脑1连接Openwrt路由器&#xff0c;可以进行SSH连接到openwrt 路由器。但是电脑2无法远程访问Openwrt路由器网页和SSH远程连接。 本次操作固件版本…

前端面试题JS篇(5)

如何判断一个对象是空对象 1、使用 JSON 自带的stringify方法判断 let obj{}; console.log(JSON.stringify(obj)"{}"); 2、使用 ES6 新增的方法 Object.keys()来判断 Object.keys(obj).length0 如果 new 一个箭头函数的会怎么样 箭头函数是ES6中的提出来的&…

python main 函数-启动-传递参数 python 打包 exe C# 进程传参

Part1:Python main 传递参数 在Python编程中&#xff0c;我们经常需要从命令行或其他外部环境中获取参数。Python提供了一种简单而灵活的方式来处理这些参数&#xff0c;即通过main函数传参 1.python main 函数-启动-传递参数 test.py import sysdef main():# 获取命令行参…

代码随想录算法训练营day48|打家劫舍 |198.打家劫舍|213.打家劫舍II|337.打家劫舍 III

198.打家劫舍 力扣题目链接 你是一个专业的小偷&#xff0c;计划偷窃沿街的房屋。每间房内都藏有一定的现金&#xff0c;影响你偷窃的唯一制约因素就是相邻的房屋装有相互连通的防盗系统&#xff0c;如果两间相邻的房屋在同一晚上被小偷闯入&#xff0c;系统会自动报警。 给…

Pytorch intermediate(三) BiLSTM

Bi-directional Long Short-Term Memory&#xff0c;双向LSTM网络。 有些时候预测可能需要由前面若干输入和后面若干输入共同决定&#xff0c;这样会更加准确。因此提出了双向循环神经网络&#xff0c;网络结构如上图。 构建LSTM模型时&#xff0c;在参数中添加bidirectionalTr…

面试半个月后的一些想法

源于半个月面试经历后的一些想法&#xff0c;刚开始想的是随便写写&#xff0c;没想到居然写了这么多。 找不到目标找不到意义亦或是烦躁的时候&#xff0c;就写写文章吧&#xff0c;把那些困扰你很久的问题铺开来 花时间仔细想想&#xff0c;其实真正让我们生气懊恼&#xff0…

轻松搭建本地知识库的ChatGLM2-6B

近期发现了一个项目&#xff0c;它的前身是ChatGLM&#xff0c;在我之前的博客中有关于ChatGLM的部署过程&#xff0c;本项目在前者基础上进行了优化&#xff0c;可以基于当前主流的LLM模型和庞大的知识库&#xff0c;实现本地部署自己的ChatGPT&#xff0c;并可结合自己的知识…