【问题标题】:Using simple-peer to broadcast live webcam video. NodeJs使用 simple-peer 直播网络摄像头视频。 NodeJs
【发布时间】:2020-04-20 03:19:37
【问题描述】:

我正在尝试使用 simple-peer 库将实时视频流从网络摄像头广播到服务器,然后从服务器广播到多个用户。我目前在使用 stun/turn 服务器时遇到问题。我正在使用 Xirsys。该程序在本地运行没有问题,但是当我在 Heroku 上运行它时却没有。我是 NodeJs 的新手。

有谁知道为什么它在本地运行,而不是全球运行?

客户端:

let Peer = require('simple-peer')
let socket = io()
const video = document.querySelector('video')
let client = {}

var configuration={
    iceServers: [{
        urls: [ "stun:sp-turn1.xirsys.com" ]
     }, {
        username: "LdzgXD2MWspU8qKuKIa9nYv02AqPhqD_qOeFSCsJfBjaCwq5mN-LsbrHReCmgGLwAAAAAF4HabRjYW1pbG9oaW5vam9zYQ==",
        credential: "320899dc-2980-11ea-810a-06374c00029e",
        urls: [
            "turn:sp-turn1.xirsys.com:80?transport=udp",
            "turn:sp-turn1.xirsys.com:3478?transport=udp",
            "turn:sp-turn1.xirsys.com:80?transport=tcp",
        ]
     }]
}

function CreateVideo(stream){
    video.srcObject = stream
    video.play()
}

document.getElementById('stream').onclick=function(){
    navigator.mediaDevices.getUserMedia({ video: true, audio: true })
    .then(stream=>{
        socket.emit('NewClientStreamer')
        video.srcObject = stream
        video.play()

        socket.on('CreateClientStreamerPeer',function(){
            let peer = new Peer({ 
                initiator:true,
                config:configuration,
                iceTransportPolicy: 'relay', 
                stream: stream, 
                trickle:true
            })
            peer.on('stream',function(stream){
                CreateVideo(stream)
            })
            peer.on('close',function(){
                document.getElementById("peerVideo").remove()
                peer.destroy()
            })
            peer.on('signal', function(data){
                if(!client.gotAnswer)
                    socket.emit('Offer',data)
            })
            client.peer=peer
        })

        socket.on('Answer',function(answer){
            client.gotAnswer=true
            client.peer.signal(answer)        
        })

    })
    .catch(err=>document.write(err))
}

document.getElementById('receive').onclick=function(){

    socket.emit('NewClientReceiver')

    socket.on('Offer',function(offer){
        let peer = new Peer({ 
            initiator: false,
            trickle:true
         })
        peer.on('stream',function(stream){
            CreateVideo(stream)
        })
        peer.on('signal', function(data){
            socket.emit('ClientAnswer',data)
        })
        peer.signal(offer)
        client.peer=peer
    })
}

服务器端:

const express = require('express')
const app = express()
const http = require('http').Server(app)
const io = require('socket.io')(http)
const port = process.env.PORT || 3000

const Peer=require('simple-peer')
const wrtc=require('wrtc')

var Streamer={}
var Receiver={}



var configuration={
    iceServers: [{
        urls: [ "stun:sp-turn1.xirsys.com" ]
     }, {
        username: "LdzgXD2MWspU8qKuKIa9nYv02AqPhqD_qOeFSCsJfBjaCwq5mN-LsbrHReCmgGLwAAAAAF4HabRjYW1pbG9oaW5vam9zYQ==",
        credential: "320899dc-2980-11ea-810a-06374c00029e",
        urls: [
            "turn:sp-turn1.xirsys.com:80?transport=udp",
            "turn:sp-turn1.xirsys.com:3478?transport=udp",
            "turn:sp-turn1.xirsys.com:80?transport=tcp",
        ]
     }]
}

app.use(express.static(__dirname + "/public"))

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

    socket.on('NewClientStreamer',function(){
        socket.emit('CreateClientStreamerPeer')
    })

    function InitializeReceiver(offer){
        var receiver={}
        let peer = new Peer({
            initiator:false,
            config:configuration,
            iceTransportPolicy: 'any',
            wrtc:wrtc,
            trickle:true
         })
        peer.on('signal', (data) => {
            socket.emit('Answer',data)
        })
        peer.on('close',function(){
            //
        })
        peer.on('stream',function(stream){
            receiver.stream=stream
            receiver.peer=peer
            Receiver=receiver
        })
        peer.signal(offer)
    }

    socket.on('Offer',function(offer){
        InitializeReceiver(offer)
    })

    socket.on('NewClientReceiver',function(){
        var streamer={}
        streamer.gotAnswer=false
        let peer = new Peer({
            initiator:true,
            config:configuration,
            iceTransportPolicy: 'any',
            wrtc:wrtc,
            stream: Receiver.stream, 
            trickle:true
        })
        peer.on('signal', function(offer){
            if(!streamer.gotAnswer)
                socket.emit('Offer',offer)
        })
        peer.on('connect',function(){
            Streamer=streamer
        })
        streamer.peer=peer

        socket.on('ClientAnswer',function(data){    
            streamer.gotAnswer=true
            streamer.peer.signal(data)  
        })
    })




})

