使用js搭建简易的WebRTC实现视频直播

news2024/11/28 21:36:30
  1. 首先需要一个信令服务器,我们使用nodejs来搭建。两个端:发送端和接收端。
  2. 我的目录结构如下图:
  3. 流程
    1. 创建一个文件夹 WebRTC-Test。
    2. 进入文件夹中,新建一个node的文件夹。
    3. 使用终端并进入node的目录下,使用
      npm init

      创建package.json。

    4. 新建server.js,复制一下代码
      const app = require('express')();
      const wsInstance = require('express-ws')(app);
      
      const cors = require('cors');
      app.use(cors({ origin: 'http://localhost:3000' }));
      
      app.ws('/', ws => {
      	ws.on('message', data => {
      		// 未做业务处理,收到消息后直接广播
      		wsInstance.getWss().clients.forEach(server => {
      			if (server !== ws) {
      				server.send(data);
      				console.log(data,)
      			}
      		});
      	});
      });
      
      console.log("服务启动: http://localhost:8080");
      app.listen(8080, '0.0.0.0');
    5. 下载信令服务器的依赖。
      npm install express;
      npm install express-ws;
      npm install cors;
    6. 使用node server.js启动node的服务。
    7. 准备接收方的代码(receive.html)。
      <!DOCTYPE html>
      <html lang="zh-CN">
      
      <head>
          <meta charset="UTF-8">
          <meta http-equiv="X-UA-Compatible" content="IE=edge">
          <meta name="viewport" content="width=device-width, initial-scale=1.0">
          <meta http-equiv="Content-Security-Policy" content="upgrade-insecure-requests">
          <title>Receiver</title>
      </head>
      
      <body>
          <video autoplay id="remote"></video>
      </body>
      <script>
          const remoteVideo = document.querySelector('#remote')
      
          const socket = new WebSocket('ws://localhost:8080');
          socket.onopen = function () {
              console.log("Socket Success")
          }
          let buddy = new RTCPeerConnection()
      
      
          // 如果接收到对方的视频
          socket.onmessage = function (e) {
              const { type, sdp, iceCandidate } = JSON.parse(e.data)
              console.log(type)
              switch (type) {
                  case "offer":
                      buddy.setRemoteDescription(
                          new RTCSessionDescription({ type, sdp })
                      )
                      buddy.createAnswer().then(answer => {
                          buddy.setLocalDescription(answer)
                          socket.send(JSON.stringify(answer))
                      })
                      break;
      
                  case "offer_ice":
                      buddy.addIceCandidate(iceCandidate)
                      break;
      
                  default:
                      break;
              }
          }
      
          buddy.ontrack = function (e) {
              remote.srcObject = e.streams[0]
          }
      
          buddy.onicecandidate = function (e) {
              if (e.candidate) {
                  socket.send(JSON.stringify({
                      type: "answer_ice",
                      iceCandidate: e.candidate
                  }))
              }
          }
      
      </script>
      
      </html>
    8. 准备发送方的代码(send.html)。
      <!DOCTYPE html>
      <html lang="zh-CN">
      
      <head>
          <meta charset="UTF-8">
          <meta http-equiv="X-UA-Compatible" content="IE=edge">
          <meta name="viewport" content="width=device-width, initial-scale=1.0">
          <meta http-equiv="Content-Security-Policy" content="upgrade-insecure-requests">
          <title>Send</title>
      </head>
      
      <body>
          <script>
              const socket = new WebSocket('ws://localhost:8080');
              socket.onopen = function () {
                  console.log("Socket Success")
              }
              let peer = new RTCPeerConnection()
      
              navigator.mediaDevices.getUserMedia({
                  video: true,
                  audio: true
              }).then(stream => {
                  stream.getTracks().forEach(track => {
                      peer.addTrack(track, stream);
                  })
      
                  peer.createOffer().then(offer => {
                      peer.setLocalDescription(offer);
                      socket.send(JSON.stringify(offer));
                  })
              })
      
              peer.onicecandidate = function (e) {
                  if (e.candidate) {
                      socket.send(JSON.stringify({
                          type: "offer_ice",
                          iceCandidate: e.candidate
                      }))
                  }
              }
      
              // 如果接收到对方的视频
              socket.onmessage = function (e) {
                  const { type, sdp, iceCandidate } = JSON.parse(e.data)
                  console.log(type)
                  switch (type) {
                      case "answer":
                          peer.setRemoteDescription(
                              new RTCSessionDescription({ type, sdp })
                          )
                          break;
      
                      case "answer_ice":
                          peer.addIceCandidate(iceCandidate)
                          break;
      
                      default:
                          break;
                  }
              }
          </script>
      </body>
      
      </html>
    9. 使用vscode的插件live server启动两个html文件。
      下载live server插件。

      启动live server。

      启动后两个端口号。


    10. 等全部启动后,查看接收端的页面,要等一段时间,可以看到摄像头拍到的画面。
      接受端播放不了,在浏览器控制台中输入 remoteVideo.play() 就行
       

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

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

