生产中的视频流 500 错误 (NextJS)

Video Streaming 500 error in production (NextJS)

我一直在开发这个网站:https://mirobod-tumani.vercel.app。在主页上有一个视频背景。为了优化初始负载,我优化了视频本身并决定将其流式传输。 这是代码:

// 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>

在本地,当我导航到根 localhost:3000/ 时,它按我预期的那样工作, 但是当我尝试以不同的方式打开 /api/video api 时,例如,当我导航到 localhost:3000/api/video 或在 Postman 中调用它时,出现错误 Cannot read property 'replace' of undefined,我不明白req.headers.rangeundefined。同样在生产中,api 出现 500 错误,并且没有显示视频,正如您在上面的网站 link 中看到的那样。

我试过了:

if(!req.headers.range) // send the whole video at one

else ...

但在这种情况下,这不是我想要的流媒体,而且这导致 Exceeding Serverless Function Payload Size Limit

请问这是什么问题,我该怎么办?提前致谢!

正如错误所解释的那样,您 运行 限制了一个免费的 vercel 函数可以执行多少 - 视频流最好用可以处理该传输的主机或桶来处理 - 我建议托管它其他地方 https://cloudinary.com/pricing 有免费计划

从这个 post 开始,免费计划可以满足您的需求

25K transformations or 25 GB of managed storage or 25 GB of net viewing bandwidth

开发流式视频解决方案需要相关资源,您部署代码的主机不应该解决免费版本中的视频流。

我找到了答案,将其张贴给遇到同样问题的人。

根据我的理解https://www.w3.org/Protocols/rfc2616/rfc2616-sec14.html#sec14.27

req.headers.range 可能未针对初始请求设置,但在流传输期间可用。
实际上,初始范围等于 'bytes=0-',并根据您定义的块大小

在流期间更新

原来如此:

let range = req.headers.range
if(!range) range = 'bytes=0-'

...

但是还是有问题 我以为是关于路径的,然后我改了这个:

const videoPath = 'public/assets/mirobod.webm'

对此:

const videoName = 'mirobod.webm'
const videoPath = path.resolve('public/assets/', videoName)

成功了!