WebRTC Demo

利用WebRTC实现的一个局域网内单向视频的示例。由于是在局域网内,所用没有使用到STUN/TURN 服务器,如果需要则可以使用coturn开源库来搭建。然后使用Node.js搭建了一个简单的信令服务器。运行时,需要先打开接收端页面,再打开发送端页面,才能正常看到视频流。

下面是主要部分的代码:

服务器端 

server.js:

'use strict'

var http = require('http');
var https = require('https');
var fs = require('fs');

var serveIndex = require('serve-index');

var express = require('express');

//socket.io
var socketIo = require('socket.io');

var app = express();
//顺序不能换
app.use(serveIndex('./public'));
app.use(express.static('./public'));


var options = {
  key: fs.readFileSync('./cert/oxbbnb.top_nginx/oxbbnb.top.key'),
  cert: fs.readFileSync('./cert/oxbbnb.top_nginx/oxbbnb.top_bundle.pem')
}

var https_server = https.createServer(options, app);
//bind socket.io with https_server
var io = socketIo(https_server);

// 转发双方的SDP和ICE
io.on('connection', (socket) => {
  console.log('a user connected');

  socket.on('send_sdp', (msg) => {
    console.log('send_sdp:\n' + msg.slice(0, 50) + '...\n');
    io.emit('send_sdp', msg);
  });

  socket.on('recv_sdp', (msg) => {
    console.log('recv_sdp:\n' + msg.slice(0, 50) + '...\n');
    io.emit('recv_sdp', msg);
  });

  socket.on('send_ice', (msg) => {
    console.log('send_ice:\n' + msg + '\n');
    io.emit('send_ice', msg);
  });

  socket.on('recv_ice', (msg) => {
    console.log('recv_ice:\n' + msg + '\n');
    io.emit('recv_ice', msg);
  });

  socket.on('disconnect', () => {
    console.log('user disconnected');
    io.emit('user_disconnected');
  });
});

https_server.listen(443, '0.0.0.0');

var http_server = http.createServer(app);
http_server.listen(8080, '0.0.0.0');

发送端:

sender.html:

<!DOCTYPE html>
<html lang="en">

<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>WebRTC Sender</title>
</head>

<body>
    <h1>WebRTC Sender</h1>
    <video id="localVideo" autoplay playsinline></video>

    <script src="https://webrtc.github.io/adapter/adapter-latest.js"></script>
    <script src="https://cdn.socket.io/socket.io-3.0.1.js"></script>
    <script src="./js/sender.js"></script>
</body>

</html>

sender.js:

const socket = io();

var pc;

navigator.mediaDevices.getUserMedia({ video: true, audio: true })
    .then(function (localStream) {
        //document.getElementById('localVideo').srcObject = localStream;

        /*
        const configuration = {
            iceServers: [
                // STUN 服务器
                {
                    urls: 'stun:xxx.xxx.xxx.xxx:3478',
                },
                // TURN 服务器
                {
                    urls: 'turn:xxx.xxx.xxx.xxx:3478',
                    username: 'xxx',
                    credential: 'xxx'
                }
            ]
        };
        pc = new RTCPeerConnection(configuration);
        */
        
        pc = new RTCPeerConnection();
        localStream.getTracks().forEach(track => pc.addTrack(track, localStream));

        var offerOptions = {
            offerToReceiveAudio: 1,
            offerToReceiveVideo: 1
        }
        pc.createOffer(offerOptions)
            .then(function (offer) {
                return pc.setLocalDescription(offer);
            })
            .then(function () {
                // 发送SDP
                socket.emit('send_sdp', pc.localDescription.sdp);
                //console.log('send_sdp:\n' + pc.localDescription.sdp);
            });

        pc.onicecandidate = event => {
            if (event.candidate) {
                // 发送ICE
                var data = {
                    type: 'candidate',
                    label: event.candidate.sdpMLineIndex,
                    id: event.candidate.sdpMid,
                    candidate: event.candidate.candidate
                }
                socket.emit('send_ice', JSON.stringify(data));
                //console.log('send_ice:\n' + JSON.stringify(data));
            }
        };
    })
    .catch(function (error) {
        console.error("Error accessing camera:", error);
    });

//接收SDP
socket.on('recv_sdp', (sdp) => {
    //console.log('receive sdp:\n' + sdp);
    pc.setRemoteDescription(new RTCSessionDescription({ type: 'answer', sdp: sdp }));
})

