DEV Community

Cover image for How to Code a Video Streaming Server using NodeJS

How to Code a Video Streaming Server using NodeJS

Abdisalan on October 25, 2020

Do you want to stream video in your app without needing users to download the entire video? Here's how to do exactly that using NodeJS. F...
 
dgiulian profile image
Diego Giuliani

right, makes sense. That's what happens when you have a small hiccup in the network and the stream lowers the quality for a moment and resets back to a better quality when it gets better.
Thanks for your reply.

Collapse
 
patriciooncode profile image
Patricio

Hey Abdisalan! Great one!
I made the project from scratch from the article, and then noticed it was missing the "require fs". in the repo that's all ok, just the article misses it.
Other than that, perfect start. I'm starting my journey into video and streaming, and was an excellent start! Is this a main interest of yours?

Collapse
 
abdisalan_js profile image
Abdisalan

I love it! Glad to have helped you get started! I'll try to fix that issue!

Collapse
 
anandbej profile image
anandkumar

I'm not able to stream the video. I'm getting the "Requires Range header" response.
I tried doing const range = "bytes=0-1023"; but that didnt work too. The player just appears and doesnt play the video

Collapse
 
gazee profile image
gazee

i also got same erroot

how it is solve .did u got it?

Collapse
 
cybergen49 profile image
Cyber

I ran into the same error. The fix seems to be to set your Content-Type header before checking for Range.

Collapse
 
dgiulian profile image
Diego Giuliani

wouldn't that require extra processing power? I thought what they did was generate multiple versions of the file and pick one accordingly to the required bandwidth and quality

Collapse
 
elliot__c8f94cdeeaa8d318b profile image
Elliot • Edited

Thanks for this. The way it's written works in Chrome but not Safari. To make it work in Safari I had to modify the code from this:

  const CHUNK_SIZE = 10 ** 6; // 1MB
  const start = Number(range.replace(/\D/g, ""));
  const end = Math.min(start + CHUNK_SIZE, videoSize - 1); 
Enter fullscreen mode Exit fullscreen mode

To this:

   //Safari range header has start and end, vs. Chrome has just start
   let parts = range.split('=')[1]
   let start = Number(parts.split('-')[0])
   let end = Number(parts.split('-')[1])

   //For Chrome
   if (!end) {
       const CHUNK_SIZE = 10 ** 6
       end = Math.min(start + CHUNK_SIZE, videoSize - 1)
   } 
Enter fullscreen mode Exit fullscreen mode
Collapse
 
cybergen49 profile image
Cyber

Just came across this post while searching for exactly this, and I'm happy to report that all has gone smoothly! I refactored the code a bit to work with Node's built-in http module, since that's what the rest of my project is using, and made a couple changes to ensure downloading (via the default video player's Download option) works correctly.

Collapse
 
rizadwiandhika profile image
Riza Dwi

Great articles! Really insightful to me since i'm starting curious in streaming

I wonder that if this stream way uses http protocol, does this mean we use tcp protocol ?

I just recently learned about tcp & udp protocols
where one of the usecases of udp is to serve connectionless data transfer (which is perfect in this video streaming case)

Collapse
 
csandman profile image
Christopher Sandvik

"For a chunk size, I've decided 1MB but you could change that to whatever you like!"

Is there any info on how to decide a chunk size? I've seen 1MB in a few articles but I haven't seen any reasons for it.

Collapse
 
abdisalan_js profile image
Abdisalan

Wow I never knew, that’s cool!

Collapse
 
shahinghasemi profile image
shahinghasemi

does fs.createReadStream uses sockets under the hood?

Collapse
 
xubmuajkub profile image
xubmuajkub

Great work! Can you also do the example of play video from remote? e.g example.com/video.mp4

Collapse
 
rmfranciacastillo profile image
Renato Francia Castillo

Nice! Love that you used Node instead of some middleware. Keep it up Abdi!

Collapse
 
abdisalan_js profile image
Abdisalan

Thanks!

Collapse
 
kanhasonu21 profile image
Kanhaiya Kumar

How can we access the URL in frontend if we make this API protected by adding a middleware

Collapse
 
anztrax profile image
andrew ananta

wow. this is awesome... thanks for sharing bro

Collapse
 
elbigans04 profile image
rhafael bijaksana

thank man. this is very helpful

Collapse
 
lokuedo5000 profile image
Brayan

Hi, I want to do that, but with webtorrent, how do I do that?

Collapse
 
bharathvajganesan profile image
Bharathvaj

Modern browser like Chrome does this video streaming by default. 🤔

Collapse
 
son0nline profile image
Son0nline

Pls help, I'm tried with 600MB video
It ok in localhost but failed in LAN

Collapse
 
acagastya profile image
Agastya

Were you trying it on iOS/Safari by any chance? I faced the problem when trying to make it work on iOS, so I followed this blog.logrocket.com/streaming-video.... Safari-based browsers need a different way of handling things.

Collapse
 
nimaessi profile image
nima essi

error net::ERR_FILE_NOT_FOUND

Collapse
 
vrobbi profile image
vrobbi

Works perfectly with my own .mp4 files, thank you

Collapse
 
prernapahwa profile image
Prerna-Pahwa • Edited

Nice article...but I am unable to stream the video. It's showing just blank with the disabled play button. pls refer the screenshot i attached below.

Collapse
 
omadoyeabraham profile image
omadoyeabraham

@prernapahwa I had a similar issue and the problem for me ended up being that the options object passed to fs.createReadStream as the 2nd parameter requires the keys to be 'start' and 'end'.

So if you renamed the start and end variables from the tutorial (like i did), you'll need to explicitly pass them to the createReadStream call, e.g.

fs.createReadStream(videoPath, { start: STARTING_BYTE_POSITION, end: FINAL_BYTE_POSITION });
Enter fullscreen mode Exit fullscreen mode

NB: STARTING_BYTE_POSITION and FINAL_BYTE_POSITION are the names of my own variables, you'll need to replace them with yours.

I also noticed that typos in headers also caused the blank video player error you described. Hope this helps.

Collapse
 
yas1n67 profile image
yas1n67

How can play more than one video?

Collapse
 
yas1n67 profile image
yas1n67

How can I stream two different videos?