Browse Source

Revert "提前吧合成数据发送"

This reverts commit 837b870644.
newdev_shunjiawei
lxm 9 months ago
parent
commit
93979e8ae8
  1. 52
      local_plugins/azure_speech/android/src/main/kotlin/com/yunqiinnovation/azure_speech/AzureAsrToAsr.kt
  2. 8
      local_plugins/azure_speech/android/src/main/kotlin/com/yunqiinnovation/azure_speech/AzureSpeechPlugin.kt
  3. 8
      local_plugins/azure_speech/ios/azure_speech/Sources/azure_speech/AzureSpeechPlugin.swift
  4. 54
      local_plugins/azure_speech/ios/azure_speech/Sources/azure_speech/IntegratedSpeechTranslationService.swift

52
local_plugins/azure_speech/android/src/main/kotlin/com/yunqiinnovation/azure_speech/AzureAsrToAsr.kt

@ -80,36 +80,6 @@ class IntegratedSpeechTranslationService(
// 语音映射缓存 // 语音映射缓存
private val voiceCache = ConcurrentHashMap<String, String>() private val voiceCache = ConcurrentHashMap<String, String>()
// TTS合成中的音频缓存
private var ttsdata: ByteArray = ByteArray(0)
/**
* 处理合成音频分片(按1280字节对齐)
* 输入的音频数据会追加到缓存;仅当累计长度达到`multiple`的整数倍时,
* 将该整数倍长度的部分通过`onSynthesisAudioGenerated`发送;余数保留在缓存等待下次。
*/
private fun processSynthesisAudioChunk(
text: String,
incoming: ByteArray,
multiple: Int = 1280
) {
if (incoming.isNotEmpty()) {
ttsdata = ttsdata + incoming
}
val sendLen = (ttsdata.size / multiple) * multiple
if (sendLen > 0) {
val chunk = ttsdata.copyOfRange(0, sendLen)
Log.d(TAG, "按${multiple}字节对齐发送音频: ${chunk.size} 字节,缓存剩余: ${ttsdata.size - sendLen}")
eventCallback?.onSynthesisAudioGenerated(text, chunk)
ttsdata = ttsdata.copyOfRange(sendLen, ttsdata.size)
} else {
Log.d(TAG, "暂未够${multiple}字节,当前缓存: ${ttsdata.size}")
}
}
/** /**
* 服务配置类 * 服务配置类
*/ */
@ -429,7 +399,6 @@ class IntegratedSpeechTranslationService(
// 合成开始事件 // 合成开始事件
SynthesisStarted.addEventListener { _, _ -> SynthesisStarted.addEventListener { _, _ ->
Log.d(TAG, "合成开始事件") Log.d(TAG, "合成开始事件")
ttsdata = ByteArray(0)
serviceState.isSynthesizing.set(true) serviceState.isSynthesizing.set(true)
eventCallback?.onStateChanged("Synthesis", true) eventCallback?.onStateChanged("Synthesis", true)
} }
@ -437,11 +406,9 @@ class IntegratedSpeechTranslationService(
// 合成进行中事件 // 合成进行中事件
Synthesizing.addEventListener { _, event -> Synthesizing.addEventListener { _, event ->
Log.d(TAG, "合成进行中事件") Log.d(TAG, "合成进行中事件")
// 计算进度(简化版) // 计算进度(简化版)
val progress = 0.5f // 实际应用中可以根据音频数据计算 val progress = 0.5f // 实际应用中可以根据音频数据计算
eventCallback?.onSynthesisProgress("", progress) eventCallback?.onSynthesisProgress("", progress)
val incoming = event.result.audioData ?: ByteArray(0)
processSynthesisAudioChunk("", incoming, 1280)
} }
// 合成完成事件 // 合成完成事件
@ -454,7 +421,6 @@ class IntegratedSpeechTranslationService(
// 合成取消事件 // 合成取消事件
SynthesisCanceled.addEventListener { _, event -> SynthesisCanceled.addEventListener { _, event ->
Log.d(TAG, "合成取消事件") Log.d(TAG, "合成取消事件")
ttsdata = ByteArray(0)
serviceState.isSynthesizing.set(false) serviceState.isSynthesizing.set(false)
val reason = event.result.reason val reason = event.result.reason
eventCallback?.onError("Synthesis", "语音合成取消: $reason") eventCallback?.onError("Synthesis", "语音合成取消: $reason")
@ -639,7 +605,6 @@ class IntegratedSpeechTranslationService(
try { try {
Log.d(TAG, "开始语音合成: $text") Log.d(TAG, "开始语音合成: $text")
serviceState.isSynthesizing.set(true) serviceState.isSynthesizing.set(true)
eventCallback?.onSynthesisStarted(text) eventCallback?.onSynthesisStarted(text)
val ssml = generateOptimizedSsml(text) val ssml = generateOptimizedSsml(text)
@ -653,13 +618,12 @@ class IntegratedSpeechTranslationService(
// 获取音频数据 // 获取音频数据
val audioData = result.audioData val audioData = result.audioData
// if (audioData != null && audioData.isNotEmpty()) { if (audioData != null && audioData.isNotEmpty()) {
// // 通过回调返回音频数据 // 通过回调返回音频数据
// eventCallback?.onSynthesisAudioGenerated(text, audioData) eventCallback?.onSynthesisAudioGenerated(text, audioData)
// Log.d(TAG, "音频数据大小: ${audioData.size} 字节") Log.d(TAG, "音频数据大小: ${audioData.size} 字节")
// } }
eventCallback?.onSynthesisAudioGenerated(text, ttsdata)
ttsdata = ByteArray(0)
return audioData return audioData
} else { } else {
Log.e(TAG, "语音合成失败: ${result?.reason}") Log.e(TAG, "语音合成失败: ${result?.reason}")

8
local_plugins/azure_speech/android/src/main/kotlin/com/yunqiinnovation/azure_speech/AzureSpeechPlugin.kt

@ -1042,10 +1042,10 @@ class AzureSpeechPlugin : BleService.Callback, FlutterPlugin {
override fun onSynthesisAudioGenerated(text: String, audioData: ByteArray) { override fun onSynthesisAudioGenerated(text: String, audioData: ByteArray) {
FileLogger.d(tag, "语音合成音频生成,文本=${text},音频数据大小=${audioData.size}") FileLogger.d(tag, "语音合成音频生成,文本=${text},音频数据大小=${audioData.size}")
// Azure TTS返回的是RIFF WAV格式,需要去除文件头 // Azure TTS返回的是RIFF WAV格式,需要去除文件头
//val pcmData = extractPcmFromWav(audioData) val pcmData = extractPcmFromWav(audioData)
if (audioData.isNotEmpty()) { if (pcmData.isNotEmpty()) {
FileLogger.d(tag, "提取PCM数据,大小=${audioData.size}字节") FileLogger.d(tag, "提取PCM数据,大小=${pcmData.size}字节")
BleService.writeExternalAudioData(audioData) BleService.writeExternalAudioData(pcmData)
} }
else { else {
FileLogger.e(tag, "提取PCM数据失败,音频数据可能不是WAV格式") FileLogger.e(tag, "提取PCM数据失败,音频数据可能不是WAV格式")

8
local_plugins/azure_speech/ios/azure_speech/Sources/azure_speech/AzureSpeechPlugin.swift

@ -1039,10 +1039,10 @@ private class AstEventCallback: IntegratedSpeechTranslationService.ServiceEventC
os_log("语音合成音频生成,文本=%@,音频数据大小=%d", log: plugin.log, type: .info, text, audioData.count) os_log("语音合成音频生成,文本=%@,音频数据大小=%d", log: plugin.log, type: .info, text, audioData.count)
// Azure TTS返回的是RIFF WAV格式,需要去除文件头提取PCM数据 // Azure TTS返回的是RIFF WAV格式,需要去除文件头提取PCM数据
// let pcmData = plugin.extractPcmFromWav(audioData) let pcmData = plugin.extractPcmFromWav(audioData)
if !audioData.isEmpty { if !pcmData.isEmpty {
os_log("提取PCM数据,大小=%d字节", log: plugin.log, type: .info, audioData.count) os_log("提取PCM数据,大小=%d字节", log: plugin.log, type: .info, pcmData.count)
BleService.shared.writeExternalAudioData(data: audioData) BleService.shared.writeExternalAudioData(data: pcmData)
} else { } else {
os_log("提取PCM数据失败,音频数据可能不是WAV格式", log: plugin.log, type: .error) os_log("提取PCM数据失败,音频数据可能不是WAV格式", log: plugin.log, type: .error)
} }

54
local_plugins/azure_speech/ios/azure_speech/Sources/azure_speech/IntegratedSpeechTranslationService.swift

@ -66,9 +66,6 @@ import os.log
// 处理队列 // 处理队列
private let processingQueue = DispatchQueue(label: "com.azure.speech.processing", qos: .userInitiated) private let processingQueue = DispatchQueue(label: "com.azure.speech.processing", qos: .userInitiated)
// 合成中的音频缓存
private var ttsBuffer = Data()
// MARK: - Configuration Structures // MARK: - Configuration Structures
/** /**
@ -481,7 +478,6 @@ import os.log
// 合成开始事件 // 合成开始事件
synthesizer?.addSynthesisStartedEventHandler { [weak self] (synthesizer, event) in synthesizer?.addSynthesisStartedEventHandler { [weak self] (synthesizer, event) in
guard let self = self else { return } guard let self = self else { return }
self.ttsBuffer = Data()
os_log("合成开始事件", log: self.log, type: .info) os_log("合成开始事件", log: self.log, type: .info)
self.serviceState.isSynthesizing = true self.serviceState.isSynthesizing = true
@ -491,7 +487,7 @@ import os.log
} }
} }
// 合成进行中事件 - 增量发送音频分片(按1280字节对齐) // 合成进行中事件 - 修改为返回音频数据
synthesizer?.addSynthesizingEventHandler { [weak self] (synthesizer, event) in synthesizer?.addSynthesizingEventHandler { [weak self] (synthesizer, event) in
guard let self = self else { return } guard let self = self else { return }
// 安全解包audioData // 安全解包audioData
@ -499,8 +495,8 @@ import os.log
os_log("合成进行中事件,音频数据为空", log: self.log, type: .debug) os_log("合成进行中事件,音频数据为空", log: self.log, type: .debug)
return return
} }
self.processSynthesisAudioChunk(text: "", incoming: audioData, multiple: 1280) os_log("合成进行中事件,音频数据长度: %d bytes", log: self.log, type: .debug, audioData.count)
os_log("合成进行中事件,累计缓存长度: %d bytes", log: self.log, type: .debug, self.ttsBuffer.count)
} }
// 合成完成事件 // 合成完成事件
@ -509,14 +505,16 @@ import os.log
os_log("合成完成事件", log: self.log, type: .info) os_log("合成完成事件", log: self.log, type: .info)
// 安全解包audioData // 安全解包audioData
guard let audioData = event.result.audioData else {
// 发送缓存中的剩余数据(可能非1280对齐的余量) os_log("合成完成事件,音频数据为空", log: self.log, type: .debug)
let remaining = self.ttsBuffer return
self.ttsBuffer = Data() }
os_log("合成完成事件,音频数据长度: %d bytes", log: self.log, type: .debug, audioData.count)
DispatchQueue.main.async { DispatchQueue.main.async {
self.serviceState.isSynthesizing = false self.serviceState.isSynthesizing = false
self.eventCallback?.onSynthesisAudioGenerated(text: "", audioData: remaining) // 立即返回当前生成的音频数据
self.eventCallback?.onStateChanged(component: "Synthesis", isActive: false) self.eventCallback?.onSynthesisAudioGenerated(text: "", audioData: audioData)
self.eventCallback?.onStateChanged(component: "Synthesis", isActive: false)
} }
} }
@ -527,8 +525,6 @@ import os.log
os_log("合成取消事件", log: self.log, type: .info) os_log("合成取消事件", log: self.log, type: .info)
self.serviceState.isSynthesizing = false self.serviceState.isSynthesizing = false
// 取消时清空缓存,避免脏数据
self.ttsBuffer = Data()
// 修复:移除可选链,因为event.result不是可选类型 // 修复:移除可选链,因为event.result不是可选类型
let reason = event.result.reason let reason = event.result.reason
@ -546,32 +542,6 @@ import os.log
} }
} }
/**
* 处理合成音频分片(按multiple字节对齐,默认1280)
* - 参数 text: 正在合成的文本
* - 参数 incoming: 新到达的音频数据块
* - 参数 multiple: 对齐字节倍数(例如16000Hz/16bit/mono下常用1280)
* 将incoming追加到缓存,仅当累计长度达到multiple的整数倍时,
* 发送对齐部分;余数继续保留在缓存,等待后续数据到来或合成完成时一次性发送。
*/
private func processSynthesisAudioChunk(text: String, incoming: Data?, multiple: Int = 1280) {
guard let incoming = incoming, !incoming.isEmpty else { return }
// 追加到缓存
ttsBuffer.append(incoming)
// 计算可发送的对齐长度
let sendLen = (ttsBuffer.count / multiple) * multiple
if sendLen > 0 {
let chunk = ttsBuffer.prefix(sendLen)
// 发送对齐部分
let toSend = Data(chunk)
DispatchQueue.main.async { [weak self] in
self?.eventCallback?.onSynthesisAudioGenerated(text: text, audioData: toSend)
}
// 保留余数
ttsBuffer = Data(ttsBuffer.suffix(ttsBuffer.count - sendLen))
}
}
// MARK: - Public Methods // MARK: - Public Methods
/** /**

Loading…
Cancel
Save