(
stream: Readable,
onChunk: (chunk: Buffer) => void,
onEnd: () => void,
resolve: () => void,
reject: (error: any) => void,
targetChunkSize: number = 640,
rateLimitMs: number = 20,
abortController: AbortController,
onStreamDestroy?: () => void
)
| 121 | } |
| 122 | |
| 123 | const processStreamWithRateLimit = async ( |
| 124 | stream: Readable, |
| 125 | onChunk: (chunk: Buffer) => void, |
| 126 | onEnd: () => void, |
| 127 | resolve: () => void, |
| 128 | reject: (error: any) => void, |
| 129 | targetChunkSize: number = 640, |
| 130 | rateLimitMs: number = 20, |
| 131 | abortController: AbortController, |
| 132 | onStreamDestroy?: () => void |
| 133 | ) => { |
| 134 | const TARGET_CHUNK_SIZE = targetChunkSize |
| 135 | const RATE_LIMIT_MS = rateLimitMs |
| 136 | |
| 137 | let buffer: Buffer = Buffer.alloc(0) |
| 138 | let isEnded = false |
| 139 | |
| 140 | const processChunks = async () => { |
| 141 | while (!isEnded || buffer.length > 0) { |
| 142 | // Check if aborted |
| 143 | if (abortController.signal.aborted) { |
| 144 | if (!stream.destroyed) { |
| 145 | stream.destroy() |
| 146 | } |
| 147 | onStreamDestroy?.() |
| 148 | reject(new Error('TTS generation aborted')) |
| 149 | return |
| 150 | } |
| 151 | |
| 152 | if (buffer.length >= TARGET_CHUNK_SIZE) { |
| 153 | const chunk = buffer.subarray(0, TARGET_CHUNK_SIZE) |
| 154 | buffer = buffer.subarray(TARGET_CHUNK_SIZE) |
| 155 | onChunk(chunk) |
| 156 | await sleep(RATE_LIMIT_MS) |
| 157 | } else if (isEnded && buffer.length > 0) { |
| 158 | onChunk(buffer) |
| 159 | buffer = Buffer.alloc(0) |
| 160 | } else if (!isEnded) { |
| 161 | await sleep(RATE_LIMIT_MS) |
| 162 | } else { |
| 163 | break |
| 164 | } |
| 165 | } |
| 166 | |
| 167 | onEnd() |
| 168 | resolve() |
| 169 | } |
| 170 | |
| 171 | stream.on('data', (chunk) => { |
| 172 | if (!abortController.signal.aborted) { |
| 173 | buffer = Buffer.concat([buffer, Buffer.from(chunk)]) |
| 174 | } |
| 175 | }) |
| 176 | |
| 177 | stream.on('end', () => { |
| 178 | isEnded = true |
| 179 | }) |
| 180 |
no test coverage detected