How to display IP camera feed from an RTSP url onto reactjs app page?
Asked Answered
C

4

6

I want to display the live footage of an ip camera on a web page built using ReactJS.

I found some solutions on the internet but that provide solutions using the http url. However my camera has a username and password, and I don't know how to embed the username/password into the http url.

I have a functioning rtsp url with the username/password.

I would like to have a video element inside the react app like this:

render() {
   return (
     <div>
       <video
         ....
       />
     </div>
   );
}

My functioning rtsp url is like: rtsp://username:[email protected]:554

Cavatina answered 31/7, 2019 at 12:21 Comment(2)
Ave you triyed to use an iframe?Verdugo
Something like that as source http://username:[email protected]:554Verdugo
B
4

Your solution should be set with two parts: a nodejs application that will read the steram from the RTSP and client side a canvas that will get that stream from the nodejs application.

Think of it as a "proxy"

On Server:

Stream = require('node-rtsp-stream')
stream = new Stream({
  name: 'name',
  streamUrl: 'rtsp://username:[email protected]:554',
  wsPort: 9999,
  ffmpegOptions: { // options ffmpeg flags
    '-stats': '', // an option with no neccessary value uses a blank string
    '-r': 30 // options with required values specify the value after the key
  }
})

On Client:

client = new WebSocket('ws://NODEJS_SERVER_IP:9999')
player = new jsmpeg(client, {
  canvas: canvas // Canvas should be a canvas DOM element
})

There is a good npm you can use that does that:

https://www.npmjs.com/package/node-rtsp-stream

Burma answered 31/7, 2019 at 12:39 Comment(0)
T
0

I think you need a special media player. Have you tried hls.js. You may include the library, then build your own component and pass the link to it so it may play then.

Taffy answered 31/7, 2019 at 12:37 Comment(0)
C
0

we need to use third party api or we can also do by using nginx to display the cctv camera footage into react application . As we know react has virtual DOM it will not allow to show the rtsp data flow it maximum allows the http flow data or hls flow data will be accepted but comming to html we can show the streaming data using websockets . As there is no virtual DOM .

The Node js CODE:

       const express = require('express');
const Stream = require('node-rtsp-stream');

const app = express();
const port = 3002;
let stream = null;

app.get('/stream/:id', (req, res) => {
  const id = req.params.id;
  const newRtspStreamUrl = 'rtsp://*****:*******@address'

  // Create the WebSocket stream only if it doesn't exist or the RTSP URL has changed
  if (!stream || currentRtspStreamUrl !== newRtspStreamUrl) {
    if (stream) {
      stream.stop();
    }
    stream = new Stream({
      name: 'Camera Stream',
      streamUrl: newRtspStreamUrl,
      wsPort: 9999
    });
    currentRtspStreamUrl = newRtspStreamUrl;
  }


  res.send('Streaming started');
});

app.listen(port, () => {
  console.log(`Server running on port ${port}`);
});

Here we are creating a websocket and we are assigning port to it and we are stoping the stream when the rtsp link is changing we that has not changed then the new socket will be created on that same port resulting in the error.

Now we will create a frontend in REACTJS:

PUBLIC>>INDEX.html

     <!DOCTYPE html>
