mirror of
https://github.com/hicccc77/WeFlow.git
synced 2026-03-24 23:06:51 +00:00
fix: 清理导出服务日志并简化whisper接口参数
- 移除exportService中的冗余console日志输出 - 简化whisper API接口,移除downloadModel和getModelStatus的payload参数 - 清理图片、表情、语音导出过程中的调试日志 - 移除数据库查询和媒体处理中的详细日志记录 - 优化代码可读性,减少控制台输出噪音
This commit is contained in:
@@ -184,10 +184,10 @@ contextBridge.exposeInMainWorld('electronAPI', {
|
||||
},
|
||||
|
||||
whisper: {
|
||||
downloadModel: (payload: { modelName: string; downloadDir?: string; source?: string }) =>
|
||||
ipcRenderer.invoke('whisper:downloadModel', payload),
|
||||
getModelStatus: (payload: { modelName: string; downloadDir?: string }) =>
|
||||
ipcRenderer.invoke('whisper:getModelStatus', payload),
|
||||
downloadModel: () =>
|
||||
ipcRenderer.invoke('whisper:downloadModel'),
|
||||
getModelStatus: () =>
|
||||
ipcRenderer.invoke('whisper:getModelStatus'),
|
||||
onDownloadProgress: (callback: (payload: { modelName: string; downloadedBytes: number; totalBytes?: number; percent?: number }) => void) => {
|
||||
ipcRenderer.on('whisper:downloadProgress', (_, payload) => callback(payload))
|
||||
return () => ipcRenderer.removeAllListeners('whisper:downloadProgress')
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
import * as fs from 'fs'
|
||||
import * as fs from 'fs'
|
||||
import * as path from 'path'
|
||||
import * as http from 'http'
|
||||
import * as https from 'https'
|
||||
@@ -364,7 +364,6 @@ class ExportService {
|
||||
|
||||
return `[${callType}]`
|
||||
} catch (e) {
|
||||
console.error('[ExportService] Failed to parse VOIP message:', e)
|
||||
return '[通话]'
|
||||
}
|
||||
}
|
||||
@@ -417,8 +416,7 @@ class ExportService {
|
||||
if (localType === 3 && options.exportImages) {
|
||||
const result = await this.exportImage(msg, sessionId, mediaDir)
|
||||
if (result) {
|
||||
console.log('[ExportService] 图片导出成功:', result.relativePath)
|
||||
}
|
||||
}
|
||||
return result
|
||||
}
|
||||
|
||||
@@ -438,8 +436,7 @@ class ExportService {
|
||||
if (localType === 47 && options.exportEmojis) {
|
||||
const result = await this.exportEmoji(msg, sessionId, mediaDir)
|
||||
if (result) {
|
||||
console.log('[ExportService] 表情导出成功:', result.relativePath)
|
||||
}
|
||||
}
|
||||
return result
|
||||
}
|
||||
|
||||
@@ -461,12 +458,9 @@ class ExportService {
|
||||
const imageDatName = msg.imageDatName
|
||||
|
||||
if (!imageMd5 && !imageDatName) {
|
||||
console.log('[ExportService] 图片消息缺少 md5 和 datName:', msg.localId)
|
||||
return null
|
||||
}
|
||||
|
||||
console.log('[ExportService] 导出图片:', { localId: msg.localId, imageMd5, imageDatName, sessionId })
|
||||
|
||||
const result = await imageDecryptService.decryptImage({
|
||||
sessionId,
|
||||
imageMd5,
|
||||
@@ -524,7 +518,6 @@ class ExportService {
|
||||
|
||||
return null
|
||||
} catch (e) {
|
||||
console.error('[ExportService] 导出图片失败:', e)
|
||||
return null
|
||||
}
|
||||
}
|
||||
@@ -545,19 +538,15 @@ class ExportService {
|
||||
|
||||
// 如果已存在则跳过
|
||||
if (fs.existsSync(destPath)) {
|
||||
console.log('[ExportService] 语音已存在:', destPath)
|
||||
return {
|
||||
relativePath: `media/voices/${fileName}`,
|
||||
kind: 'voice'
|
||||
}
|
||||
}
|
||||
|
||||
console.log('[ExportService] 导出语音:', { localId: msg.localId, sessionId })
|
||||
|
||||
// 调用 chatService 获取语音数据
|
||||
const voiceResult = await chatService.getVoiceData(sessionId, msgId)
|
||||
if (!voiceResult.success || !voiceResult.data) {
|
||||
console.log('[ExportService] 获取语音数据失败:', voiceResult.error)
|
||||
return null
|
||||
}
|
||||
|
||||
@@ -565,13 +554,11 @@ class ExportService {
|
||||
const wavBuffer = Buffer.from(voiceResult.data, 'base64')
|
||||
fs.writeFileSync(destPath, wavBuffer)
|
||||
|
||||
console.log('[ExportService] 语音导出成功:', destPath)
|
||||
return {
|
||||
relativePath: `media/voices/${fileName}`,
|
||||
kind: 'voice'
|
||||
}
|
||||
} catch (e) {
|
||||
console.error('[ExportService] 导出语音失败:', e)
|
||||
return null
|
||||
}
|
||||
}
|
||||
@@ -587,7 +574,6 @@ class ExportService {
|
||||
}
|
||||
return '[语音消息 - 转文字失败]'
|
||||
} catch (e) {
|
||||
console.error('[ExportService] 语音转文字失败:', e)
|
||||
return '[语音消息 - 转文字失败]'
|
||||
}
|
||||
}
|
||||
@@ -625,7 +611,6 @@ class ExportService {
|
||||
|
||||
// 如果已存在则跳过
|
||||
if (fs.existsSync(destPath)) {
|
||||
console.log('[ExportService] 表情已存在:', destPath)
|
||||
return {
|
||||
relativePath: `media/emojis/${fileName}`,
|
||||
kind: 'emoji'
|
||||
@@ -634,22 +619,18 @@ class ExportService {
|
||||
|
||||
// 下载表情
|
||||
if (emojiUrl) {
|
||||
console.log('[ExportService] 开始下载表情:', emojiUrl)
|
||||
const downloaded = await this.downloadFile(emojiUrl, destPath)
|
||||
if (downloaded) {
|
||||
console.log('[ExportService] 表情下载成功:', destPath)
|
||||
return {
|
||||
relativePath: `media/emojis/${fileName}`,
|
||||
kind: 'emoji'
|
||||
}
|
||||
} else {
|
||||
console.log('[ExportService] 表情下载失败:', emojiUrl)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return null
|
||||
} catch (e) {
|
||||
console.error('[ExportService] 导出表情失败:', e)
|
||||
return null
|
||||
}
|
||||
}
|
||||
@@ -823,13 +804,11 @@ class ExportService {
|
||||
// 图片消息
|
||||
imageMd5 = this.extractImageMd5(content)
|
||||
imageDatName = this.extractImageDatName(content)
|
||||
console.log('[ExportService] 提取图片字段:', { localId, imageMd5, imageDatName })
|
||||
} else if (localType === 47 && content) {
|
||||
} else if (localType === 47 && content) {
|
||||
// 动画表情
|
||||
emojiCdnUrl = this.extractEmojiUrl(content)
|
||||
emojiMd5 = this.extractEmojiMd5(content)
|
||||
console.log('[ExportService] 提取表情字段:', { localId, emojiMd5, emojiCdnUrl: emojiCdnUrl?.substring(0, 100) })
|
||||
}
|
||||
}
|
||||
|
||||
rows.push({
|
||||
localId,
|
||||
@@ -1233,7 +1212,6 @@ class ExportService {
|
||||
|
||||
return { success: true }
|
||||
} catch (e) {
|
||||
console.error('ExportService: 导出失败:', e)
|
||||
return { success: false, error: String(e) }
|
||||
}
|
||||
}
|
||||
@@ -1348,7 +1326,6 @@ class ExportService {
|
||||
|
||||
return { success: true }
|
||||
} catch (e) {
|
||||
console.error('ExportService: 导出失败:', e)
|
||||
return { success: false, error: String(e) }
|
||||
}
|
||||
}
|
||||
@@ -1570,14 +1547,7 @@ class ExportService {
|
||||
|
||||
// 调试日志
|
||||
if (msg.localType === 3 || msg.localType === 47) {
|
||||
console.log('[ExportService] 媒体消息填充表格:', {
|
||||
localId: msg.localId,
|
||||
localType: msg.localType,
|
||||
hasMediaItem: !!mediaItem,
|
||||
mediaRelativePath: mediaItem?.relativePath,
|
||||
contentValue: contentValue?.substring(0, 100)
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
worksheet.getCell(currentRow, 1).value = i + 1
|
||||
worksheet.getCell(currentRow, 2).value = this.formatTimestamp(msg.createTime)
|
||||
@@ -1628,8 +1598,6 @@ class ExportService {
|
||||
|
||||
return { success: true }
|
||||
} catch (e) {
|
||||
console.error('ExportService: 导出 Excel 失败:', e)
|
||||
|
||||
// 处理文件被占用的错误
|
||||
if (e instanceof Error) {
|
||||
if (e.message.includes('EBUSY') || e.message.includes('resource busy') || e.message.includes('locked')) {
|
||||
@@ -1721,3 +1689,4 @@ class ExportService {
|
||||
}
|
||||
|
||||
export const exportService = new ExportService()
|
||||
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
import { app } from 'electron'
|
||||
import { app } from 'electron'
|
||||
import { existsSync, mkdirSync, statSync, unlinkSync, createWriteStream } from 'fs'
|
||||
import { join } from 'path'
|
||||
import * as https from 'https'
|
||||
@@ -98,7 +98,6 @@ export class VoiceTranscribeService {
|
||||
sizeBytes: totalSize
|
||||
}
|
||||
} catch (error) {
|
||||
console.error('[VoiceTranscribe] getModelStatus error:', error)
|
||||
return { success: false, error: String(error) }
|
||||
}
|
||||
}
|
||||
@@ -125,7 +124,6 @@ export class VoiceTranscribeService {
|
||||
const vadPath = this.resolveModelPath((SENSEVOICE_MODEL.files as any).vad)
|
||||
|
||||
// 下载模型文件 (40%)
|
||||
console.info('[VoiceTranscribe] 开始下载模型文件...')
|
||||
await this.downloadToFile(
|
||||
MODEL_DOWNLOAD_URLS.model,
|
||||
modelPath,
|
||||
@@ -142,7 +140,6 @@ export class VoiceTranscribeService {
|
||||
)
|
||||
|
||||
// 下载 tokens 文件 (30%)
|
||||
console.info('[VoiceTranscribe] 开始下载 tokens 文件...')
|
||||
await this.downloadToFile(
|
||||
MODEL_DOWNLOAD_URLS.tokens,
|
||||
tokensPath,
|
||||
@@ -160,7 +157,6 @@ export class VoiceTranscribeService {
|
||||
)
|
||||
|
||||
// 下载 vad 文件 (30%)
|
||||
console.info('[VoiceTranscribe] 开始下载 VAD 文件...')
|
||||
await this.downloadToFile(
|
||||
(MODEL_DOWNLOAD_URLS as any).vad,
|
||||
vadPath,
|
||||
@@ -178,10 +174,8 @@ export class VoiceTranscribeService {
|
||||
}
|
||||
)
|
||||
|
||||
console.info('[VoiceTranscribe] 模型下载完成')
|
||||
return { success: true, modelPath, tokensPath }
|
||||
} catch (error) {
|
||||
console.error('[VoiceTranscribe] 下载失败:', error)
|
||||
const modelPath = this.resolveModelPath(SENSEVOICE_MODEL.files.model)
|
||||
const tokensPath = this.resolveModelPath(SENSEVOICE_MODEL.files.tokens)
|
||||
const vadPath = this.resolveModelPath((SENSEVOICE_MODEL.files as any).vad)
|
||||
@@ -221,8 +215,6 @@ export class VoiceTranscribeService {
|
||||
// main.js 和 transcribeWorker.js 同在 dist-electron 目录下
|
||||
const workerPath = join(__dirname, 'transcribeWorker.js')
|
||||
|
||||
console.info('[VoiceTranscribe] 启动后台 Worker 转写...', { workerPath })
|
||||
|
||||
const worker = new Worker(workerPath, {
|
||||
workerData: {
|
||||
modelPath,
|
||||
@@ -248,7 +240,6 @@ export class VoiceTranscribeService {
|
||||
})
|
||||
|
||||
worker.on('error', (err: Error) => {
|
||||
console.error('[VoiceTranscribe] Worker error:', err)
|
||||
resolve({ success: false, error: String(err) })
|
||||
})
|
||||
|
||||
@@ -260,7 +251,6 @@ export class VoiceTranscribeService {
|
||||
})
|
||||
|
||||
} catch (error) {
|
||||
console.error('[VoiceTranscribe] 启动 Worker 失败:', error)
|
||||
resolve({ success: false, error: String(error) })
|
||||
}
|
||||
})
|
||||
@@ -350,10 +340,10 @@ export class VoiceTranscribeService {
|
||||
// sherpa-onnx 的 recognizer 可能需要手动释放
|
||||
this.recognizer = null
|
||||
} catch (error) {
|
||||
console.error('[VoiceTranscribe] 释放识别器失败:', error)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
export const voiceTranscribeService = new VoiceTranscribeService()
|
||||
|
||||
|
||||
@@ -58,11 +58,13 @@ export class WcdbService {
|
||||
})
|
||||
|
||||
this.worker.on('error', (err) => {
|
||||
console.error('WCDB Worker 错误:', err)
|
||||
// Worker error
|
||||
})
|
||||
|
||||
this.worker.on('exit', (code) => {
|
||||
if (code !== 0) console.error(`WCDB Worker 异常退出,退出码: ${code}`)
|
||||
if (code !== 0) {
|
||||
// Worker exited with error
|
||||
}
|
||||
this.worker = null
|
||||
})
|
||||
|
||||
@@ -73,7 +75,7 @@ export class WcdbService {
|
||||
this.setLogEnabled(this.logEnabled)
|
||||
|
||||
} catch (e) {
|
||||
console.error('创建 WCDB Worker 失败:', e)
|
||||
// Failed to create worker
|
||||
}
|
||||
}
|
||||
|
||||
@@ -97,7 +99,7 @@ export class WcdbService {
|
||||
setPaths(resourcesPath: string, userDataPath: string): void {
|
||||
this.resourcesPath = resourcesPath
|
||||
this.userDataPath = userDataPath
|
||||
this.callWorker('setPaths', { resourcesPath, userDataPath }).catch(console.error)
|
||||
this.callWorker('setPaths', { resourcesPath, userDataPath }).catch(() => {})
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -105,7 +107,7 @@ export class WcdbService {
|
||||
*/
|
||||
setLogEnabled(enabled: boolean): void {
|
||||
this.logEnabled = enabled
|
||||
this.callWorker('setLogEnabled', { enabled }).catch(console.error)
|
||||
this.callWorker('setLogEnabled', { enabled }).catch(() => {})
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
import { parentPort, workerData } from 'worker_threads'
|
||||
import { parentPort, workerData } from 'worker_threads'
|
||||
import * as fs from 'fs'
|
||||
|
||||
interface WorkerParams {
|
||||
@@ -9,37 +9,23 @@ interface WorkerParams {
|
||||
}
|
||||
|
||||
async function run() {
|
||||
console.info('[TranscribeWorker] Worker process starting...');
|
||||
|
||||
if (!parentPort) {
|
||||
console.error('[TranscribeWorker] Critical Error: parentPort is null');
|
||||
return;
|
||||
}
|
||||
|
||||
try {
|
||||
console.info('[TranscribeWorker] Loading sherpa-onnx-node...');
|
||||
// 动态加载以捕获可能的加载错误(如 C++ 运行库缺失等)
|
||||
let sherpa: any;
|
||||
try {
|
||||
sherpa = require('sherpa-onnx-node');
|
||||
console.info('[TranscribeWorker] sherpa-onnx-node loaded successfully.');
|
||||
} catch (requireError) {
|
||||
console.error('[TranscribeWorker] Failed to load sherpa-onnx-node:', requireError);
|
||||
} catch (requireError) {
|
||||
parentPort.postMessage({ type: 'error', error: 'Failed to load speech engine: ' + String(requireError) });
|
||||
return;
|
||||
}
|
||||
|
||||
const { modelPath, tokensPath, wavData: rawWavData, sampleRate } = workerData as WorkerParams
|
||||
const wavData = Buffer.from(rawWavData);
|
||||
console.info('[TranscribeWorker] Params received:', {
|
||||
modelPath,
|
||||
tokensPath,
|
||||
sampleRate,
|
||||
wavDataLength: wavData?.length
|
||||
});
|
||||
|
||||
// 1. 初始化识别器 (SenseVoiceSmall)
|
||||
console.info('[TranscribeWorker] Initializing OfflineRecognizer...');
|
||||
const recognizerConfig = {
|
||||
modelConfig: {
|
||||
senseVoice: {
|
||||
@@ -52,12 +38,8 @@ async function run() {
|
||||
}
|
||||
}
|
||||
const recognizer = new sherpa.OfflineRecognizer(recognizerConfig)
|
||||
console.info('[TranscribeWorker] OfflineRecognizer initialized.');
|
||||
|
||||
// 2. 初始化 VAD (用于流式输出效果)
|
||||
const vadPath = modelPath.replace('model.int8.onnx', 'silero_vad.onnx');
|
||||
console.info('[TranscribeWorker] VAD Path:', vadPath);
|
||||
|
||||
const vadConfig = {
|
||||
sileroVad: {
|
||||
model: vadPath,
|
||||
@@ -73,8 +55,6 @@ async function run() {
|
||||
|
||||
// 检查 VAD 模型是否存在,如果不存在则退回到全量识别
|
||||
if (!fs.existsSync(vadPath)) {
|
||||
console.warn('[TranscribeWorker] VAD model not found, falling back to full transcription.');
|
||||
|
||||
const pcmData = wavData.slice(44)
|
||||
const samples = new Float32Array(pcmData.length / 2)
|
||||
for (let i = 0; i < samples.length; i++) {
|
||||
@@ -86,15 +66,11 @@ async function run() {
|
||||
recognizer.decode(stream)
|
||||
const result = recognizer.getResult(stream)
|
||||
|
||||
console.info('[TranscribeWorker] Full transcription result:', result.text);
|
||||
parentPort.postMessage({ type: 'final', text: result.text })
|
||||
return
|
||||
}
|
||||
|
||||
console.info('[TranscribeWorker] Initializing Vad...');
|
||||
const vad = new sherpa.Vad(vadConfig, 60) // 60s max
|
||||
console.info('[TranscribeWorker] VAD initialized.');
|
||||
|
||||
// 3. 处理音频数据
|
||||
const pcmData = wavData.slice(44)
|
||||
const samples = new Float32Array(pcmData.length / 2)
|
||||
@@ -107,7 +83,6 @@ async function run() {
|
||||
let offset = 0
|
||||
let accumulatedText = ''
|
||||
|
||||
console.info('[TranscribeWorker] Starting processing loop...');
|
||||
let segmentCount = 0;
|
||||
|
||||
while (offset < samples.length) {
|
||||
@@ -120,9 +95,6 @@ async function run() {
|
||||
while (!vad.isEmpty()) {
|
||||
const segment = vad.front(false)
|
||||
|
||||
// Log segment detection
|
||||
console.info(`[TranscribeWorker] VAD Segment detected. Duration: ${segment.samples.length / sampleRate}s`);
|
||||
|
||||
const stream = recognizer.createStream()
|
||||
stream.acceptWaveform({ sampleRate, samples: segment.samples })
|
||||
recognizer.decode(stream)
|
||||
@@ -133,7 +105,6 @@ async function run() {
|
||||
if (text.length > 0) {
|
||||
accumulatedText += (accumulatedText ? ' ' : '') + text
|
||||
segmentCount++;
|
||||
console.info(`[TranscribeWorker] Partial update #${segmentCount}: "${text}" -> Total: "${accumulatedText.substring(0, 50)}..."`);
|
||||
parentPort.postMessage({ type: 'partial', text: accumulatedText })
|
||||
}
|
||||
}
|
||||
@@ -149,26 +120,23 @@ async function run() {
|
||||
vad.flush();
|
||||
while (!vad.isEmpty()) {
|
||||
const segment = vad.front(false);
|
||||
console.info(`[TranscribeWorker] Final VAD Segment detected. Duration: ${segment.samples.length / sampleRate}s`);
|
||||
const stream = recognizer.createStream()
|
||||
stream.acceptWaveform({ sampleRate, samples: segment.samples })
|
||||
recognizer.decode(stream)
|
||||
const result = recognizer.getResult(stream)
|
||||
if (result.text) {
|
||||
accumulatedText += (accumulatedText ? ' ' : '') + result.text.trim()
|
||||
console.info(`[TranscribeWorker] Final partial update: "${result.text.trim()}"`);
|
||||
parentPort.postMessage({ type: 'partial', text: accumulatedText })
|
||||
}
|
||||
vad.pop();
|
||||
}
|
||||
|
||||
console.info('[TranscribeWorker] Loop finished. Final text length:', accumulatedText.length);
|
||||
parentPort.postMessage({ type: 'final', text: accumulatedText })
|
||||
|
||||
} catch (error) {
|
||||
console.error('[TranscribeWorker] Fatal error:', error);
|
||||
parentPort.postMessage({ type: 'error', error: String(error) })
|
||||
}
|
||||
}
|
||||
|
||||
run();
|
||||
|
||||
|
||||
Reference in New Issue
Block a user