fix: WeChat login Content-Type header, ASR tiny model, re-upload mini-program v1.0.11

This commit is contained in:
yuzhiran
2026-06-15 10:00:02 +08:00
parent 4fa620f0a2
commit 18c50726cd
22 changed files with 311 additions and 128 deletions
+47 -2
View File
@@ -10,6 +10,7 @@ interface TtsResult {
hash: string
filePath: string
durationMs: number
amplitudeData: number[]
}
const VALID_VOICES = new Set([
@@ -41,7 +42,10 @@ export class TtsService {
if (fs.existsSync(filePath)) {
const durationMs = await this.getDuration(filePath)
return { hash, filePath, durationMs }
const amplitudeData = this.loadAmplitudeData(hash)
if (amplitudeData) {
return { hash, filePath, durationMs, amplitudeData }
}
}
try {
@@ -50,8 +54,9 @@ export class TtsService {
{ timeout: 30000 },
)
const durationMs = await this.getDuration(filePath)
const amplitudeData = this.extractAmplitude(filePath, hash)
this.logger.log(`TTS generated: hash=${hash} text="${text.slice(0, 40)}..." duration=${durationMs}ms`)
return { hash, filePath, durationMs }
return { hash, filePath, durationMs, amplitudeData }
} catch (e) {
this.logger.error(`TTS failed: ${e.message}`)
throw e
@@ -63,6 +68,46 @@ export class TtsService {
return fs.existsSync(filePath) ? filePath : null
}
private extractAmplitude(mp3Path: string, hash: string): number[] {
try {
const pcmPath = `/tmp/tts-cache/${hash}.pcm`
execSync(
`ffmpeg -y -i "${mp3Path}" -f s16le -acodec pcm_s16le -ar 16000 -ac 1 "${pcmPath}" 2>/dev/null`,
{ timeout: 10000 },
)
const pcmBuf = fs.readFileSync(pcmPath)
const samples = new Int16Array(pcmBuf.buffer, pcmBuf.byteOffset, pcmBuf.byteLength / 2)
const chunkSize = Math.floor(16000 * 0.05) // 50ms
const amplitudes: number[] = []
for (let i = 0; i < samples.length; i += chunkSize) {
const end = Math.min(i + chunkSize, samples.length)
let sumSq = 0
for (let j = i; j < end; j++) {
sumSq += samples[j] * samples[j]
}
const rms = Math.sqrt(sumSq / (end - i))
amplitudes.push(Number((Math.min(1, rms / 16000)).toFixed(4)))
}
try { fs.unlinkSync(pcmPath) } catch {}
const ampPath = `/tmp/tts-cache/${hash}.amp`
fs.writeFileSync(ampPath, JSON.stringify(amplitudes))
return amplitudes
} catch (e) {
this.logger.warn(`振幅提取失败: ${e.message}`)
return []
}
}
private loadAmplitudeData(hash: string): number[] | null {
try {
const ampPath = `/tmp/tts-cache/${hash}.amp`
if (!fs.existsSync(ampPath)) return null
return JSON.parse(fs.readFileSync(ampPath, 'utf8'))
} catch {
return null
}
}
private escapeText(text: string): string {
return text.replace(/"/g, '\\"').replace(/\n/g, ' ').replace(/\r/g, '')
}