Bun does not support streaming videos with range requests
What version of Bun is running?
1.1.4
What platform is your computer?
Darwin 23.4.0 arm64 arm
What steps can reproduce the bug?
I created a sample http server using express that streams videos with range requests, but it seems that bun is not able to handle it and the request is loading indefinitely.
here is an express sample project code:
server.js
import express from 'express'
import fs from 'fs'
console.log('Starting server...')
const port = 3000
const app = express()
app.use(express.static('public'))
app.get('/video', function (req, res) {
try {
const range = req.headers.range
if (!range) {
res.status(416).send('Requires Range header')
return
}
const videoPath = 'local-file-path.mp4'
const size = fs.statSync(videoPath).size
const CHUNK_SIZE = 2 * (10 ** 6) // 2MB each chunk
const start = Number(range.replace(/\D/g, '')) // starting point from the request range
const end = Math.min(start + CHUNK_SIZE, size - 1) // ending point
const contentLength = end - start + 1
res.writeHead(206, {
'Content-Range': `bytes ${start}-${end}/${size}`,
'Accept-Ranges': 'bytes',
'Content-Length': contentLength,
'Content-Type': 'video/mp4',
'Access-Control-Allow-Origin': '*',
})
const videoStream = fs.createReadStream(videoPath, { start, end })
videoStream.pipe(res)
} catch (e) {
console.error('failed to get video:', e)
res.status(500)
}
})
app.listen(port, function () {
console.log(`Listening on port ${port}...`)
})
also, index.html:
<!DOCTYPE html>
<html lang="en">
<body>
<video style="width: 100vw; height: 100vh" controls autofocus>
<source src="/video">
</video>
</body>
</html>
Using Bun.file
I tried also using the standard Bun way with Bun.file('path'), it seems to download the entire file instead of serving the requested range.
What is the expected behavior?
I'm expecting bun to support every use case of video streaming
- supporting
expresslibrary - supporting with
Bun.file('path')
What do you see instead?
- with
expressexample: The request is indefinite, and does not ever ends - using
Bun.file(withBun.serve): The video file is served from beginning before video reaching the requested start-range
Additional information
I also tried it with Elysia to be sure there is no workaround with a supporting framework, I got the similar result as using only Bun.serve with Bun.file
server.ts: (serving identical index.html for the client)
import { Elysia } from 'elysia'
import { staticPlugin } from '@elysiajs/static'
const app = new Elysia()
.get('/', Bun.file('public/index.html')
.get('/video', Bun.file('local-file-path.mp4'))
.listen(3000)
console.log(
`🦊 Elysia is running at ${app.server?.hostname}:${app.server?.port}`,
)
Sadly there is no way to slice a Bun.file (yet)
I'm pretty sure we have tests that verify this works
oh this is using express, that makes more sense
@Jarred-Sumner
I'm pretty sure we have tests that verify this works
Can you direct me to an example?
I think it's this example?
Fixed in Bun v1.1.9
Note the current version of Bun is Bun v1.2.5. We are a little behind on issues.