function registerWhisperRoutes(app, deps) { const { exec, fs, path, projectRoot, whisperDir, readManifest, writeManifest, resolveVideoPath, } = deps; app.post('/api/whisper/transcribe', async (req, res) => { const { videoId, language = 'Chinese', model = 'base' } = req.body; if (!videoId) { return res.status(400).json({ error: '缺少 videoId 参数' }); } const manifest = readManifest(); const video = manifest.find(v => v.id === videoId); if (!video) { return res.status(404).json({ error: `未找到视频: ${videoId}` }); } const videoPath = resolveVideoPath(video.filename); if (!fs.existsSync(videoPath)) { return res.status(404).json({ error: `视频文件不存在: ${video.filename}` }); } const baseName = video.filename.replace(/\.[^.]+$/, ''); const outputDir = path.join(whisperDir, baseName); if (!fs.existsSync(outputDir)) { fs.mkdirSync(outputDir, { recursive: true }); } console.log(`🎙️ 开始 Whisper 转录: ${video.filename}`); console.log(` 模型: ${model}, 语言: ${language}`); console.log(` 输出目录: ${outputDir}`); const cmd = `whisper "${videoPath}" --model ${model} --language ${language} --output_dir "${outputDir}"`; try { await new Promise((resolve, reject) => { const process = exec(cmd, { cwd: projectRoot, timeout: 10 * 60 * 1000, maxBuffer: 10 * 1024 * 1024, }); let stdout = ''; let stderr = ''; process.stdout.on('data', (data) => { stdout += data; console.log(` [whisper] ${data.toString().trim()}`); }); process.stderr.on('data', (data) => { stderr += data; }); process.on('close', (code) => { if (code === 0) { resolve({ stdout, stderr }); } else { reject(new Error(`Whisper 退出码: ${code}\n${stderr}`)); } }); process.on('error', (err) => { reject(new Error(`无法启动 Whisper: ${err.message}`)); }); }); const txtFile = path.join(outputDir, `${baseName}.txt`); const srtFile = path.join(outputDir, `${baseName}.srt`); const transcript = fs.existsSync(txtFile) ? fs.readFileSync(txtFile, 'utf-8') : ''; const srt = fs.existsSync(srtFile) ? fs.readFileSync(srtFile, 'utf-8') : ''; if (!transcript) { return res.status(500).json({ error: 'Whisper 执行完成但未生成文字稿' }); } const whisperPaths = { transcript: `Whisper/${baseName}/${baseName}.txt`, srt: `Whisper/${baseName}/${baseName}.srt`, }; const jsonFile = path.join(outputDir, `${baseName}.json`); if (fs.existsSync(jsonFile)) whisperPaths.segments = `Whisper/${baseName}/${baseName}.json`; video.whisper = whisperPaths; writeManifest(manifest); console.log(`✅ Whisper 转录完成: ${baseName}`); res.json({ success: true, videoId: video.id, transcript, srt, whisper: whisperPaths, outputDir: `Whisper/${baseName}`, }); } catch (err) { console.error('❌ Whisper 转录失败:', err.message); res.status(500).json({ error: `Whisper 转录失败: ${err.message}`, hint: '请确保已安装 Whisper: pip install openai-whisper', }); } }); app.get('/api/whisper/status', (req, res) => { exec('whisper --help', { timeout: 5000 }, (err) => { if (err) { res.json({ available: false, message: '未检测到 Whisper,请执行: pip install openai-whisper' }); } else { res.json({ available: true, message: 'Whisper 已安装' }); } }); }); } module.exports = { registerWhisperRoutes };