You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Node.js如何将接收的音频流分片写入多个单文件100MB的文件

Node.js 音频流拆分存储100MB分片文件实现方案

原方案不生效的原因

当你使用.pipe()将可读流绑定到fs.createWriteStream实例后,可写流的写入权限完全由管道机制接管,所有写入操作都是自动调度的,此时你手动调用fs.truncate()、fs.write()会和内置的写入逻辑产生时序冲突,自然无法生效。

实现思路

放弃直接使用pipe()绑定单个可写流,改为手动监听可读流的data事件,自行统计每个分片的已写入字节数,达到100MB阈值时自动切换新的写入文件即可。

完整实现代码

const fs = require('fs')
const path = require('path')

// 配置项
const CHUNK_SIZE = 100 * 1024 * 1024 // 每个分片100MB
const OUTPUT_DIR = './audio_chunks' // 分片存储目录
const BASE_FILENAME = 'audio_part' // 分片文件名前缀

// 初始化目录
if (!fs.existsSync(OUTPUT_DIR)) {
  fs.mkdirSync(OUTPUT_DIR, { recursive: true })
}

// 状态变量
let currentFileIndex = 1
let currentWriteStream = null
let bytesWrittenToCurrent = 0

// 创建新的分片写入流
function createNewWriteStream() {
  if (currentWriteStream) {
    currentWriteStream.end()
  }
  const filename = path.join(OUTPUT_DIR, `${BASE_FILENAME}_${currentFileIndex}.raw`)
  currentWriteStream = fs.createWriteStream(filename)
  bytesWrittenToCurrent = 0
  currentFileIndex++
  // 处理背压
  currentWriteStream.on('drain', () => {
    stream.resume() // 之前如果暂停了流,这里恢复
  })
  currentWriteStream.on('error', (err) => {
    console.error('写入流错误:', err)
    stream.destroy(err)
  })
}

// 初始化第一个写入流
createNewWriteStream()

// 你的原始音频输入流,这里替换为你实际的流对象
// const stream = 你接收到的音频buffer流
stream.on('data', (chunk) => {
  let remainingChunk = chunk
  while (remainingChunk.length > 0) {
    const availableSpace = CHUNK_SIZE - bytesWrittenToCurrent
    if (remainingChunk.length <= availableSpace) {
      // 当前分片还有足够空间,直接写入
      const canWrite = currentWriteStream.write(remainingChunk)
      bytesWrittenToCurrent += remainingChunk.length
      remainingChunk = Buffer.alloc(0)
      if (!canWrite) {
        stream.pause() // 处理背压,暂停读取
      }
    } else {
      // 剩余空间不足,拆分chunk
      const chunkToWrite = remainingChunk.subarray(0, availableSpace)
      const canWrite = currentWriteStream.write(chunkToWrite)
      remainingChunk = remainingChunk.subarray(availableSpace)
      bytesWrittenToCurrent += availableSpace
      // 切换新分片
      createNewWriteStream()
      if (!canWrite) {
        stream.pause()
        // 等drain之后再继续处理剩下的chunk
        currentWriteStream.once('drain', () => stream.resume())
        break
      }
    }
  }
})

// 流读取完成收尾
stream.on('end', () => {
  if (currentWriteStream) {
    currentWriteStream.end()
  }
  console.log(`所有分片写入完成,共生成${currentFileIndex - 1}个文件`)
})

stream.on('error', (err) => {
  console.error('输入流错误:', err)
  if (currentWriteStream) {
    currentWriteStream.destroy()
  }
})

注意事项

  • 如果你需要存储的是可直接播放的音频格式而非原始buffer,需要额外补充音频头写入逻辑,上述代码存储的是原始二进制分片
  • 代码中已经处理了流背压问题,不会因为写入速度跟不上读取速度导致内存溢出
  • 可根据实际需求修改分片大小、存储路径、文件名生成规则

内容的提问来源于stack exchange,提问作者Mohamed Farouk

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.09.27 03:36:03