How to Render RTSP Streams within a React App
Prerequisites: NodeJS, Docker, git
Repository for this tutorial can be found here.
If you need to incorporate an RTSP stream into an existing web app, you might think its as easy as adding the RTSP URL into your HTML5 <video />
. However, it’s not really that simple. In this article, we will stand up a simple React application with Vite, a Golang-based video encoding service with RTSPtoWeb, and view the encoded and streamed video in our React application using the VideoJS package.
Before we get started with coding, let’s learn a little bit about the history of RTSP.
Time for a little history lesson…
RTSP, a.k.a. Real-Time Streaming Protocol, is a protocol for streaming video online. RTSP is most commonly used for security footage streaming, such as those coming from CCTV or IP cameras. The strength of RTSP is that rather than forcing the viewers to download an entire video before watching it, the RTSP stream allows them to watch the content before the download is fully complete. Nowadays, this is not very special, but when RTSP was first proposed in 1996 it was a very cutting edge concept.
Developers who try to integrate RTSP into their apps today may struggle because you cannot directly stream RTSP within web applications. A few extra steps need to be taken before it can be rendered within a browser. The process outlined below is just one of the many ways that we can solve this issue, but it is the one which worked best for me. Your situation may vary!
Getting Started
If you don’t have a proper RTSP video stream ready before you begin development, you can check out this article here which has good amount of video links to use as placeholders in your project. For my examples, I will be using rtsp://rtsp/stream/pattern
. This example RTSP just shows some simple SMPTE color bars, text, visual noise, and a repeating tone.
Opening the link in the browser is not enough to view the stream, but if you have VLC installed, you should be able to view it by going “File > Open Network” and pasting the RTSP URL into the box and clicking “Open.” If you cannot view this example and you do not have an example of your own, I suggest you scour the internet for an alternative. This guide won’t be very useful without an RTSP feed!
After we’ve confirmed that we can see the example stream, we’ll work on setting up our web app. You may already have a React app that you’re working on for an existing project, so feel free to use that instead, but for this tutorial will stand up a small example app. The same concepts can be applied to Vue, Angular, or Svelte as well, but you will need to figure out a few things on your own.
Creating our example React app
We’re going to be using Vite for our React app build tooling. Let’s create a new project by running npm create vite@latest
, going through the wizard, and choosing “react-ts” when prompted. Run npm install
in the directory shown in order to install dependencies and then run npm run dev
to spin up the development server.
Now, dive into the App.tsx
file and clear mostly everything out.
This gives us a simple playground where we can start iterating on our code.
Starting RTSPtoWeb
Now that we have an incredibly simple web app, we can begin setting up our RTSP conversion service. For this, we will be leveraging RTSPtoWeb. RTSPtoWeb is a Golang-based service which converts RTSP streams to a browser-friendly format.
Lets start by cloning the RTSPtoWeb project by running the following commands:
git clone https://github.com/deepch/RTSPtoWeb
cd RTSPtoWeb
RTSPtoWeb requires a config.json
file to be defined and configured before runtime in order to understand where your RTSP videos are. After cloning the repo, we can edit the config.json
that they’ve provided by running vim config.json
inside of the RTSPtoWeb folder. We can leave most of the fields as they are, but we’re going to update the “streams” item to have the following information:
If you’re following along with the Git repo, I’ve included the full config.json here. Let’s note a few things about this configuration:
- That we’ve defined a stream titled “pattern”
- Within that stream we have defined a channel 0 containing the URL of our example RTSP stream.
Keep this structure in mind, because we’ll be using it later to help us understand what URL to access when we want to define our video src
in our web app.
Now that we’ve updated the config.json, all that’s left to do is to start the RTSPtoWeb service by running the following command:
GO111MODULE=on go run *.go
You may receive a network notifications request during this stage, but just allow it to proceed. We can now confirm that the service is running by visiting localhost:8083 in our browser. If your dashboard looks like the image below, then you should be in the clear!
Within this dashboard we can see a few of the different formats that RTSPtoWeb can convert our stream: MSE, HLS, and WebRTC. For our use, we will be leveraging the HLS stream. Confirm that your HLS stream loads properly by clicking on the HLS button. You should see the following image confirming that the video is being appropriately converted by RTSPtoWeb.
Under the hood, the HLS video format consists of two key parts:
- An .m3u8 playlist digest file which defines the references to the segments of the video
- A series of .ts files which contain the individual video segments (note that .ts does not stand for “TypeScript” here 🙂)
The src for our video will be this .m3u8 file.
Integrating VideoJS
In order to bring our HLS video into the browser, we need to add a new library to our front-end. Let’s stop our Vite React server with cmd+c, install the necessary package, and start the server again with the following commands:
npm install --save-dev video.js @types/video.js
npm run dev
In order to set up video.js in an app, we will need to define a special component to handle the video feed. Lets start by creating a new file named VideoFeed.tsx. For this component, we will be using the Video.js React tutorial documentation to build out our component. I’ll provide the snippet below, but if any of it is confusing, I recommend checking out that tutorial for more information.
Bringing it all together now…
Now that we have our VideoFeed component set up, we can integrate our stream into it. Remember from our previous setup that we defined our stream as being named “pattern” and our channel as “0”? In order to access the appropriate m3u8 file, we’re going to need to formulate the correct URL. The format is http://localhost:8083/stream/{stream_name}/channel/{channel_name}/hls/live/index.m3u8
. Let’s replace stream_name with “pattern” and channel_name with “0”. This makes our final URL http://localhost:8083/stream/pattern/channel/0/hls/live/index.m3u8
.
Let’s add our VideoFeed component into our main App.tsx file with the correct src.
Now when we refresh our page, we should be able to see our RTSP feed appropriately in our web browser!
Conclusion
RTSP is a pain in the butt, but it doesn’t have to be so difficult with these wonderful open source projects. Like I said before, there are a few ways around this problem. If this method didn’t work for you, then I highly recommend checking out this article detailing a similar approach with FFMPEG, this project called rtsp-simple-server, or this method using VLC.
If you just want to check out the finished code from this article, check out the code repository here. Follow the instructions in the README and you should be good to go.