首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
您现在的位置: 程式碼之家 >> 編程語言 >  >> 更多程式語言 >> 程式設計綜合問答

WebRTC 實現網頁視頻通話完整教程:信令、ICE、SDF、TURNS 服務器部署與前端代碼

     編輯:程式設計綜合問答

WebRTC 核心流程

獲取媒體流 → 創建 PeerConnection → 生成 Offer/Answer (SDP) → 信令交換 → ICE Candidate 交換 → 建立 P2P 連接 → 媒體傳輸

關鍵基礎設施

最小可行前端代碼 (原生 JS, 無框架)







// app.js
const config = {
    iceServers: [
        { urls: 'stun:stun.l.google.com:19302' },
        { urls: 'turn:turn.example.com:3478?transport=udp', username: 'user', credential: 'pass' }
    ]
};
const pc = new RTCPeerConnection(config);
const localVideo = document.getElementById('localVideo');
const remoteVideo = document.getElementById('remoteVideo');
const signaling = new WebSocket('wss://signal.example.com');

// 1. 獲取本地媒體流
navigator.mediaDevices.getUserMedia({ video: true, audio: true })
    .then(stream => {
        localVideo.srcObject = stream;
        stream.getTracks().forEach(track => pc.addTrack(track, stream));
    })
    .catch(console.error);

// 2. 處理遠端軌道
pc.ontrack = e => remoteVideo.srcObject = e.streams[0];

// 3. ICE Candidate 交換
pc.onicecandidate = e => {
    if (e.candidate) signaling.send(JSON.stringify({ type: 'candidate', candidate: e.candidate }));
};

// 4. 信令消息處理
signaling.onmessage = async ({ data }) => {
    const msg = JSON.parse(data);
    switch (msg.type) {
        case 'offer':
            await pc.setRemoteDescription(new RTCSessionDescription(msg));
            const answer = await pc.createAnswer();
            await pc.setLocalDescription(answer);
            signaling.send(JSON.stringify({ type: 'answer', sdp: answer }));
            break;
        case 'answer':
            await pc.setRemoteDescription(new RTCSessionDescription(msg));
            break;
        case 'candidate':
            await pc.addIceCandidate(new RTCIceCandidate(msg.candidate));
            break;
        case 'bye':
            pc.close();
            break;
    }
};

// 5. 發起呼叫
document.getElementById('btnCall').onclick = async () => {
    const offer = await pc.createOffer();
    await pc.setLocalDescription(offer);
    signaling.send(JSON.stringify({ type: 'offer', sdp: offer }));
};

// 6. 掛斷
document.getElementById('btnHangup').onclick = () => {
    signaling.send(JSON.stringify({ type: 'bye' }));
    pc.close();
};

信令服務器極簡實現 (Node.js + ws)

// signal.js
const WebSocket = require('ws');
const wss = new WebSocket.Server({ port: 8443 }); // 需配置 SSL 憑證
const rooms = new Map();

wss.on('connection', (ws, req) => {
    const room = new URL(req.url, `https://${req.headers.host}`).searchParams.get('room') || 'default';
    if (!rooms.has(room)) rooms.set(room, new Set());
    rooms.get(room).add(ws);

    ws.on('message', (msg) => {
        // 廣播給房間內其他人
        for (const client of rooms.get(room)) {
            if (client !== ws && client.readyState === WebSocket.OPEN) {
                client.send(msg);
            }
        }
    });

    ws.on('close', () => rooms.get(room).delete(ws));
});

coturn 部署要點 (Ubuntu 22.04)

apt update && apt install -y coturn
# /etc/turnserver.conf
listening-port=3478
tls-listening-port=5349
fingerprint
lt-cred-mech
use-auth-secret
static-auth-secret=your_long_random_secret
realm=example.com
total-quota=100
stale-nonce=600
# systemctl enable --now coturn

常見坑點速查

組件作用部署建議
信令服務器WebSocket 交換 SDP/ICE CandidateNode.js + ws / Socket.io / Go + Gorilla WebSocket,需 HTTPS/WSS
STUN 服務器獲取公網 IP:Port (NAT 穿透)免費:`stun:stun.l.google.com:19302` 或自建 coturn
TURN 服務器中繼流量 (對稱 NAT/防火牆)**生產必須自建** coturn,配置長期憑證 `turn:turn.example.com:3478?transport=udp`
HTTPS 憑證瀏覽器強制安全上下文Let's Encrypt / CF SSL,配置 HSTS
現象原因解決
本地能通、跨網不通缺 TURN 或 TURN 埠未放行部署 coturn、防火牆開 3478/5349 UDP/TCP
視頻黑屏/綠屏編碼器協商失敗 (H.264/VP8/VP9)SDp 中確保雙端支援共同編碼,或強制 `RTCRtpTransceiver.setCodecPreferences`
移動端無聲音自動播放策略、AudioContext 需用戶手勢啟動按鈕點擊時 `audioContext.resume()`
信令 WebSocket 頻繁斷開負載均衡器無 Sticky Session / 超時配置 WebSocket 親和性、心跳 Ping/Pong

進階資源

總結

**WebRTC = getUserMedia + RTCPeerConnection + 信令 + STUN/TURN**。前端代碼不足 100 行,**關鍵在於基礎設施 (TURN、HTTPS、信令高可用)**。建議先跑通官方樣例,再逐步替換信令/ TURN 為自建服務。

  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved