node+eggjs推送视频流并观察B站视频流分块方式,自己的视频播放时无法快进问题?
发布于 3 年前 作者 evilArsh 2575 次浏览 来自 问答

用了eggjs,后台完全是RESTful api。播放视频时根本不能快进,一快进视频就停止了。只能重新播放。 http头Content-Rang也设置了的。 在浏览器输入http://127.0.0.1:7001/api/resources/9.mp4 下图是播放的视频 image.png 但是这个视频它只能播放3秒,播放3秒之后就卡住了,我打开了chrome控制台查看网络请求。

  1. 这是第一次请求的图片截图: (图1) image.png 可以看到在Request Headers中并没有 Range:bytes 0-字段。因为我在后端代码中判断前台发送的http请求头中是否有 range,如果没有的话我在响应头中设置以下默认值:

    	let header = {
                'Accept-Ranges': 'bytes',
                'Content-Type': type,
                'Content-Length': 视频文件的大小,
                'Content-Range': `bytes 0-视频文件的大小/视频文件的大小`,
                "cache-control":'public,max-age=31536000'
            };
    

    在(图1)中的Response Headers中可以看到以上默认字段 这时后端控制台打印如下图: (图1.1) image.png 2.这是第二次请求的图片截图 (图2) image.png

    Response Headers中的值并没有变,但是Request Headers中出现了Range: bytes=0-字段 后端打印和(图1.1)一样,但是时间戳多了一秒,如下图: 图(2.1) image.png 3.这是第三次请求的图片截图 (图3) image.png

    以下是疑问: 1. Request HeadersRange: bytes=23035904- "23035904"数字怎么来的 后台打印的如下图: (图3.1) image.png 最后后台也没有打印,视频在这3次请求中一直在播放,只放了3秒,视频就终止了。

然后我又打开了一个窗口,在浏览器输入http://127.0.0.1:7001/api/resources/9.mp4 后台打印如下图 (图4) image.png 视频一直在播放,下图是控制台请求的图片 (图4.1) image.png 上图中138Mb部分一直在增加 请求头和响应头如下图 (图4.2) image.png 现在我来把视频进度条往后拉,前端后端状态如下(图4.3)(图4.4): (图4.3) image.png (图4.4) image.png 这时视频停止播放了,后台也没有打印数据了。 以下是后端代码代码。

    //type "video/mp4"
    video(filePath, type) {
        const { ctx, app } = this;
        if (!(/video/.test(type))) {
            return;
        }
        let fileSize = fs.statSync(filePath).size;
        let step=parseInt(fileSize/100);
            let start = ctx.get('range').substr(ctx.get('range').indexOf('=') + 1, ctx.get('range').indexOf('-') - 1),
                end = ctx.get('range').substr(ctx.get('range').indexOf('-') + 1);
            start = parseInt(start);
            end = parseInt(end);

            if (isNaN(start)) {
                start=0;
            }
            if (isNaN(end)) {
                end = fileSize - 1;
                // end=start+step>=fileSize?fileSize-1:start+step;
            }
            console.log('**************************')
            console.log('start-end', start,'-',end)
            console.log('**************************')
            ctx.status = 206;
            let header = {
                'Accept-Ranges': 'bytes',
                'Content-Type': type,
                'Content-Length': end - start + 1,
                'Content-Range': `bytes ${start}-${end}/${fileSize}`,
                "cache-control":'public,max-age=31536000'
            };
            ctx.set(header);

            ctx.body = fs.createReadStream(filePath, {
                satrt: start,
                end: end,
                autoClose:true
            });
    }

现在我去B站随便找一个视频看他的网络状况,我随机往后点击进度条 Request Headers中第一次出现range的请求如下图 image.png 我不知道为什么Range: bytes=1008-1735初始bytes不是0而是1008 前台显示如下系列图(部分): image.png image.png image.png 三次请求中 一.Request Headers中的 range分为三段连续的 ->1.Range: bytes=12265533-12871199 ->2.Range: bytes=12871200-13386314 ->3.Range: bytes=13386315-13922958 二.Response Headers中的 Content-Range同理也分为三段连续的 ->1.Content-Range: bytes=12265533-12871199/33430066 ->2.Content-Range: bytes=12871200-13386314/33430066 ->3.Content-Range: bytes=13386315-13922958/33430066 这样的实现了向后快进播放。 1.为啥我的就不可以快进, 2.为啥我的Range直接是Range: bytes=0-视频文件大小,并没没有分块,但我们的Status Code:都是206

10 回复

这个错误 ERROR 112264 [-/127.0.0.1/-/21ms GET /api/resources/9.mp4] nodejs.ECONNABORTEDError: write ECONNABORTED到底是什么鬼

start not strat

@MiYogurt 什么意思?兄弟你知道这个问题该怎么解决吗

fs.createReadStream(filePath, {
            start: <number>start,
            end: end,
            autoClose: false
        })

@MiYogurt 谢谢老哥指正,虽然现在可以快进了,但是要是点击进度条的跨度太大的话,也会终止.后台也没有任何打印。 还有就是B站的加载视频是一个块一个块加载的,他是怎么搞的啊

  config.onerror = {
    appErrorFilter(err, ctx) {
      const errnoCodeWhitelist = ['EPIPE'];
      if (errnoCodeWhitelist.includes(err.errno)) {
        return false
      }
      return true
    },
  };

不是终止,是继续去拉取,我测试的都是 20mb 左右的,我这里都可以正常播放。 块加载跟播放器有关,没研究过。

B站用的是http-flv了解下 自豪地采用 CNodeJS ionic

回到顶部