nodejs大文件合并遇到的问题

18 阅读1分钟

话不多说先看第一个有毛病的代码 这是使用pipeline的并行合并,合成出来的视频有时候可以播放,有时候不行,求请教

    Promise.all(
      all_chunks.map(item => {
        // 开始写的位置
        const start = item * chunkSize
        console.log(start)
        // 使用管道连接读流和写流
        return new Promise((resolve, reject) => {
          pipeline(
            fs.createReadStream(`${CHUNK_PATH}/${md5}/${item}`),
            fs.createWriteStream(`${VIDEO_PATH}/${md5}`, {
              flags: 'w+',
              start: start,
              autoClose: true
            }),
            err => {
              if (!err) {
                resolve('success')
              }
              console.log(err)
            }
          )
        })
      })
    ).then(() => {
      fs.rename(`${VIDEO_PATH}/${md5}`, `${VIDEO_PATH}/${md5}.mp4`, () => {})
    })

这是获取的文件

image.png

然后我以为是并行合并的问题,然后我就使用串行合并,也就是for循坏,但视频也不能播放

    // 进行串行合并操作
    for (let i = 0; i < all_chunks.length; i++) {
      pipeline(
        fs.createReadStream(`${CHUNK_PATH}/${md5}/${all_chunks[i]}`),
        fs.createWriteStream(`${VIDEO_PATH}/${md5}`, {
          flags: 'a',
          autoClose: true
        }),
        err => {
          if (err) {
            console.log(err)
          }
        }
      )
    }

最后我使用了,pipe的递归合并,视频就可以播放,但官网推荐使用pipeline,说更安全,有大佬能发现bug吗

this.streamMergeRecursive(all_chunks, fs.createWriteStream(`${VIDEO_PATH}/${md5}.mp4`, { flags: 'w+' }), `${CHUNK_PATH}/${md5}`)

该函数的内容

  // 递归合并切片
  streamMergeRecursive(chunk_list = [], fileWriteStream, chunks_path) {
    // 递归到尾部情况判断
    if (!chunk_list.length) {
      return fileWriteStream.end("console.log('Stream 合并完成')") // 最后关闭可写流,防止内存泄漏
    }

    const currentFile = `${chunks_path}/${chunk_list.shift()}` // 获取当前文件路径

    const currentReadStream = fs.createReadStream(currentFile) // 获取当前的可读流

    currentReadStream.pipe(fileWriteStream, { end: false })

    currentReadStream.on('end', () => {
      this.streamMergeRecursive(chunk_list, fileWriteStream, chunks_path)
    })

    currentReadStream.on('error', function (error) {
      // 监听错误事件,关闭可写流,防止内存泄漏
      console.error(error)
      fileWriteStream.close()
    })
  }