首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >问答首页 >尝试用管道从ERR_STREAM_PREMATURE_CLOSE服务器流视频时获取错误的Node.JS

尝试用管道从ERR_STREAM_PREMATURE_CLOSE服务器流视频时获取错误的Node.JS
EN

Stack Overflow用户
提问于 2022-01-29 21:28:24
回答 1查看 373关注 0票数 0

我试图使用流库的管道功能将视频从服务器流流到浏览器。这是一个相当大的视频(88.7MB),这意味着我想将它以5MB块的形式流到浏览器。我根据一些在线教程创建了服务器,但是我注意到有一些奇怪的行为,流被过早关闭(因为浏览器决定在发送第一部分之前就想要视频的最后一部分)。

这是输出:

代码语言:javascript
运行
复制
21:01:29.215   Server is running on http://192.168.1.180:80
21:01:33.562   --------------------------------- New Request ---------------------------------
21:01:33.563   No range specified.
21:01:33.624   --------------------------------- New Request ---------------------------------
21:01:33.625   ( 1 )  Starting Pipe  | Browser requested:  bytes=0-  | Start:  0  | End:  5242880  | Content Length:  5242881  | Content Range:  bytes 0-5242880/93008043  | Video Size:  93008043
21:01:33.625   ( 1 )  Pipeline created
21:01:33.710   --------------------------------- New Request ---------------------------------
21:01:33.710   ( 2 )  Starting Pipe  | Browser requested:  bytes=92798976-  | Start:  92798976  | End:  93008042  | Content Length:  209067  | Content Range:  bytes 92798976-93008042/93008043  | Video Size:  93008043
21:01:33.711   ( 2 )  Pipeline created
21:01:33.711   ( 1 )  Pipeline error:  
21:01:33.711   Error [ERR_STREAM_PREMATURE_CLOSE]: Premature close
                   at new NodeError (node:internal/errors:371:5)
                   at ServerResponse.onclose (node:internal/streams/end-of-stream:139:30)
                   at ServerResponse.emit (node:events:532:35)
                   at emitCloseNT (node:_http_server:845:10)
                   at Socket.onServerResponseClose (node:_http_server:233:5)
                   at Socket.emit (node:events:532:35)
                   at TCP.<anonymous> (node:net:687:12)
                   at TCP.callbackTrampoline (node:internal/async_hooks:130:17)

21:01:33.715   ( 2 )  Pipeline success

正如您在上面看到的那样,浏览器最初请求视频的第一个字节,但在60 As之后(甚至在数据被发送之前),它会为视频(?)的最后部分创建第二个管道请求。这毫无意义。这会导致第一个管道出错,我不知道如何修复这个问题。(发送较小的块不是一个选项)。

我注意到的另一件事是,它没有尽快发送所有的数据,它所做的只是等到浏览器说它想要更多的数据(而不是立即发送)。

当其他设备试图同时观看视频(或从多个选项卡观看)时,我没有注意到出现了这个错误,所以我想知道是否导致了这个错误,因为它不能创建到同一个选项卡/设备/源的两个管道。

以下是我的服务器代码:

代码语言:javascript
运行
复制
const http = require("http");
const path = require("path");
const { statSync, createReadStream } = require("fs");
const { pipeline } = require("stream")
const print = require("./../../mods/print.js")

const host = "192.168.1.180";
const port = 80;

let pipe_number = 0;
let chunk_size = 1024*1024*5
let video_path = path.normalize(__dirname + "/video.mp4")

http.createServer((req, res) => {
    print(`--------------------------------- New Request ---------------------------------`)
    const { range } = req.headers
    const { size } = statSync(video_path)
    if (range) {
        pipe_number++
        let this_pipe = pipe_number
        const parts = range.replace(/bytes=/, "").split("-")
        const start = parseInt(parts[0], 10)
        const end = parts[1] ? parseInt(parts[1], 10) : Math.min(start + chunk_size, size - 1)
        
        const content_length = (end-start) + 1
        const head = {
            "Content-Range": `bytes ${start}-${end}/${size}`,
            "Accept-Ranges": `bytes`,
            "Content-Length": content_length,
            "Content-Type": `video/mp4`
        };
        print(`( ${this_pipe} )`, `Starting Pipe`, "| Browser requested:", range, "| Start:", start, "| End:", end, "| Content Length:", content_length, "| Content Range:", `bytes ${start}-${end}/${size}`,"| Video Size:", size)

        const file = createReadStream(video_path, {start, end})

        res.writeHead(206, head);

        print(`( ${this_pipe} )`, "Pipeline created")
        pipeline(file, res, (err) => {
            if (err) {
                print(`( ${this_pipe} )`, "Pipeline error:", err)
            } else {
                print(`( ${this_pipe} )`, "Pipeline success")
        }
    })
    } else {
        print("No range specified.")
        const head = {
            'Content-Length': 0,
            'Content-Type': 'video/mp4',
        };
        res.writeHead(200, head)
        res.end()
    }
}).listen(port, host, () => {print(`Server is running on http://${host}:${port}`)})

我从网上教程中得到了大部分这些,因为这对我来说是新的东西。我这里也不使用express.js。

EN

回答 1

Stack Overflow用户

发布于 2022-09-09 21:28:59

现在,您可能已经发现了这个问题,但对于未来的googlers人员来说,我遇到了这个问题,结果发现错误的内容被写入响应(开始/结束字节不存在,所以整个文件都在编写中)。

另外,https://github.com/vercel/serve-handler/blob/master/src/index.js对于如何正确返回206/416响应也有很好的参考价值。

票数 1
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/70909887

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档