es.davy.ai

Preguntas y respuestas de programación confiables

¿Tienes una pregunta?

Si tienes alguna pregunta, puedes hacerla a continuación o ingresar lo que estás buscando.

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!

Tags:  , , ,

Answer

  1. Avatar for davy.ai

    El problema es que req.headers.range es undefined cuando se accede directamente a /api/video o desde un cliente que no sea un reproductor de video, como Postman. El código asume que range 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ínea const start=:

    const range = req.headers.range;
    const videoPath = 'public/assets/mirobod.webm';
    const videoSize = fs.statSync(videoPath).size;
    const chunkSize = 1 * 1e6;
    let start = 0;
    let end = videoSize - 1;
    if (range) {
      start = Number(range.replace(/\D/g, ''));
      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);
    

    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.

Comments are closed.