我基于PeerJS搭建了一个P2P视频软件

一个拖了很久的待办

“玩一玩WebRTC” 在我的待办清单里躺了大概一年,因为这事有趣,但是项目太多无法抽身,最近vibe coding大行其道,这种小demo的项目,可以快速实现,大概花了2天时间实现了这个旧项目:Peertest

WebRTC、PeerJS、视频通话的关系

在聊实现之前,先理清这几个概念的关系。

WebRTC:底层的通信协议

WebRTC (Web Real-Time Communication) 是浏览器原生的实时通信 API。它可以让两个浏览器直接传输音视频数据。

WebRTC 只负责"传输",不负责"建立连接"。

打个比方,WebRTC 就像是两个人打电话的”通话线路”,但在此之前,你们得先交换电话号码。这个”交换号码”的过程,叫信令(Signaling)

信令服务器:连接的桥梁

两个浏览器要建立 WebRTC 连接,需要先交换一些信息:

  • 谁是发起方、谁是接收方
  • 各自支持什么编码格式
  • 如何穿透 NAT(IP 地址和端口)

这些信息需要通过一个中间服务器来传递,这就是信令服务器。

而这就是 PeerJS 存在的意义。

它帮你:

  • 处理好了信令握手
  • 封装了复杂的 WebRTC API
  • 提供了现成的 PeerServer
  • 用简单的 peer.call() 就能发起通话

原本需要几百行代码的 WebRTC 连接,用 PeerJS 几行就能搞定。

所以关系是这样的:

1
2
3
4
5
视频通话应用

PeerJS (封装层)

WebRTC (通信协议) + PeerServer (信令服务)

我的选型

前端:React + TypeScript + Vite

选择 React 是因为熟悉,TypeScript 是为了类型安全,Vite 则是因为开发体验好(真的很快)。

整个应用只有一个 App.tsx 组件,单组件架构。我觉得这个规模的项目,没必要过度设计。

核心设计:主叫方(房间建立者)和被叫方(加入房间这)

建立房间模式

1
2
3
4
用户点击"建立房间"
→ 连接 PeerServer,获取 6 位数字房间号
→ 生成分享链接 http://host:port/#123456
→ 等待对方来电

加入房间模式

1
2
3
用户粘贴分享链接,点击"呼叫"
→ 自动连接 PeerServer
→ 同时发起 WebRTC 呼叫

单组件的状态管理

没有用 Redux、Zustand 任何状态库,纯 React hooks:

1
2
3
const [mode, setMode] = useState<'join' | 'create'>('join')
const [connectionStatus, setConnectionStatus] = useState<'disconnected' | 'connecting' | 'connected'>('disconnected')
const [callStatus, setCallStatus] = useState<'idle' | 'calling' | 'incall'>('idle')

我觉得这就是”刚刚好”的复杂度——再多就是过度设计。

服务器架构

两个独立的服务:

  1. PeerServer (peer-server.js):Node.js 写的信令服务器,端口 9009
  2. Vite Dev Server:前端开发服务器

配置 host: '0.0.0.0' 是为了支持局域网访问——这样我的手机可以和电脑互相通话。

一个小细节:6 位数字房间号

我用了随机生成 6 位数字作为房间 ID:

1
2
3
const generateRoomId = (): string => {
return Math.floor(100000 + Math.random() * 900000).toString()
}

为什么不用 UUID?因为数字好记、好输入,特别是手机端粘贴链接时体验更好。

摄像头控制

每个视频框都有独立的开关:

  • 本地摄像头:真实开启/关闭 MediaStream
  • 远程显示:只切换可见度(opacity 0.3-1.0)

本地视频加了镜像翻转 transform: scaleX(-1),不然看着自己的视频会很别扭。

技术栈总结

层级 技术
前端框架 React 19 + TypeScript
构建工具 Vite
WebRTC 封装 PeerJS 1.5.5
信令服务器 PeerServer (peer 包)
状态管理 React hooks

再见

写到这里,代码已经能跑了。两个浏览器窗口可以互相通话,画质清晰,延迟低。

这个项目不大,但填补了我对 WebRTC 的认知空白。

对了,代码在 Gitee,欢迎 star。


再见,下一个待办见。

作者

简单代码

发布于

2026-01-17

更新于

2026-01-17

许可协议