mirror of
https://github.com/denizsafak/abogen.git
synced 2026-07-18 13:40:27 +02:00
feat: Implement language aliasing in debug TTS and add debug WAVs page with artifact handling
This commit is contained in:
@@ -90,7 +90,29 @@ def run_debug_tts_wavs(
|
|||||||
if missing:
|
if missing:
|
||||||
raise RuntimeError(f"Debug EPUB missing expected codes: {', '.join(missing)}")
|
raise RuntimeError(f"Debug EPUB missing expected codes: {', '.join(missing)}")
|
||||||
|
|
||||||
language = str(settings.get("language") or "en").strip() or "en"
|
language = str(settings.get("language") or "a").strip() or "a"
|
||||||
|
# Kokoro's KPipeline expects short language codes like "a" (American English),
|
||||||
|
# but older settings may store ISO-like values such as "en".
|
||||||
|
language_aliases = {
|
||||||
|
"en": "a",
|
||||||
|
"en-us": "a",
|
||||||
|
"en_us": "a",
|
||||||
|
"en-gb": "b",
|
||||||
|
"en_gb": "b",
|
||||||
|
"es": "e",
|
||||||
|
"es-es": "e",
|
||||||
|
"fr": "f",
|
||||||
|
"fr-fr": "f",
|
||||||
|
"hi": "h",
|
||||||
|
"it": "i",
|
||||||
|
"pt": "p",
|
||||||
|
"pt-br": "p",
|
||||||
|
"ja": "j",
|
||||||
|
"jp": "j",
|
||||||
|
"zh": "z",
|
||||||
|
"zh-cn": "z",
|
||||||
|
}
|
||||||
|
language = language_aliases.get(language.lower(), language)
|
||||||
voice_spec = str(settings.get("default_voice") or "").strip()
|
voice_spec = str(settings.get("default_voice") or "").strip()
|
||||||
use_gpu = bool(settings.get("use_gpu", False))
|
use_gpu = bool(settings.get("use_gpu", False))
|
||||||
speed = float(settings.get("default_speed", 1.0) or 1.0)
|
speed = float(settings.get("default_speed", 1.0) or 1.0)
|
||||||
|
|||||||
@@ -195,12 +195,38 @@ def run_debug_wavs() -> ResponseReturnValue:
|
|||||||
return redirect(url_for("settings.settings_page", _anchor="debug"))
|
return redirect(url_for("settings.settings_page", _anchor="debug"))
|
||||||
|
|
||||||
flash("Debug WAV generation completed.", "success")
|
flash("Debug WAV generation completed.", "success")
|
||||||
return redirect(
|
return redirect(url_for("settings.debug_wavs_page", run_id=str(manifest.get("run_id") or "")))
|
||||||
url_for(
|
|
||||||
"settings.settings_page",
|
|
||||||
debug_run_id=str(manifest.get("run_id") or ""),
|
@settings_bp.get("/debug/<run_id>")
|
||||||
_anchor="debug",
|
def debug_wavs_page(run_id: str) -> ResponseReturnValue:
|
||||||
)
|
safe_run = (run_id or "").strip()
|
||||||
|
if not safe_run:
|
||||||
|
abort(404)
|
||||||
|
|
||||||
|
root = Path(current_app.config.get("OUTPUT_FOLDER") or get_user_output_path("web"))
|
||||||
|
run_dir = (root / "debug" / safe_run).resolve()
|
||||||
|
manifest_path = run_dir / "manifest.json"
|
||||||
|
if not manifest_path.exists():
|
||||||
|
abort(404)
|
||||||
|
|
||||||
|
try:
|
||||||
|
import json
|
||||||
|
|
||||||
|
manifest = json.loads(manifest_path.read_text(encoding="utf-8"))
|
||||||
|
except Exception:
|
||||||
|
abort(404)
|
||||||
|
|
||||||
|
artifacts = manifest.get("artifacts") or []
|
||||||
|
# Precompute download URLs for each artifact.
|
||||||
|
for item in artifacts:
|
||||||
|
filename = str(item.get("filename") or "")
|
||||||
|
item["url"] = url_for("settings.download_debug_wav", run_id=safe_run, filename=filename)
|
||||||
|
|
||||||
|
return render_template(
|
||||||
|
"debug_wavs.html",
|
||||||
|
run_id=safe_run,
|
||||||
|
artifacts=artifacts,
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -0,0 +1,61 @@
|
|||||||
|
{% extends "base.html" %}
|
||||||
|
|
||||||
|
{% block title %}abogen · Debug WAVs{% endblock %}
|
||||||
|
|
||||||
|
{% block content %}
|
||||||
|
<section class="card">
|
||||||
|
<h1 class="card__title">Debug WAVs</h1>
|
||||||
|
<p class="tag">Run ID: <code>{{ run_id }}</code></p>
|
||||||
|
|
||||||
|
<div class="field field--stack">
|
||||||
|
<audio data-role="debug-audio" controls preload="none" style="width: 100%;"></audio>
|
||||||
|
<p class="hint">Click an ID to play its WAV. “Overall” is the concatenation of all samples.</p>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
{% if artifacts %}
|
||||||
|
<div class="field field--wide">
|
||||||
|
<label>Samples</label>
|
||||||
|
<ul>
|
||||||
|
{% for item in artifacts %}
|
||||||
|
<li>
|
||||||
|
<button
|
||||||
|
type="button"
|
||||||
|
class="button button--ghost"
|
||||||
|
data-role="debug-play"
|
||||||
|
data-audio-src="{{ item.url }}"
|
||||||
|
>
|
||||||
|
{{ item.label }}
|
||||||
|
</button>
|
||||||
|
<a class="muted" href="{{ item.url }}" download>{{ item.filename }}</a>
|
||||||
|
</li>
|
||||||
|
{% endfor %}
|
||||||
|
</ul>
|
||||||
|
</div>
|
||||||
|
{% endif %}
|
||||||
|
|
||||||
|
<div class="field field--inline">
|
||||||
|
<a href="{{ url_for('settings.settings_page', _anchor='debug') }}" class="button button--ghost">Back to Settings</a>
|
||||||
|
</div>
|
||||||
|
</section>
|
||||||
|
|
||||||
|
<script>
|
||||||
|
(function () {
|
||||||
|
const audio = document.querySelector('[data-role="debug-audio"]');
|
||||||
|
const buttons = Array.from(document.querySelectorAll('[data-role="debug-play"]'));
|
||||||
|
if (!audio || !buttons.length) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
buttons.forEach((button) => {
|
||||||
|
button.addEventListener('click', () => {
|
||||||
|
const src = button.dataset.audioSrc;
|
||||||
|
if (!src) return;
|
||||||
|
if (audio.src !== src) {
|
||||||
|
audio.src = src;
|
||||||
|
}
|
||||||
|
audio.play();
|
||||||
|
});
|
||||||
|
});
|
||||||
|
})();
|
||||||
|
</script>
|
||||||
|
{% endblock %}
|
||||||
@@ -84,10 +84,10 @@ def test_settings_debug_route_writes_manifest(tmp_path, monkeypatch):
|
|||||||
resp = client.post("/settings/debug/run")
|
resp = client.post("/settings/debug/run")
|
||||||
assert resp.status_code in {302, 303}
|
assert resp.status_code in {302, 303}
|
||||||
location = resp.headers.get("Location", "")
|
location = resp.headers.get("Location", "")
|
||||||
assert "debug_run_id=" in location
|
assert "/settings/debug/" in location
|
||||||
|
|
||||||
# Extract run id from query string.
|
# Extract run id from /settings/debug/<run_id>
|
||||||
run_id = location.split("debug_run_id=")[1].split("&")[0].split("#")[0]
|
run_id = location.rsplit("/settings/debug/", 1)[1].split("?", 1)[0].split("#", 1)[0]
|
||||||
manifest_path = tmp_path / "debug" / run_id / "manifest.json"
|
manifest_path = tmp_path / "debug" / run_id / "manifest.json"
|
||||||
assert manifest_path.exists()
|
assert manifest_path.exists()
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user