项目用的是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关闭或销毁可读流,但是仍然出现这个问题。除非我重启应用实例,重启后第一播放没问题,第二次有问题。这个问题困扰了我好几天,但一直没有找到方法解决,请问这个问题如何解决?希望有处理过类似问题的大佬能指点迷津,如能解决,红包答谢!万分感谢,万分感谢,万分感谢。
参考GPT和自己的思路:
通过分析你提供的代码,发现在视频播放的过程中,每次读取1M的数据后,对第1M数据进行了解密处理,并将处理后的数据流传给了bufferStream,从bufferStream中pipe到了res。在第二次播放时,你发现chunk的长度只有262144,也就是只有1/4的数据被读取了,并且数据部分发生了变化,因此导致了问题。
这个问题可能是由于可读流没有及时关闭导致的。在代码中,可以看到使用了rs.unpipe()和rs.destroy()来关闭可读流,但是仍然没有解决问题。你可以尝试使用rs.close()方法关闭可读流,同时也可以将可读流的高水位线(highWaterMark)设为0来避免触发后续的data事件。同时,为了提高代码的健壮性和可读性,建议使用try-catch语句块来处理可读流的异常,例如:
try {
rs.close();
} catch (err) {
console.log('Error closing read stream:', err.message);
}
另外,在代码中使用了Stream.PassThrough()实例来创建可写流,建议使用WritableStream的子类Transform,它不仅可以读取数据,还可以对数据进行处理后输出,能够更好地满足你的需求。