Error 500 de transmisión de video en producción (NextJS)
He estado desarrollando este sitio: https://mirobod-tumani.vercel.app. En la página de inicio hay un video de fondo. Para optimizar la carga inicial, optimicé el propio video y decidí transmitirlo.
Este es el código:
// pages/api/video
import fs from 'fs'
export default function handler(req, res) {
if (req.method === 'GET') {
const range = req.headers.range
const videoPath = 'public/assets/mirobod.webm'
const videoSize = fs.statSync(videoPath).size
const chunkSize = 1 * 1e6
const start = Number(range.replace(/\D/g, ''))
const end = Math.min(start + chunkSize, videoSize - 1)
const contentLength = end - start + 1
const headers = {
'Content-Range': `bytes ${start}-${end}/${videoSize}`,
'Accept-Ranges': 'bytes',
'Content-Length': contentLength,
'Content-Type': 'video/webm',
}
res.writeHead(206, headers)
const stream = fs.createReadStream(videoPath, { start, end })
stream.pipe(res)
}
}
// pages/index.js
<video autoplay="" muted="" loop="">
<source src='/api/video' type='video/webm'>
</video>
Localmente, cuando navego a la raíz localhost:3000/
, funciona como espero, pero cuando intento abrir esa API /api/video
de manera diferente, por ejemplo, cuando navego a localhost:3000/api/video
o la llamo en Postman, aparece un error que dice “No se puede leer la propiedad ‘replace’ de undefined”, entiendo que req.headers.range
es undefined
. Además, en producción hay un error 500 con esa API y no muestra el video, como se puede ver en el enlace del sitio anterior.
He intentado:
if(!req.headers.range) // enviar todo el video de una vez
else ...
Pero en este caso, esto no es lo que quiero de la transmisión y también esto lleva a “Exceeding Serverless Function Payload Size Limit”.
Entonces, ¿cuál es el problema, qué debo hacer? ¡Gracias de antemano!
davy.ai
El problema es que
req.headers.range
esundefined
cuando se accede directamente a/api/video
o desde un cliente que no sea un reproductor de video, como Postman. El código asume querange
existe e intenta reemplazar todos los caracteres no numéricos por una cadena vacía, lo cual causa el error.Para solucionar esto, debes verificar si
range
existe antes de usarlo. Una forma de hacerlo es agregar una condición antes de la líneaconst start=
:Esto establece el valor de start en 0 y end en videoSize – 1 si range no está presente. También puedes considerar devolver una respuesta de error con el código de estado adecuado (por ejemplo, 400 Bad Request) cuando range esté ausente o sea inválido.
En cuanto al error 500 en producción, debes verificar los registros en busca de mensajes de error o excepciones lanzadas por el código. Es posible que haya otros problemas que impidan que el video se reproduzca correctamente.