mirror of
https://github.com/denizsafak/abogen.git
synced 2026-07-18 05:40:26 +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:
|
||||
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()
|
||||
use_gpu = bool(settings.get("use_gpu", False))
|
||||
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"))
|
||||
|
||||
flash("Debug WAV generation completed.", "success")
|
||||
return redirect(
|
||||
url_for(
|
||||
"settings.settings_page",
|
||||
debug_run_id=str(manifest.get("run_id") or ""),
|
||||
_anchor="debug",
|
||||
)
|
||||
return redirect(url_for("settings.debug_wavs_page", run_id=str(manifest.get("run_id") or "")))
|
||||
|
||||
|
||||
@settings_bp.get("/debug/<run_id>")
|
||||
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")
|
||||
assert resp.status_code in {302, 303}
|
||||
location = resp.headers.get("Location", "")
|
||||
assert "debug_run_id=" in location
|
||||
assert "/settings/debug/" in location
|
||||
|
||||
# Extract run id from query string.
|
||||
run_id = location.split("debug_run_id=")[1].split("&")[0].split("#")[0]
|
||||
# Extract run id from /settings/debug/<run_id>
|
||||
run_id = location.rsplit("/settings/debug/", 1)[1].split("?", 1)[0].split("#", 1)[0]
|
||||
manifest_path = tmp_path / "debug" / run_id / "manifest.json"
|
||||
assert manifest_path.exists()
|
||||
|
||||
|
||||
Reference in New Issue
Block a user