From cfd05ec155cab2224cb2f934908679ee776b9417 Mon Sep 17 00:00:00 2001 From: Roni bhakta <77425964+ronibhakta1@users.noreply.github.com> Date: Mon, 6 Jul 2026 18:16:42 +0530 Subject: [PATCH] feat: add demo page and update README with demo link; change voice gender to male --- README.md | 2 + app/data/voices/pocket/voices.json | 14 +- app/main.py | 5 + app/static/demo.html | 382 +++++++++++++++++++++++++++++ tests/test_demo.py | 9 + 5 files changed, 405 insertions(+), 7 deletions(-) create mode 100644 app/static/demo.html create mode 100644 tests/test_demo.py diff --git a/README.md b/README.md index ef3b516..7803f4f 100644 --- a/README.md +++ b/README.md @@ -42,6 +42,8 @@ curl -s -X POST http://localhost:8000/v1/synthesize \ > **First start** downloads the selected language models (~240 MB each) into a persistent Docker volume. Every restart after that is instant — models are already cached. +**Browser demo:** `http://localhost:8000/demo` (or `:8080` behind nginx in production). A single static page, served same-origin by the app itself — no build step, no extra dependency. Lets you pick a voice (with language/provider/gender filters), type an utterance, and hear it synthesized in-browser, with the equivalent `curl` command and raw response shown alongside. A "Developer tools" panel exposes the rest of the request body (format, bitrate, speed, pitch, sample rate, SSML, word-boundary mode) — fields confirmed to actually affect output are called out separately from ones the current provider silently ignores (see [`docs/API.md`](docs/API.md) "Not implemented"). + ### Production ```bash diff --git a/app/data/voices/pocket/voices.json b/app/data/voices/pocket/voices.json index 7e57798..1e92e0b 100644 --- a/app/data/voices/pocket/voices.json +++ b/app/data/voices/pocket/voices.json @@ -6,7 +6,7 @@ "originalName": "alba", "voiceURI": "urn:readium:tts:pocket:en-alba", "language": "en", - "gender": "female", + "gender": "male", "quality": "normal", "preloaded": true, "provider": "pocket", @@ -526,7 +526,7 @@ "originalName": "alba", "voiceURI": "urn:readium:tts:pocket:fr-alba", "language": "fr", - "gender": "female", + "gender": "male", "quality": "normal", "preloaded": true, "provider": "pocket", @@ -1046,7 +1046,7 @@ "originalName": "alba", "voiceURI": "urn:readium:tts:pocket:it-alba", "language": "it", - "gender": "female", + "gender": "male", "quality": "normal", "preloaded": true, "provider": "pocket", @@ -1566,7 +1566,7 @@ "originalName": "alba", "voiceURI": "urn:readium:tts:pocket:de-alba", "language": "de", - "gender": "female", + "gender": "male", "quality": "normal", "preloaded": true, "provider": "pocket", @@ -2086,7 +2086,7 @@ "originalName": "alba", "voiceURI": "urn:readium:tts:pocket:es-alba", "language": "es", - "gender": "female", + "gender": "male", "quality": "normal", "preloaded": true, "provider": "pocket", @@ -2606,7 +2606,7 @@ "originalName": "alba", "voiceURI": "urn:readium:tts:pocket:pt-alba", "language": "pt", - "gender": "female", + "gender": "male", "quality": "normal", "preloaded": true, "provider": "pocket", @@ -3119,4 +3119,4 @@ ], "pitchControl": false } -] \ No newline at end of file +] diff --git a/app/main.py b/app/main.py index f1de35d..d5facbb 100644 --- a/app/main.py +++ b/app/main.py @@ -2,6 +2,7 @@ from contextlib import asynccontextmanager from fastapi import FastAPI +from fastapi.responses import FileResponse from starlette.middleware.trustedhost import TrustedHostMiddleware from app.api.errors import register_error_handlers @@ -72,6 +73,10 @@ def create_app() -> FastAPI: app.include_router(health_router) app.include_router(v1_router, prefix=settings.api_v1_prefix) + @app.get("/demo", include_in_schema=False) + async def demo() -> FileResponse: + return FileResponse("app/static/demo.html") + return app diff --git a/app/static/demo.html b/app/static/demo.html new file mode 100644 index 0000000..47eca6b --- /dev/null +++ b/app/static/demo.html @@ -0,0 +1,382 @@ + + + + + +Speech Server Demo + + + +TTS API Demo +

Readium Speech Server

+

Talks to GET /v1/voices and POST /v1/synthesize on this same origin.

+ +
+ + + +
+
+ + +
+
+ + +
+
+ + +
+
+ + + + + + + + + + + + +
+ Developer tools — advanced request fields +
+
+ + +
+
+ + +
+
+
+
+ + +
+
+ + +
+
+
+ + +
+
+ + +
+
+
+ +

Response

+
+ +
(nothing yet)
+
+ +

+
+ Equivalent curl + +
+

+
+ + + + diff --git a/tests/test_demo.py b/tests/test_demo.py new file mode 100644 index 0000000..d8d4b51 --- /dev/null +++ b/tests/test_demo.py @@ -0,0 +1,9 @@ +import pytest +from httpx import AsyncClient + + +@pytest.mark.route +async def test_demo_page(client: AsyncClient) -> None: + resp = await client.get("/demo") + assert resp.status_code == 200 + assert resp.headers["content-type"].startswith("text/html")