fix(cleaner): use copy+unlink for video rename to avoid Windows EBUSY

Windows fs.rename fails when ffmpeg still holds the file handle. Use
copyFileSync + unlinkSync with retry (up to 10 attempts, 1s interval)
to work around the file lock.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
Misaka_Company
2026-04-17 15:39:58 +08:00
parent c58a9066e5
commit e6ba7ad4c1

View File

@@ -1294,8 +1294,24 @@ export class CleanerService {
const finalPath = fs.existsSync(orderVideoPath) const finalPath = fs.existsSync(orderVideoPath)
? path.join(this.videoDir!, `${expectedOrderNumber}_${Date.now()}${ext}`) ? path.join(this.videoDir!, `${expectedOrderNumber}_${Date.now()}${ext}`)
: orderVideoPath : orderVideoPath
fs.renameSync(originalPath, finalPath) // Copy + unlink instead of rename — Windows EBUSY if ffmpeg still holds the file
log.debug('[视频录制] 视频已重命名', { from: originalPath, to: finalPath }) await new Promise<void>((resolve, reject) => {
const tryRename = (attempt: number) => {
try {
fs.copyFileSync(originalPath, finalPath)
fs.unlinkSync(originalPath)
log.debug('[视频录制] 视频已重命名', { from: originalPath, to: finalPath })
resolve()
} catch (err) {
if (attempt < 10) {
setTimeout(() => tryRename(attempt + 1), 1000)
} else {
reject(err)
}
}
}
tryRename(0)
})
} }
} catch (videoError) { } catch (videoError) {
log.warn('[视频录制] 重命名视频失败', { log.warn('[视频录制] 重命名视频失败', {