鍍金池/ 問答/Java  Linux  HTML/ webrtc + socket.io 實現(xiàn)一個視頻分享的功能

webrtc + socket.io 實現(xiàn)一個視頻分享的功能

寫了很簡單的一個demo,多次調(diào)試之后所有的報錯都已經(jīng)解決了,但是現(xiàn)在還是沒能實現(xiàn)想要的效果。各位大佬幫看下是哪里出問題了。

// 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
        })
    }
}

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

// 獲取用戶本地設(shè)備
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')
}

// 遠(yuǎn)端 sdp 設(shè)置到本地
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.用戶進(jìn)入一個web網(wǎng)站,該網(wǎng)站有一個沒有視頻源的video標(biāo)簽。
2.用戶通過手機打開一個該網(wǎng)站的子頁面,調(diào)用手機攝像頭拍攝影像并傳遞到web網(wǎng)站的video標(biāo)簽上。


補充:
1.在console中打印的iceConnectionState時發(fā)現(xiàn),phone.js內(nèi)部的iceConnectionState觸發(fā)過程:checking -> connected -> completed;而index.js中觸發(fā)過程僅有checking -> connected。
2.在firefox下訪問時,控制臺內(nèi)會提示ICE failed, add a STUN server and see about:webrtc for more details。

回答
編輯回答
冷溫柔

沒有人用過嗎?給個webRtc的群也行啊。

2017年9月12日 11:35