fix: WeChat login Content-Type header, ASR tiny model, re-upload mini-program v1.0.11
This commit is contained in:
@@ -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, '')
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user