We have prepared a simple solution for processing real-time data from GPS devices for one of our customers. Devices communicate on two different ports, one for GPS data and the second for binary data like live video streaming or recorded incident videos. And this blog post will be about live video streaming on the Node.js platform and with the help of the Total.js framework.
We have created a small Total.js video service with a TCP server that can be clusterized. The video service receives text messages combined with binary data. So, the binary data for live stream video contains chunks of H264 videos, such as I-FRAMES and B-FRAMES (P-FRAMES are missing).
Collected video data isn't playable (maybe the problem can be in missing P-FRAMES). So our service collects chunks and divides them into small 100-150 kB files. In addition, each file contains between 3-8 seconds of video. Then our service converts these files via FFMPEG into the Video Transport Stream File with the
.ts extension, and after the end, the service prepares the
m3u8 file with the list of last processed videos. A duration for converting videos takes around ~3-10 seconds via FFMPEG, but it depends on the video quality and server hardware.
Here is the content of one of our m3u8 lists:
All video files are handled by another app called HTTP Video Server that can be clusterized quickly too. However, the HTTP Video Server app sends only existing
.ts videos and
m3u8 lists to all online clients.
m3u8 content works on all modern web browsers like Chrome, Safari, iPhone Safari, Android Chrome, and directly in the QuickTime or VLC player.
We had problems with the Chromium browsers because a browser played only the first video and then stopped. Also, we solved the problem by adding the
#EXT-X-DISCONTINUITY phrase. One more important thing is that Chromium browsers are sensitive to the exact video duration defined in the
We have tested browser compatibility with the help of this web application: https://m3u8player.net. Here is a small screenshot from our test environment: