webrtc + socket.io 实现一个视频分享的功能

写了很简单的一个demo,多次调试之后所有的报错都已经解决了,但是现在还是没能实现想要的效果。各位大佬帮看下是哪里出问题了。

// server.js
const express = require('express')
const app = express()
const path = require('path')

app.use(express.static(path.join(__dirname, 'public')))

app.get('/phone', function (req, res) {
    res.sendfile(__dirname + '/phone.html')
})

app.get('/', function (req, res) {
    res.sendfile(__dirname + '/index.html')
})

const server = require('http').createServer(app)
const io = require('socket.io')(server)
let clients = []

io.on('connection', function (socket) {

    clients.push(socket)
    const referer = socket.handshake.headers.referer

    if(referer.match('/phone')) {
        // phone
        socket.on('phone_ice_candidate', function (res) {
            socket.broadcast.emit('pc_add_ice', { ice: res.ice })
        })

        // phone
        socket.on('send_phone_sdp', function (data) {
            socket.broadcast.emit('set_pc_remote_sdp', { desc: data.desc })
        })
    }

    // pc 获取 ice 后推送给 phone
    socket.on('remote_ice_candidate', function (ice) {
        socket.to(getId(clients, '/phone')).emit('send_ice_to_pc', {ice: ice})
    })

    // pc 获取 sdp 后推送给 phone
    socket.on('send_pc_sdp', function (data) {
        // 推送给 phone
        socket.to(getId(clients, '/phone')).emit('set_phone_remote_sdp', {desc: data})
    })

    // 断开
    socket.on('disconnect', () => {
        let id = socket.id
        clients.forEach((client, index) => {
            if(client.id === id) {
                clients.splice(index, 1)
            }
        })
    })
})

function getId(sockets, exp) {
    let id
    sockets.forEach(socket => {
        if(socket.handshake.headers.referer.match(exp)) {
            id = socket.id
        }
    })
    return id
}

server.listen(3000, function () {
    console.log('port listening at 3000')
})
// phone.js
var socket = io();
var server = {
        // "iceServers": [{
        //     "url": "stun:stun.l.google.com:19302"
        // }]
    },
    pc = new RTCPeerConnection(server),
    v = document.querySelector('#video1')


// 候选列表
pc.onicecandidate = function (event) {
    if (event.candidate) {
        socket.emit('phone_ice_candidate', {
            ice: event.candidate
        })
    }
}

// 接收远端 ice
socket.on('send_ice_to_pc', function (event) {
    pc.addIceCandidate(new RTCIceCandidate(event.ice.ice))
})

// 获取用户本地设备
navigator.mediaDevices.getUserMedia({
    video: {width: 400, height: 300},
    audio: false
})
    .then(function (stream) {
        v.src = window.URL.createObjectURL(stream);
        pc.addStream(stream);
    })
    .catch(function (err) {
        console.log(err.name + ": " + err.message);
    })

// create offer
pc.createOffer({offerToReceiveVideo: 1}).then(function (e) {
    // pc setLocalDescription
    pc.setLocalDescription(e).then(
        function () {
            socket.emit('send_phone_sdp', {desc: e})
        },
        function () {
            console.log('pc setLocalDescription error')
        }
    )
});

socket.on('set_phone_remote_sdp', function (e) {
    pc.setRemoteDescription(e.desc.desc).then(
        function () {
            console.log('pc setRemoteDescription success')
        }, function (err) {
            console.log(err)
        })
})
// index.js
var socket = io();
var server = {
        // "iceServers": [{
        //     "url": "stun:stun.l.google.com:19302"
        // }]
    },
    pc = new RTCPeerConnection(server),
    v = document.querySelector('#video2')

pc.onicecandidate = function (event) {
    if (event.candidate) {
        socket.emit('remote_ice_candidate', {
            ice: event.candidate
        })
    }
}

socket.on('pc_add_ice', function (event) {
    pc.addIceCandidate(new RTCIceCandidate(event.ice))
})

//
pc.ontrack = function (e) {
    // v.srcObject = e.streams[0];
    console.log(e, 'pc.ontrack')
}

// 远端 sdp 设置到本地
socket.on('set_pc_remote_sdp', function (e) {
    pc.setRemoteDescription(e.desc).then(
        function () {
            console.log('remote setRemoteDescription success')

            pc.createAnswer().then(function (desc) {
                pc.setLocalDescription(desc).then(
                    function () {
                        socket.emit('send_pc_sdp', {desc: desc})
                    },
                    function (err) {
                        console.log(err)
                    }
                );
            })
        },
        function () {
            console.log('pc setLocalDescription error')
        }
    )

})

需求:
1.用户进入一个web网站,该网站有一个没有视频源的video标签。
2.用户通过手机打开一个该网站的子页面,调用手机摄像头拍摄影像并传递到web网站的video标签上。


补充:
1.在console中打印的iceConnectionState时发现,phone.js内部的iceConnectionState触发过程:checking -> connected -> completed;而index.js中触发过程仅有checking -> connected
2.在firefox下访问时,控制台内会提示ICE failed, add a STUN server and see about:webrtc for more details

阅读 3.8k
1 个回答
撰写回答
你尚未登录,登录后可以
  • 和开发者交流问题的细节
  • 关注并接收问题和回答的更新提醒
  • 参与内容的编辑和改进,让解决方法与时俱进
推荐问题