stt: debug-дампы аудио-пути (очки: сырой микрофон в WAV; телефон: принятые PCM) по старту от stt_dump.marker
This commit is contained in:
@@ -366,6 +366,11 @@ class PhoneApp : Application() {
|
||||
tokensPath = tokens.absolutePath,
|
||||
numThreads = 4,
|
||||
)
|
||||
val dumpPcm = if (File(filesDir, "stt_dump.marker").exists()) {
|
||||
File(filesDir, "stt_dump_phone.raw")
|
||||
} else {
|
||||
null
|
||||
}
|
||||
val s = SttStreamer(
|
||||
stt = whisper,
|
||||
vad = SherpaStreamingVad(vadModel.absolutePath),
|
||||
@@ -378,8 +383,10 @@ class PhoneApp : Application() {
|
||||
log("stt", "тишина 30 с — автo-отмена")
|
||||
scope.launch { server.hub.broadcast(SttCancel(reason = "timeout")) }
|
||||
},
|
||||
dumpPcm = dumpPcm,
|
||||
)
|
||||
sttStreamer = s
|
||||
log("stt", "PCM-дампа (телефон): ${dumpPcm?.absolutePath ?: "off"}")
|
||||
log("stt", "SttStreamer готов (Whisper-small int8, VAD fp32)")
|
||||
return s
|
||||
}
|
||||
|
||||
@@ -1,10 +1,13 @@
|
||||
package pw.binom.viewmate.phone.stt
|
||||
|
||||
import java.io.File
|
||||
import java.io.FileOutputStream
|
||||
import java.util.concurrent.Executors
|
||||
import java.util.concurrent.Future
|
||||
import java.util.concurrent.TimeUnit
|
||||
import kotlin.concurrent.thread
|
||||
import kotlin.concurrent.withLock
|
||||
import pw.binom.viewmate.phone.log
|
||||
|
||||
/** s16le (16 кГц, mono) → FloatArray [-1, 1]. Чистая функция — покрыта тестами. */
|
||||
internal fun s16leToFloat(pcm: ByteArray): FloatArray {
|
||||
@@ -37,6 +40,7 @@ class SttStreamer(
|
||||
private val vad: StreamingVad,
|
||||
private val onPhrase: (phrase: String, full: String) -> Unit,
|
||||
private val onSilence30s: () -> Unit,
|
||||
private val dumpPcm: File? = null,
|
||||
) {
|
||||
companion object {
|
||||
private const val SILENCE_TIMEOUT_MS = 30_000L
|
||||
@@ -60,6 +64,18 @@ class SttStreamer(
|
||||
@Volatile
|
||||
private var deadlineMs = 0L
|
||||
|
||||
/**
|
||||
* Debug-дампа принятых PCM: сырые s16le (16 кГц, mono), без WAV-заголовка —
|
||||
* формат помечен в логе. Сбой открытия не ломает распознавание.
|
||||
*/
|
||||
private val dumpOut: FileOutputStream? = dumpPcm?.let { file ->
|
||||
runCatching {
|
||||
FileOutputStream(file, true).also {
|
||||
log("stt", "PCM-дампа: ${file.absolutePath} (16 кГц, s16, mono)")
|
||||
}
|
||||
}.onFailure { log("stt", "PCM-дампа: ${it.message}") }.getOrNull()
|
||||
}
|
||||
|
||||
/** Недозаполненные сэмплы (< 512) для следующего окна VAD. */
|
||||
private var pending = FloatArray(0)
|
||||
|
||||
@@ -109,6 +125,11 @@ class SttStreamer(
|
||||
}
|
||||
if (i < floats.size) pending = floats.copyOfRange(i, floats.size)
|
||||
}
|
||||
val out = dumpOut
|
||||
if (out != null) {
|
||||
runCatching { out.write(pcm) }
|
||||
.onFailure { log("stt", "PCM-дампа: ${it.message}") }
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -141,6 +162,8 @@ class SttStreamer(
|
||||
deadlineMs = 0
|
||||
vad.close()
|
||||
}
|
||||
runCatching { dumpOut?.close() }
|
||||
.onFailure { log("stt", "PCM-дампа: ${it.message}") }
|
||||
executor.shutdownNow()
|
||||
watchdog.interrupt()
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user