<html lang="en">
  <head>
    <meta charset="utf-8" />
    <link rel="icon" href="%PUBLIC_URL%/favicon.ico" />
    <meta name="viewport" content="width=device-width, initial-scale=1" />
    <meta name="theme-color" content="#000000" />
    <meta
      name="description"
      content="Web site created using create-react-app"
    />
    <link rel="apple-touch-icon" href="%PUBLIC_URL%/logo192.png" />
    <link rel="manifest" href="%PUBLIC_URL%/manifest.json" />
    <title>React App</title>
    <style>
      .camera {
  background-color: aqua;
  width: 800px;
  height: 400px;
}
    </style>
  </head>
  <body>
    <noscript>You need to enable JavaScript to run this app.</noscript>
    <div id="root"></div>
    <div id="cctv" style="position: fixed; display: none;width: 100%;height: 100%;background-color: aqua;">
      <button onclick="shoot1(),cctv_call()">Go back to dashboard</button>
      <p id="asdf">yasawnth</p>
        <input id="cctv_inputvalue" type="text" />
        <button onclick="cctv_call() ">Show stream</button>
      <script src="https://cdn.jsdelivr.net/npm/axios/dist/axios.min.js"></script>
      <script>
        // Fetch the stream URL
      
       
        window.onload = cctv_call();
        function cctv_call(){
          if(window.document.getElementById("cctv_inputvalue").value){
            sessionStorage.cameraid = window.document.getElementById("cctv_inputvalue").value;

          }
          else{
            sessionStorage.cameraid = sessionStorage.getItem("cameraid");
            window.document.getElementById("cctv_inputvalue").value = sessionStorage.getItem("cctv_inputvalue");
           
          }
          if(sessionStorage.getItem("root")=="none"){
                        root.style.display = "none";
                        cctv.style.display = "block";
          }
          const i=sessionStorage.getItem("cameraid");
          console.log(i);
        
          axios.get('http://localhost:3002/stream/'+i)
            .then(response => {
              const streamUrl = response.data.streamUrl;
              videoPlayer.src = streamUrl;
              console.log(videoPlayer.src)
            })
            .catch(error => {
              console.error('Error fetching video stream:', error);
            });
        }
      </script>
      <h1>Streaming Video</h1>
      <canvas class="camera" id="videoCanvas" style="background-color: aqua;" width="640" height="480"></canvas>
      <script src="jsmpeg.min.js"></script>
      <script>
        const canvas = document.getElementById('videoCanvas');
        const url = 'ws://localhost:9999';
        const player = new JSMpeg.Player(url, { canvas });
        // Handle WebSocket connection errors
        player.onError = (error) => {
          console.error('WebSocket error:', error);
        };
        // Handle WebSocket connection close
        player.onSourceEnd = () => {
          console.log('WebSocket connection closed');
        };
        //axios req
      </script>
    </div>
  </body>
  <script>

    function shoot1(){
      
      root.style.display="block";
      cctv.style.display="none";
      sessionStorage.root='block';
      sessionStorage.cctv = "none";
    
    }
  </script>
</html>

you need to use JSMPEG to stream the data in frontend and now we need to write

APP.JS

import React from 'react';
import './App.css';


const App = () => {
  const root=window.document.getElementById('root')
  const cctv=window.document.getElementById('cctv')
 
  const shoot = () => {
    root.style.display="none";
    cctv.style.display="block";
    sessionStorage.setItem("root","none");
    sessionStorage.setItem("cctv","block");
  }
  return (
    <div className='ra'>
      <button onClick={shoot}>cctv dashboard</button>
    </div>
  );
};

export default App; This is how it works

@yaswanthsaipilla @bharathmaradana

Compensate answered 12/6, 2023 at 9:22 Comment(0)
C
0

Refactor it however you please, but this should give you the essential blocks to successfully display the rtsp url in the react js app.

Also make sure the rtsp feed is valid, you can test it using vlc media app.

On Server

const express = require("express")
const Stream = require("node-rtsp-stream")
const cors = require("cors")

const app = express()
const port = 3002
let stream = null

app.use(
  cors({
    origin: "http://localhost:3000",
    credentials: true,
  })
)

app.get("/stream", (req, res) => {
  const newRtspStreamUrl = req.query.rtsp
  let currentRtspStreamUrl = ""

  // Create the WebSocket stream only if it doesn't exist or the RTSP URL has changed
  if (!stream || currentRtspStreamUrl !== newRtspStreamUrl) {
    if (stream || newRtspStreamUrl === "stop") {
      stream.stop()
    }
    stream = new Stream({
      name: "Camera Stream",
      streamUrl: newRtspStreamUrl,
      wsPort: 9999,
    })
    currentRtspStreamUrl = newRtspStreamUrl
  }

  res.send(200).json({ url: `ws://127.0.0.1:9999` })
})

app.listen(port, () => {
  console.log(`Server running on port ${port}`)
})

On Client

import React from "react"
import JSMpeg from "@cycjimmy/jsmpeg-player"
import axios from "axios"

const StreamPlayer = () => {

useEffect(()=>{
    let canvas = document.getElementById("video-canvas")
    let url = "ws://localhost:9999"
    new JSMpeg.Player(url, { canvas: canvas })
  },[])

const rtspurl = ""//enter the rtsp url here
  
const httpRequest = (url) => {
   axios.get(`http://127.0.0.1:3002/stream?rtsp=${url}`)
}
    
const startRTSPFeed = () => {
   httpRequest(rtspurl)
}
    
const stopRTSPFeed = () => {
   httpRequest("stop")
}

return(
   <div>
      <div>
        <canvas id="video-canvas"></canvas>
      </div>
      <div>
        <button onClick={startRTSPFeed}>Start RTSP Feed</button>
        <button onClick={stopRTSPFeed}> Stop RTSP Feed</button>
      </div>
   </div>
)}
Cooperman answered 17/10, 2023 at 12:29 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.