fix(voices): /voices reflète l'inventaire CosyVoice (.cvps), pas les vestiges Qwen3
voicesCursor() marquait une voix « ready » dès que ses embeddings Qwen3 (_voice_prefix/suffix.bin) existaient — des vestiges morts depuis la bascule CosyVoice → des voix fantômes « prête » sans aucun .cvps (incident zelda). Désormais : union (WAV = « à convertir ») ∪ (cosyvoice/*.cvps = « prête ») ; les .bin Qwen3 ne sont plus comptés ; nouvelle colonne cvps_exists (additive). Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
parent
613c7efc66
commit
8bcf9f8ebe
|
|
@ -79,6 +79,11 @@ class KazeiaTelemetryProvider : ContentProvider() {
|
|||
get() = "${com.kazeia.KazeiaApplication.MODELS_DIR}/qwen3-tts-npu"
|
||||
private const val PREFIX_SUFFIX = "_voice_prefix.bin"
|
||||
private const val SUFFIX_SUFFIX = "_voice_suffix.bin"
|
||||
// Voix CosyVoice (prod) : artefacts `.cvps` enrôlés. C'est l'inventaire réel
|
||||
// depuis la bascule ; les `_voice_*.bin` ci-dessus sont des vestiges Qwen3.
|
||||
private val VOICE_CVPS_DIR: String
|
||||
get() = "${com.kazeia.KazeiaApplication.MODELS_DIR}/cosyvoice"
|
||||
private const val CVPS_SUFFIX = ".cvps"
|
||||
}
|
||||
|
||||
private val matcher = UriMatcher(UriMatcher.NO_MATCH).apply {
|
||||
|
|
@ -526,26 +531,32 @@ class KazeiaTelemetryProvider : ContentProvider() {
|
|||
private fun voicesCursor(): Cursor {
|
||||
val cols = arrayOf(
|
||||
"id", "name", "state",
|
||||
"wav_exists", "prefix_exists", "suffix_exists",
|
||||
"wav_exists", "prefix_exists", "suffix_exists", "cvps_exists",
|
||||
"wav_size_bytes", "wav_duration_seconds", "wav_path", "created_at"
|
||||
)
|
||||
val cursor = MatrixCursor(cols)
|
||||
|
||||
// Set des ids = union (wav basenames) ∪ (prefix bin basenames)
|
||||
// Inventaire = réalité CosyVoice : union (WAV = « à convertir ») ∪
|
||||
// (`.cvps` = « prête »). Les embeddings Qwen3 (`_voice_*.bin`) NE sont plus
|
||||
// comptés dans l'union : vestiges morts depuis la bascule, ils faisaient
|
||||
// apparaître des voix « prête » fantômes sans aucun `.cvps`.
|
||||
val wavDir = File(VOICE_WAV_DIR)
|
||||
val embDir = File(VOICE_EMB_DIR)
|
||||
val cvpsDir = File(VOICE_CVPS_DIR)
|
||||
val wavIds = (wavDir.listFiles { f -> f.name.endsWith(".wav") } ?: emptyArray())
|
||||
.associateBy { it.nameWithoutExtension.lowercase() }
|
||||
val prefixIds = (embDir.listFiles { f -> f.name.endsWith(PREFIX_SUFFIX) } ?: emptyArray())
|
||||
.associateBy { it.name.removeSuffix(PREFIX_SUFFIX).lowercase() }
|
||||
val ids = (wavIds.keys + prefixIds.keys).sorted()
|
||||
val cvpsIds = (cvpsDir.listFiles { f -> f.name.endsWith(CVPS_SUFFIX) } ?: emptyArray())
|
||||
.associateBy { it.name.removeSuffix(CVPS_SUFFIX).lowercase() }
|
||||
val ids = (wavIds.keys + cvpsIds.keys).sorted()
|
||||
|
||||
for (id in ids) {
|
||||
val wav = wavIds[id]
|
||||
val cvps = cvpsIds[id]
|
||||
val prefix = File(VOICE_EMB_DIR, "${id}$PREFIX_SUFFIX")
|
||||
val suffix = File(VOICE_EMB_DIR, "${id}$SUFFIX_SUFFIX")
|
||||
// « ready » = `.cvps` déployé (jouable par CosyVoice) ; « recorded » =
|
||||
// WAV seul (à convertir/enrôler par Kazeia-central) ; sinon « error ».
|
||||
val state = when {
|
||||
prefix.exists() && suffix.exists() -> "ready"
|
||||
cvps != null -> "ready"
|
||||
wav != null -> "recorded"
|
||||
else -> "error"
|
||||
}
|
||||
|
|
@ -557,10 +568,11 @@ class KazeiaTelemetryProvider : ContentProvider() {
|
|||
if (wav != null) 1 else 0,
|
||||
if (prefix.exists()) 1 else 0,
|
||||
if (suffix.exists()) 1 else 0,
|
||||
if (cvps != null) 1 else 0,
|
||||
wav?.length() ?: 0L,
|
||||
durSec,
|
||||
wav?.absolutePath ?: "",
|
||||
wav?.lastModified() ?: prefix.lastModified()
|
||||
wav?.lastModified() ?: cvps?.lastModified() ?: 0L
|
||||
))
|
||||
}
|
||||
return cursor
|
||||
|
|
|
|||
Loading…
Reference in New Issue