相关文章

易基因:MeRIP-seq等揭示mRNA m6A甲基化调控拟南芥的抗寒性分子机制|植物抗逆

大家好&#xff0c;这里是专注表观组学十余年&#xff0c;领跑多组学科研服务的易基因。 植物通过改变数千个基因的mRNA丰度以促进其生理和代谢过程&#xff0c;从而对低温应激进行响应。在转录后水平上&#xff0c;这些冷应激应答转录本经历可变剪接、microRNA介导的调控和可…

气象站的工作内容有哪些?

气象站的工作内容包括观测、记录和报告天气数据。具体来说&#xff0c;气象站需要通过各种传感器和数据记录器来测量和记录气温、湿度、风速、风向、气压、降雨量、雪深等气象参数&#xff0c;对数据的分析、处理和存储。例如&#xff0c;气象站需要将收集到的数据与历史数据进…

Redis设置开机自启动

&#xff08;配置环境变量&#xff09;需要重启电脑 1、在安装目录打开命令行&#xff0c;输入&#xff1a;打开一个命令窗进入文件夹内&#xff0c;输入redis-server --service-install redis.windows-service.conf 2、windowsR ---->services.msc 找到Redis&#xff0c;右…

【好书推荐】人月神话

《人月神话》一书被评为神品之作&#xff0c;以其深入的思想和优美的文字而享誉于软件工程领域。该书由Frederick P. Brooks撰写于28年前&#xff0c;探讨了软件工程领域的现实问题&#xff0c;揭示了软件行业在解决问题上存在的错误方案和缺乏专业性的现象。 在这本书中&…

独立站新手引流,谷歌SEO工具汇总

俗话说“工欲善其事&#xff0c;必先利其器”&#xff0c;做谷歌SEO也一样&#xff0c;要想做好并提升SEO效果&#xff0c;卖家就需要了解并利用好SEO工具。那我们今天就来盘点一下&#xff0c;常用的SEO工具有哪些吧~ 网站检测工具 1、PageSpeed Insights&#xff1a;这是谷…

Python足球训练打卡系统SpringBoot足球场地预约系统源码 调试 lw

&#x1f495;&#x1f495;作者&#xff1a;计算机源码社 &#x1f495;&#x1f495;个人简介&#xff1a;本人七年开发经验&#xff0c;擅长Java、Python、PHP、.NET、微信小程序、爬虫、大数据等&#xff0c;大家有这一块的问题可以一起交流&#xff01; &#x1f495;&…

财报解读:德尔玛净利润同比增长10.79%,自研将延续增长态势?

高成长性的小家电领域&#xff0c;近年来已成为家电行业的热门赛道。数据显示&#xff0c;我国小家电行业未来将保持6%-7%左右增速&#xff0c;预计2026年市场规模将接近6000亿元。在庞大的市场机遇中&#xff0c;德尔玛等后起之秀也频频迎来投资者关注。 从进行品牌设计&…

图片转pdf软件有哪些?这几款收藏下来

图片转pdf软件有哪些&#xff1f;图片转PDF的需求很常见。有时候我们需要将一些图片文件合并成一个PDF文件&#xff0c;方便浏览和共享。比如说&#xff0c;你可能需要将一份报告或者简历的图片转换成PDF文件&#xff0c;以便于分享给其他人。此外&#xff0c;将图片转换成PDF文…

计算机网络自顶向下-web页面请求历程

1. 准备: DHCP、 UDP、 IP 和以太网 假定 Bob 启动他的便携机&#xff0c;然后将其用一根以太网电缆连接到学校的以太网交换机 &#xff0c; 交换机与学校的路由器相连。学校的路由器与一个 ISP 连接&#xff0c; 本例中 ISP 为 comcast.net &#xff0c;为学校提供了 DNS 服务…

0010Java程序设计-springboot+vue影院售票系统设计与实现

