DEV Community

German Cyganov
German Cyganov

Posted on • Originally published at Medium

RTCP stream in HTML throught WebSocket

In this article we will create an application that will output the RTCP stream to an HTML page

To convert video we will use the node-rtsp-stream server, it will convert RTCP to MPEG1 and pass the result to WebSocket. Internally it uses ffmpeg so you will need to install it

We will use jsmpeg to display the video on the page

Download minified version of jsmpeg and put it in the libs folder next to the index.html file

Also to change the link to the stream we need Express

Architecture overview

So we need to implement a server on Node.js which will, at the request of the client, start the transformation of the stream and response with a link as a result

Implementing the server

Create a folder where the server will be stored and install the dependencies

mkdir socket-server && cs socket-server
npm init -y
npm i node-rtsp-stream express cors
Enter fullscreen mode Exit fullscreen mode

Let’s write code in which we will create an express application with the /start route, which when called will create a new instance of the streaming server with a given link to the stream

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

const app = express()

app.use(cors())
app.use(express.json())

const port = 3000
const wsPort = 9999

let stream = null

app.post('/start', function (req, res) {
  if (stream !== null) {
    stream.stop()
    stream = null
  }

  const { streamUrl } = req.body

  try {
    stream = new Stream({
      name: 'videoStream',
      streamUrl: streamUrl,
      wsPort: wsPort,
      ffmpegOptions: {
        '-stats': '',
        '-r': 30,
      },
    })
    res.json({ url: `ws://127.0.0.1:${wsPort}` })
  } catch (e) {
    console.error(e)
  }
})

app.listen(port, () => {
  console.log(
    `server listening commands at http://127.0.0.1:${port} and serve stream at ws://127.0.0.1:${wsPort}`
  )
})
Enter fullscreen mode Exit fullscreen mode

Run the server

node index.js
server listening commands at http://127.0.0.1:3000
Enter fullscreen mode Exit fullscreen mode

The server started successfully, to start the broadcast you need to send a POST request with a link to the stream to the address http://127.0.0.1:3000/start

Implementing the client

Create a simple index.html file where we’ll add a container for embedding the video stream. The entry field for the link to the RTCP stream and the button to start playing a new stream, as well as don’t forget to connect jsmpeg to play the video and index.js, which will contain all the logic

<!DOCTYPE html>
<html lang="en">
  <head>
    <meta charset="UTF-8" />
    <meta http-equiv="X-UA-Compatible" content="IE=edge" />
    <meta name="viewport" content="width=device-width, initial-scale=1.0" />
    <link rel="stylesheet" href="css/main.css" />
    <title>Video Stream</title>
  </head>
  <body>
    <div id="container" class="player">
      <div id="video-container" class="video"></div>
      <div class="stream-input">
        <input
          id="stream-url-input"
          type="text"
          name="stream-url-input"
          value="rtsp://wowzaec2demo.streamlock.net/vod/mp4:BigBuckBunny_115k.mov"
          placeholder="stream url"
        />
        <input id="stream-play-btn" type="button" value="Play" />
      </div>
    </div>
  </body>
  <script type="text/javascript" src="libs/jsmpeg.min.js"></script>
  <script type="text/javascript" src="js/index.js"></script>
</html>
Enter fullscreen mode Exit fullscreen mode

Write the logic

When the Play button pressed, send a request with the streamUrl parameter to /start route of our server, upon receiving a reply we create a player that plays the video with the link given by the server response

;(function () {
  let jsmpegPlayer
  const streamInput = document.getElementById('stream-url-input')
  const playBtn = document.getElementById('stream-play-btn')
  const videoContainer = document.getElementById('video-container')

  playBtn.onclick = () => {
    const streamUrl = streamInput.value
    fetch('http://127.0.0.1:3000/start', {
      method: 'POST',
      headers: {
        'Content-Type': 'application/json;charset=utf-8',
      },
      body: JSON.stringify({ streamUrl }),
    })
      .then((response) => response.json())
      .then((data) => {
        if (jsmpegPlayer) {
          jsmpegPlayer.stop()
          jsmpegPlayer.destroy()
        }

        const canvas = document.createElement('canvas')
        canvas.id = 'jsmpeg-player'
        videoContainer.app(canvas)

        jsmpegPlayer = new JSMpeg.Player(data.url, {
          canvas,
          autoplay: true,
        })
      })
  }
})()
Enter fullscreen mode Exit fullscreen mode

Try!

Example

As you can see the streaming video appears with a pretty long delay, about 12 seconds. This may be enough, but if you want to reduce the delay of the stream and get closer to real time read the next article in which we will try to reduce that delay

Complete code can be found on GitHub

Top comments (0)