feat(video-from-script): 批量生产元数据增强 — 选题/转发文案/草稿命名/导出/草稿箱改名
- batch-pipeline.js: 新增 mark 元数据字段(topicA/B, draftName, forwardCopy, hashtags) - batch-pipeline.js: 新增 export 命令导出 CSV/XLSX 最终表格 - batch-pipeline.js: 新增 rename-drafts 命令批量重命名剪映草稿(Mac 直接 mv 文件夹) - batch-pipeline.js: 完善 displayTitle 向后兼容旧 topic 字段 - lib/phase-tts: 增强 TTS 生成稳定性 - lib/phase-videos: 视频生成优化 - lib/video-poll-utils: 提取轮询重试共享工具 - CLAUDE.md: 补充批量生产选题/转发文案/草稿命名/导出/草稿箱改名文档 - 执黑先行 account.json: 配置更新 Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
This commit is contained in:
@@ -5,6 +5,11 @@
|
||||
* 两层重试:轮询级(同一 taskId,处理网络瞬断)→ 任务级(创建新 task + 优化提示词)
|
||||
*/
|
||||
|
||||
const path = require('path')
|
||||
const fs = require('fs')
|
||||
const https = require('https')
|
||||
const http = require('http')
|
||||
|
||||
const TRANSIENT_RE = /timeout|ECONNRESET|ETIMEDOUT|network|socket/i
|
||||
|
||||
const POLL_RETRIES = 2 // 同一 task 轮询重试次数
|
||||
@@ -15,6 +20,26 @@ function isTransientError(err) {
|
||||
return TRANSIENT_RE.test(err.message || '')
|
||||
}
|
||||
|
||||
async function download(url, outputPath) {
|
||||
const protocol = url.startsWith('https') ? https : http
|
||||
return new Promise((resolve, reject) => {
|
||||
const file = fs.createWriteStream(outputPath)
|
||||
protocol.get(url, (response) => {
|
||||
if (response.statusCode >= 300 && response.statusCode < 400 && response.headers.location) {
|
||||
file.close()
|
||||
fs.unlinkSync(outputPath)
|
||||
return download(response.headers.location, outputPath).then(resolve).catch(reject)
|
||||
}
|
||||
response.pipe(file)
|
||||
file.on('finish', () => { file.close(); resolve(outputPath) })
|
||||
}).on('error', (err) => {
|
||||
file.close()
|
||||
if (fs.existsSync(outputPath)) fs.unlinkSync(outputPath)
|
||||
reject(err)
|
||||
})
|
||||
})
|
||||
}
|
||||
|
||||
/**
|
||||
* 创建 pollWithRetry 函数
|
||||
*
|
||||
|
||||
Reference in New Issue
Block a user