摘 要目 录系统实现开发环境 摘 要 看电影已经成为了人们生活中不可缺少的一部分&#xff0c;电影院售票及管理系统是电影院的日常管理及售票任务的核心&#xff0c; 在电影院中&#xff0c; 工作人员并非只是放映电影&#xff0c; 还有诸如票房统计、影片放映、影片场次安排、…

TypeScrip第一课

前言 TypeScript是一个开源的、渐进式包含类型的JavaScript超集。 作用是让开发者增强js的能力并使应用的规模扩展变得更容易。 这两点是废话&#xff0c;至于什么是超集&#xff1f; S1是S2的子集。S2是S1的超集&#xff08;类似于扩展extend&#xff09; TS基于ES6为 …

0401hive入门-hadoop-大数据学习.md

文章目录 1 Hive概述2 Hive部署2.1 规划2.2 安装软件 3 Hive体验4 Hive客户端4.1 HiveServer2 服务4.2 DataGrip 5 问题集5.1 Could not open client transport with JDBC Uri 结语 1 Hive概述 Apache Hive是一个开源的数据仓库查询和分析工具&#xff0c;最初由Facebook开发&…

elasticsearch的搜索补全提示

当用户在搜索框输入字符时&#xff0c;我们应该提示出与该字符有关的搜索项 拼音分词器 下载 要实现根据字母做补全&#xff0c;就必须对文档按照拼音分词&#xff0c;GitHub上有拼音分词插件 GitHub - medcl/elasticsearch-analysis-pinyin: This Pinyin Analysis plugin…

儿童玩具音乐芯片方案,6通道midi播放语音芯片,WT588F02B-8S

随着科技的不断进步&#xff0c;儿童玩具行业也在不断演化。如今&#xff0c;儿童们期待的不仅仅是有趣的外观&#xff0c;还有令人惊叹的音乐和声音效果。为了满足这一需求&#xff0c;深圳唯创知音研发了WT588F02B-8S&#xff0c;一款创新的6通道MIDI播放语音芯片&#xff0c…

手写Mybatis:第18章-一级缓存

文章目录 一、目标&#xff1a;一级缓存二、设计&#xff1a;一级缓存三、实现&#xff1a;一级缓存3.1 工程结构3.2 一级缓存类图3.3 一级缓存实现3.3.1 定义缓存接口3.3.2 实现缓存接口3.3.3 创建缓存KEY3.3.4 NULL值缓存key 3.4 定义缓存机制、占位符和修改配置文件3.4.1 定…

Jrebel与Xrebel教学

简介 JRebel和XRebel是两个非常有用的工具&#xff0c;可以显著提升Java开发人员的生产力和应用程序性能。 JRebel是一个强大的Java开发工具&#xff0c;它允许开发人员在不重新启动应用程序的情况下进行代码修改和调试。传统上&#xff0c;每次修改Java代码都需要重新编译和重…

bat批处理——统计当前文件夹下的所有文件名

一、在当前文件夹下建立XX.txt文件&#xff0c;将指令dir *.* /b/s>test.txt写到XX.txt文件中 测试文件夹目录及文件结构图&#xff1a; 指令说明&#xff1a; dir *.* /b/s>test.txt /*** 此部分为注释内容* dir 获取当前目录下的目录及文件* *.* 对文件进行筛选&…

ShopXO商城系统文件上传0Day代审历程

Git仓库&#xff1a; https://github.com/gongfuxiang/shopxo简介&#xff1a; 两天攻防中&#xff0c;某政局内网横向发现多网段服务器&#xff0c;该服务器搭建了ShopXO商城系统(后来发现是开发临时搭建的&#xff0c;准备做二开用的)。结果花了30来秒审了个垃圾Day拿下该服…

应用于激光雷达、 激光测距、 脉冲测量的高精度时间测量(TDC)电路MS1205N

MS1205N 是一款高精度时间测量 (TDC) 电路&#xff0c;具有四通 道、多脉冲的采样能力、高速 SPI 通讯、多种测量模式&#xff0c;适合 于激光雷达和激光测距。 主要特点 ◼ 单精度模式 60ps ◼ 双精度模式 30ps ◼ 非校准测量范围 3.5ns(0ns) 至 25μs ◼ 单…

【LeetCode】202. 快乐数 - hash表 / 快慢指针

目录 2023-9-5 09:56:15 202. 快乐数 2023-9-5 09:56:15 关键是怎么去判断循环&#xff1a; hash表&#xff1a; 每次生成链中的下一个数字时&#xff0c;我们都会检查它是否已经在哈希集合中。 如果它不在哈希集合中&#xff0c;我们应该添加它。如果它在哈希集合中&#x…