首页 > 解决方案 > WebRTC 在本地工作,但不能通过 Internet

问题描述

我正在尝试获得一个简单的概念验证 WebRTC 应用程序。我的代码可以在本地网络上运行,但不能在 Internet 上运行。

我相信我在这里列出了一个错误,但我无法弄清楚。

server.js (expressjs)

require('dotenv').config();

const express = require('express');
const app = express();
const http = require('http').createServer(app);
const io = require('socket.io')(http);

app.use(express.static('public'));

io.on('connection', (socket) => {
    socket.on('join', () => socket.broadcast.emit('join', socket.id));
    socket.on('offer', (id, sdp) => socket.to(id).emit('offer', socket.id, sdp));
    socket.on('answer', (id, sdp) => socket.to(id).emit('answer', socket.id, sdp));
    socket.on('candidate', (id, candidate) => socket.to(id).emit('candidate', socket.id, candidate));
});

const port = process.env.PORT || 443;
http.listen(port, () => console.log("listening on :" + port));

client.js(使用 webpack 构建)

import io from 'socket.io-client';

console.log('getting video stream');
navigator.mediaDevices.getUserMedia({ video: true }).then(myStream => {
    const socket = io.connect();

    console.log('joining');
    socket.emit('join');

    let connections = {};

    socket.on('join', async peer_id => {
        const connection = newConnection(peer_id);

        console.log('creating offer');
        const sdp = await connection.createOffer();

        console.log('setting local desc');
        await connection.setLocalDescription(sdp);

        console.log('sending offer');
        socket.emit('offer', peer_id, connection.localDescription);
    });

    socket.on('offer', async (peer_id, remoteDescription) => {
        const connection = newConnection(peer_id);

        console.log('setting remote desc');
        await connection.setRemoteDescription(remoteDescription);

        console.log('creating answer');
        const sdp = await connection.createAnswer();

        console.log('setting local desc');
        await connection.setLocalDescription(sdp);

        console.log('sending answer');
        socket.emit('answer', peer_id, connection.localDescription);
    });

    socket.on('answer', (peer_id, remoteDescription) => {
        console.log('setting remote desc');
        connections[peer_id].setRemoteDescription(remoteDescription);
    });

    socket.on('candidate', (peer_id, candidate) => {
        console.log('adding candidate');
        connections[peer_id].addIceCandidate(candidate);
    });

    function newConnection(peer_id) {
        console.log('creating connection');
        const connection = new RTCPeerConnection(
            { iceServers: [{ urls: ['stun:stun.l.google.com:19302'] }] }
        );

        connections[peer_id] = connection;

        connection.onconnectionstatechange = () => console.log('connection state', connection.connectionState);

        console.log('searching for candidates');
        connection.onicecandidate = event => {
            if (event.candidate) {
                console.log('sending candidate');
                socket.emit('candidate', peer_id, event.candidate);
            } else {
                console.log('all candidates found');
            }
        };

        console.log('listening for tracks');
        connection.ontrack = event => {
            console.log('track received');
            const stream = new MediaStream();
            stream.addTrack(event.track);
            document.getElementById('video').srcObject = stream;
        };

        for (const track of myStream.getTracks()) {
            console.log('sending track');
            connection.addTrack(track);
        }

        return connection;
    }
});

来自本地网络对等点的日志(已连接)

第一对等

getting video stream
joining
creating connection
searching for candidates
listening for tracks
sending track
creating offer
setting local desc
sending offer
(2) sending candidate
setting remote desc
adding candidate
track received
connection state connecting
all candidates found
connection state connected

第二对等

getting video stream
joining
creating connection
searching for candidates
listening for tracks
sending track
setting remote desc
track received
creating answer
setting local desc
sending answer
sending candidate
connection state connecting
all candidates found
connection state connected
(2) adding candidate

来自 Internet 上的对等点的日志(失败)

第一对等

getting video stream
joining
creating connection
searching for candidates
listening for tracks
sending track
creating offer
setting local desc
sending offer
(3) sending candidate
all candidates found
setting remote desc
track received
connection state connecting
(5) adding candidate
connection state failed

第二对等

getting video stream
joining
creating connection
searching for candidates
listening for tracks
sending track
setting remote desc
track received
creating answer
setting local desc
sending answer
(5) sending candidate
(3) adding candidate
connection state connecting
connection state failed
all candidates found

标签: webrtc

解决方案


除非您使用 TURN,否则 WebRTC 不会适用于所有连接配对。

您会看到一些能够连接的对等方,您可以在此处阅读我的回答中的所有重要案例


推荐阅读