You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Svelte+PeerJS视频通话应用连接失败:STUN/TURN超时问题

SvelteKit + PeerJS 视频通话无法连接,STUN/TURN 请求超时

我基于Svelte和PeerJS开发了一款小型视频通话应用,此前代码运行完全正常,但近期无法建立对等连接,控制台抛出明确错误:

ERROR PeerJS: Error: Could not connect to peer [ID]

查看WebRTC底层日志,发现核心问题是STUN绑定请求超时以及TURN分配请求超时。

我已经尝试了以下排查手段,但问题仍未解决:

  • 切换使用本地PeerJS服务器替代公共服务器
  • 逐行对比他人可正常运行的同类型项目代码
  • 在不同设备(手机、另一台PC)和不同网络(家庭WiFi、手机热点)下测试
  • 验证每次连接的用户ID唯一,无重复冲突
  • 检查localStorage中PeerID的加载逻辑,确认ID读取正常
  • 更换多个公开TURN服务器(包括Google的公共服务器)
  • 配置PeerJS关闭relay强制策略,尝试仅用直连模式

应用环境说明:本地开发为Windows 11 Pro下的SvelteKit项目,部署至Fly.io云平台后,故障现象完全一致。

前端Svelte组件核心代码

<script>
import Peer from 'peerjs';

let peer;
let remoteStream;
let localStream;

async function initPeer(userId) {
  peer = new Peer(userId, {
    host: import.meta.env.VITE_PEERJS_HOST,
    port: import.meta.env.VITE_PEERJS_PORT,
    path: '/peerjs',
    config: {
      iceServers: [
        { urls: 'stun:stun.l.google.com:19302' },
        {
          urls: 'turn:your-turn-server.com:3478',
          username: 'username',
          credential: 'password'
        }
      ]
    }
  });

  peer.on('open', (id) => {
    console.log('Peer ID:', id);
  });

  peer.on('call', async (call) => {
    localStream = await navigator.mediaDevices.getUserMedia({ video: true, audio: true });
    call.answer(localStream);
    call.on('stream', (stream) => {
      remoteStream = stream;
    });
  });

  async function startCall(targetId) {
    localStream = await navigator.mediaDevices.getUserMedia({ video: true, audio: true });
    const call = peer.call(targetId, localStream);
    call.on('stream', (stream) => {
      remoteStream = stream;
    });
    call.on('error', (err) => {
      console.error('Call error:', err);
    });
  }
}
</script>

<button on:click={() => initPeer('user1')}>初始化Peer</button>
<button on:click={() => startCall('user2')}>发起通话</button>
{#if localStream}
  <video autoplay playsinline bind:srcObject={localStream} />
{/if}
{#if remoteStream}
  <video autoplay playsinline bind:srcObject={remoteStream} />
{/if}

后端PeerJS服务器逻辑

const express = require('express');
const { ExpressPeerServer } = require('peer');

const app = express();
const server = app.listen(3001);

const peerServer = ExpressPeerServer(server, {
  debug: true,
  path: '/peerjs'
});

app.use('/peerjs', peerServer);

peerServer.on('connection', (client) => {
  console.log('Client connected:', client.id);
});

peerServer.on('disconnect', (client) => {
  console.log('Client disconnected:', client.id);
});

完整控制台错误日志

ERROR PeerJS:  Error: Could not connect to peer [user2]
    at Peer._onError (peerjs.min.js:1:22145)
    at RTCPeerConnection.<anonymous> (peerjs.min.js:1:27652)
WebRTC: ICE candidate failed: Error: STUN binding request timed out
WebRTC: ICE candidate failed: Error: TURN allocation request timed out

内容的提问来源于stack exchange,提问作者Joe

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.04 07:45:36