//接收ICE
socket.on('recv_ice', (ice) => {
    console.log('receive ice:\n' + ice);
    var obj = JSON.parse(ice);
    var iceCandidate = new RTCIceCandidate({
        candidate: obj.candidate, sdpMLineIndex: obj.label, sdpMid: obj.id
    });
    pc.addIceCandidate(iceCandidate);
})

接收端

receiver.html:

<!DOCTYPE html>
<html lang="en">

<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>WebRTC Receiver</title>
</head>

<body>
    <h1>WebRTC Receiver</h1>
    <video id="remoteVideo" autoplay playsinline></video>

    <script src="https://webrtc.github.io/adapter/adapter-latest.js"></script>
    <script src="https://cdn.socket.io/socket.io-3.0.1.js"></script>
    <script src="./js/receiver.js"></script>
</body>

</html>

receiver.js:

const socket = io();

var pc;

socket.on('send_sdp', (sdp) => {
    //console.log('send_sdp sdp:\n' + sdp);

    /*
    const configuration = {
        iceServers: [
            // STUN 服务器
            {
                urls: 'stun:xxx.xxx.xxx.xxx:3478',
            },
            // TURN 服务器
            {
                urls: 'turn:xxx.xxx.xxx.xxx:3478',
                username: 'xxx',
                credential: 'xxx'
            }
        ]
    };
    pc = new RTCPeerConnection(configuration);
    */  

    pc = new RTCPeerConnection();
    pc.setRemoteDescription(new RTCSessionDescription({ type: 'offer', sdp: sdp }));
    pc.createAnswer().then(function (answer) {
        pc.setLocalDescription(answer);
        socket.emit('recv_sdp', answer.sdp);
    })

    pc.ontrack = (event) => {
        document.getElementById('remoteVideo').srcObject = event.streams[0];
    }
})

socket.on('send_ice', (ice) => {
    console.log('send_ice ice:\n' + ice);
    var obj = JSON.parse(ice);
    var iceCandidate = new RTCIceCandidate({
        candidate: obj.candidate, sdpMLineIndex: obj.label, sdpMid: obj.id
    });
    pc.addIceCandidate(iceCandidate);
    pc.onicecandidate = (e) => {
        if (e.candidate) {
            var data = {
                type: 'candidate',
                label: e.candidate.sdpMLineIndex,
                id: e.candidate.sdpMid,
                candidate: e.candidate.candidate
            }
            socket.emit('recv_ice', JSON.stringify(data));
            //console.log('recv_ice:\n' + JSON.stringify(data));
        }
    }
})

socket.on('user_disconnected', () => {
    console.log('user_disconnected');
    if (pc) {
        pc.close();
        pc = null;
    }
    // 清除视频流
    document.getElementById('remoteVideo').srcObject = null;
});

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
WebRTC Demo是一种在线应用程序,它基于WebRTC技术,能够通过网络实时传输音频、视频和数据。WebRTC是一种开放性的标准,旨在使浏览器成为实时通信的平台,而不需要安装额外的插件或软件。 通过WebRTC Demo,用户可以利用网络直接进行语音和视频通话,而无需使用传统的电话线路。此外,它还提供了实时数据传输的功能,使用户能够共享文件、屏幕或其他类型的数据。 WebRTC Demo的工作原理是基于P2P(点对点)连接。它使用STUN(Session Traversal Utilities for NAT)和TURN(Traversal Using Relays around NAT)协议来处理网络的穿透和转发。这样,用户可以建立直接的连接,实现快速稳定的通信。 WebRTC Demo可以应用于多种场景,如在线会议、远程教育、客户服务等。它为用户提供了方便快捷的实时通信方式,无论是个人用户还是企业用户,都可以从中受益。 WebRTC Demo还具有跨平台的特性,可以在不同的设备上运行,包括桌面、移动端和嵌入式设备。用户可以在智能手机、平板电脑或计算机上使用WebRTC Demo,随时随地与其他人进行通信。 总之,WebRTC Demo是一种能够实现在线实时通信的应用程序,它利用WebRTC技术提供了音频、视频和数据传输的能力,为用户提供了方便快捷的通信方式。无论是个人用户还是企业用户,都可以通过WebRTC Demo实现在线的语音、视频通话和数据共享。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值