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
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
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}`
)
})
Run the server
node index.js
server listening commands at http://127.0.0.1:3000
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>
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,
})
})
}
})()
Try!
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)