u010361664
小小菜鸟-
2021-03-02 09:50

nodejs关闭可读流的问题,无法关闭,导致视频播放有问题?

项目用的是electron-vue的脚手架开发,electron版本为2.04,本机的node版本为14.12.0。electron升级后electron为11.3.0,node版本不变。升级前视频可以正常播放,升级后第一次播放视频正常,第二次播放出现问题,下面为代码逻辑

const highWaterMark = 1024 * 1024
function decodefiletostream (req, res, fileInfo) {
   //  log.debug('decodefiletostream', fileInfo.filepath)
    let file = path.resolve(fileInfo.filepath)
    let rs = fs.createReadStream(file, {highWaterMark: highWaterMark, autoClose: true, eimtClose: true})
    let head = {
      'Content-Type': fileInfo.c
    }
    let skey = decrypt(fileInfo.s)
    // log.debug('decodefiletostream-->skey', skey)
    // 需要设置HTTP HEAD
    res.writeHead(206, head)
    let bufferStream = new Stream.PassThrough()
    let counter = 0
    let counterSize = 0
    rs.on('data', function (chunk) {
      counter++
      counterSize += chunk.length
      log.info('00000000000000?????', chunk.length, skey, 'hightwatermark???', highWaterMark)
        // log.debug('chunk', chunk.length, skey)
        // 如果加密标志是0,则是非加密文件
        // 功能更新: 视频头部加密1M内容, 所以highWaterMark的数值以后都不能改了 (2/19/2021)
        if (fileInfo.f === '0' || skey === '') {
          log.info('1111111?????', chunk.length)
            let flag = bufferStream.write(chunk)
            if (!flag) {
              rs.pause()
            }
        } else {
          // 否则是加密文件
          let tmp = new Array(chunk.length)
          log.info('22222222?????', chunk.length, 'tmp length', tmp.length)
            for (let i = 0; i < chunk.length; i++) {
                tmp[i] = chunk[i] - parseInt(skey.charAt((i + 1) % 32), 16)
            }
            skey = ''
            let flag = bufferStream.write(Buffer.from(tmp))
            if (!flag) {
              rs.pause()
            }
        }
    })
    bufferStream.on('drain', function () {
      log.info('buffer drain')
      rs.resume()
    })
    rs.on('close', function () {
      log.info('res close', counter, counterSize)
    })
    rs.on('end', function () {
      log.info('res end', counter, counterSize)
      bufferStream.end()
      rs.unpipe()
      rs.destroy()
    })
    bufferStream.pipe(res)
}

一次可读写流完成,上面的逻辑写入流的drain事件,可读流的end,close都正常监听到。可读流的data事件每次读取1M数据,每次播放对第1M数据做了解密处理,后续流为源数据。在data事件中,打印chunk长度发现了问题。
第一次播放流处理完成时的日志信息

第二次播发流处理开始时的日志信息

第二次播放处理流结束时的日志信息

已经尝试用unpipe和destroy关闭或销毁可读流,但是仍然出现这个问题。除非我重启应用实例,重启后第一播放没问题,第二次有问题。这个问题困扰了我好几天,但一直没有找到方法解决,请问这个问题如何解决?希望有处理过类似问题的大佬能指点迷津,如能解决,红包答谢!万分感谢,万分感谢,万分感谢。

  • 点赞
  • 写回答
  • 关注问题
  • 收藏
  • 复制链接分享
  • 邀请回答

为你推荐