p2p连接时无法获取iceCandidate

问题描述 投票:0回答:1

我的任务是从 rtsp 流获取视频,然后准备并发送该流以供浏览器上的 React 客户端使用。 但我无法在客户端启动 oneicecandidate 和 ontrack 处理程序。 我想我已经在我的

p2p
服务器和
nodejs
客户端之间建立了
react
连接。但是
oneicecandidate
处理程序两侧都没有开火,任何人都可以帮我解决这个问题吗?

这是反应组件:

import {useEffect, useRef} from 'react'
import {io} from 'socket.io-client'

function VideoPlayer() {
  const videoRef = useRef<HTMLVideoElement>(null)

  const socketRef = useRef(io('ws://localhost:3333'))

  useEffect(() => {
    console.log('mount')
    const peer = new RTCPeerConnection({
      iceServers: [
        {
          urls: [
            'stun:stun.l.google.com:19302',
            'stun:stun1.l.google.com:19302',
            'stun:stun2.l.google.com:19302',
            'turn:numb.viagenie.ca',
          ],
          credential: 'muazkh',
          username: '[email protected]',
        },
      ],
    })

    socketRef.current.on('open', () => {
      console.log('connected')
    })

    socketRef.current.on('error', (err) => {
      console.log(err)
    })

    socketRef.current.on('toClient', async (message) => {
      console.log(message)
      if (message.answer) {
        await peer.setRemoteDescription(message.answer)
      }

      if (message.iceCandidate) {
        await peer.addIceCandidate(message.iceCandidate)
      }
    })

    peer.onicecandidate = (event) => {
      console.log('onicecandidate', {event})
      socketRef.current.emit('fromClient', {iceCandidate: event.candidate})
    }

    peer.ontrack = (event) => {
      console.log('ontrack', event)

      if (videoRef.current) {
        videoRef.current.srcObject = event.streams[0]
        console.log(event.streams)
        videoRef.current.play()
      }
    }

    const init = async () => {
      const offer = await peer.createOffer()
      await peer.setLocalDescription(offer)

      console.log({offer})
      socketRef.current.emit('fromClient', {offer})
    }

    init()
  }, [])

  return <video ref={videoRef} id='remoteVideo' autoPlay />
}

export default VideoPlayer

这是服务器:

const express = require('express')
const {spawn} = require('child_process')
const {MediaStream, RTCPeerConnection, nonstandard} = require('wrtc')
const {RTCVideoSource} = nonstandard
const Chunker = require('./utils/chunker')
const {Server} = require('socket.io')
const {createServer} = require('node:http')
const cors = require('cors')

const rtspUrl = 'rtsp://192.168.1.136/main_stream'

const app = express()
app.use(cors())

const server = createServer(app)
const socketIoServer = new Server({
  server,
  cors: {
    origin: '*',
  },
})

const width = 1920
const height = 1080
const ffmpeg = spawn('ffmpeg', ['-i', rtspUrl, '-c', 'copy', '-f', 'mpegts', 'pipe:1'])

const videoStream = new MediaStream()
const videoSource = new RTCVideoSource()
const videoTrack = videoSource.createTrack()
const videoChunker = new Chunker(width * height * 1.5)
ffmpeg.stdout.pipe(videoChunker)

videoChunker.on('data', (data) => {
  const i420Frame = {
    width,
    height,
    data: new Uint8ClampedArray(data),
  }
  videoSource.onFrame(i420Frame)
})

const pc = new RTCPeerConnection()
videoStream.getTracks().forEach((track) => pc.addTrack(track, videoStream))

const fromClientCb = async (message) => {
  if (message.offer) {
    console.log(message.offer)
    await pc.setRemoteDescription(message.offer)
    const answer = await pc.createAnswer()
    console.log({answer})
    await pc.setLocalDescription(answer)

    socketIoServer.emit('toClient', {answer})
  }

  if (message.iceCandidate) {
    console.log({iceCandidate: message.iceCandidate})
    pc.addIceCandidate(message.iceCandidate)
  }
}

pc.onicecandidate = (event) => {
  console.log('onicecandidate', event)
  socketIoServer.emit('toClient', {iceCandidate: event.candidate})
}

socketIoServer.on('connect', (socket) => {
  console.log('connected')
  socket.on('fromClient', (message) => fromClientCb(message))
})

socketIoServer.listen(3333)

这里是报价sdp:

{
  type: 'offer',
  sdp: 'v=0\r\n' +
    'o=mozilla...THIS_IS_SDPARTA-99.0 4698947050461943875 0 IN IP4 0.0.0.0\r\n' +
    's=-\r\n' +
    't=0 0\r\n' +
    'a=fingerprint:sha-256 4A:18:D0:76:03:B8:75:FE:E8:9B:01:A3:1C:87:5D:2D:35:22:B3:03:EC:8F:4B:A9:18:37:86:56:B7:58:86:B8\r\n' +
    'a=ice-options:trickle\r\n' +
    'a=msid-semantic:WMS *\r\n'
}

这是答案 sdp

{
  answer: {
    type: 'answer',
    sdp: 'v=0\r\n' +
      'o=- 4690817293092286367 12 IN IP4 127.0.0.1\r\n' +
      's=-\r\n' +
      't=0 0\r\n' +
      'a=msid-semantic: WMS\r\n'
  }
}

我想我应该提到客户端和服务器运行在同一台电脑和网络上

我的目标是让rtsp流在浏览器中工作

reactjs node.js webrtc rtsp rtcpeerconnection
1个回答
0
投票

您没有向 RTCPeerConnection 添加任何 MediaStreamTrack 或数据通道。因此,您的 SDP 仅显示所谓的“会话部分”,并且不用于协商任何ice 候选者。因此,不会收集 ICE 候选人,并且 onicecandidate 不会触发。

如果您想从服务器接收数据,请使用

createOffer({offerToReceiveVideo: true})
或调用
addTransceiver('video')

另请注意,“muazkh”大约在十年前更改了该 TURN 帐户的凭据。

© www.soinside.com 2019 - 2024. All rights reserved.