http.listen(port,() => console.log(`Active on ${port} port`))

WebRTC-Chrome-webRTC internals

【问题讨论】:

  • 您能否提供/附加来自 chrome://webrtc-internals/ 的转储?
  • Igor Khvostenkov,感谢您的回复。我添加了我的 webrtc-internals 的屏幕截图。
  • 如果截图不够用。这是 Heroku 应用的链接:bolxmultitest.herokuapp.com

标签: node.js video-streaming webrtc broadcast multicast


【解决方案1】:

您在服务器上解决了从客户端到服务器的流的 STUN/TURN 服务器问题,但您还需要在客户端解决此问题。如果您在尝试接收流时查看日志,您将看到 STUN/TURN 服务器的与您在代码中的配置不同。

【讨论】:

    【解决方案2】:

    I have detected the problem why my credentials were not the same as the code, it was because I had forgotten to run watchify to modify the bundle.js script based on the main.js

    这些是我的新 webRTC chrome 内部。现在凭据匹配,但它仍然没有运行。谢谢你,Igor Khvostenkov。

    这是运行新仓库的应用的链接:https://bolx-tests.herokuapp.com/

    【讨论】:

      【解决方案3】:

      因此,您最初的问题的答案是:为什么它在本地运行而不在服务器上运行:这是由于在本地运行而发生的,您要么在同一网络中运行服务器和客户端,要么通过简单的 NAT 和 STUN 服务器可以解决您的问题客户端和服务器外部 IP。当您在服务器上运行时,您的服务器或客户端位于双重 NAT 或对称 NAT 之后。根据您的代码,这应该不是问题,因为您配置了 TURN 服务器,但是如果您查看 WebRTC 统计信息,则此配置未应用,使用了其他一些配置,请参见屏幕截图。当我从我的计算机上运行它时,根本没有配置 TURN 服务器,显然我的 IP 地址没有解析,因为我在双重 NAT 后面并且连接失败,请查看我的日志:

      https://bolxmultitest.herokuapp.com/, { iceServers: [stun:stun.l.google.com:19302, stun:global.stun.twilio.com:3478?transport=udp], iceTransportPolicy: all, bundlePolicy: balanced, rtcpMuxPolicy: require, iceCandidatePoolSize: 0, sdpSemantics: "unified-plan" },
      iceconnectionstatechange (legacy)
      checking
      03/01/2020, 16:10:42    
      connectionstatechange
      connecting
      03/01/2020, 16:10:42    
      icecandidate (host)
      sdpMid: 0, sdpMLineIndex: 0, candidate: candidate:1416191245 1 udp 2113937151 cb0baca2-665d-45a9-9c92-5fd0accdbb0f.local 51937 typ host generation 0 ufrag 9Gjl network-cost 999
      03/01/2020, 16:10:42    
      icecandidate (srflx)
      sdpMid: 0, sdpMLineIndex: 0, candidate: candidate:842163049 1 udp 1677729535 37.24.130.114 51937 typ srflx raddr 0.0.0.0 rport 0 generation 0 ufrag 9Gjl network-cost 999
      03/01/2020, 16:10:42    
      icegatheringstatechange
      complete
      03/01/2020, 16:10:57    
      iceconnectionstatechange
      disconnected
      03/01/2020, 16:10:57    
      iceconnectionstatechange (legacy)
      failed
      03/01/2020, 16:10:57    
      connectionstatechange
      failed
      

      STUN/TURN 配置在日志中应该与此类似,因为这是在您上面的代码中配置的:

      { iceServers: [stun:sp-turn1.xirsys.com:3478, turns:sp-turn1.xirsys.com:443?transport=tcp], iceTransportPolicy: all, bundlePolicy: balanced, rtcpMuxPolicy: require, iceCandidatePoolSize: 0, sdpSemantics: "unified-plan" }
      

      你需要调试为什么你的代码中的配置没有被应用,为什么你和我有不同的配置,这个配置是从哪里来的。

      【讨论】:

      • 谢谢,一碰到墙或发现问题我会试一试并报告。
      • 我已经解决了这个问题,我忘记运行 watchify 来更新 bundle.js 文件。问题仍然存在。我已经发布了对我的答案的回复,其中包含屏幕截图和应用程序的链接。比你。
      • 我只看到一张截图。是用于流式传输还是用于接收?我在我的电脑上运行,对我来说,连接适用于发送流,但它不适用于接收,我发布了一个截图,其中我有 STUN/TURN 的第三方配置。
      猜你喜欢
      • 2012-05-25
      • 1970-01-01
      • 1970-01-01
      • 2020-01-09
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2010-09-20
      相关资源
      最近更新 更多