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

  1. 首先需要一个信令服务器,我们使用nodejs来搭建。两个端:发送端和接收端。
  2. 我的目录结构如下图:
  3. 流程
    1. 创建一个文件夹 WebRTC-Test。

    2. 进入文件夹中,新建一个node的文件夹。

    3. 使用终端并进入node的目录下,使用

      复制代码
      npm init

      创建package.json。

    4. 新建server.js,复制一下代码

      javascript 复制代码
      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. 下载信令服务器的依赖。

      javascript 复制代码
      npm install express;
      npm install express-ws;
      npm install cors;
    6. 使用node server.js启动node的服务。

    7. 准备接收方的代码(receive.html)。

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

      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() 就行

相关推荐
汪子熙2 小时前
浏览器环境中 window.eval(vOnInit); // csp-ignore-legacy-api 的技术解析与实践意义
前端·javascript
BUG收容所所长3 小时前
🤖 零基础构建本地AI对话机器人:Ollama+React实战指南
前端·javascript·llm
小高0073 小时前
🚀前端异步编程:Promise vs Async/Await,实战对比与应用
前端·javascript·面试
Spider_Man3 小时前
"压"你没商量:性能优化的隐藏彩蛋
javascript·性能优化·node.js
用户87612829073743 小时前
对于通用组件如何获取表单输入,区分表单类型的试验
前端·javascript
Bdygsl3 小时前
前端开发:JavaScript(6)—— 对象
开发语言·javascript·ecmascript
Mintopia4 小时前
AIGC Claude(Anthropic)接入与应用实战:从字节流到智能交互的奇妙旅程
前端·javascript·aigc
Mintopia4 小时前
Next.js 样式魔法指南:CSS Modules 与 Tailwind CSS 实战
前端·javascript·next.js
kfepiza5 小时前
JavaScript的 async , await 笔记250808
javascript
国家不保护废物5 小时前
跨域问题:从同源策略到JSONP、CORS实战,前端必知必会
前端·javascript·面试