BioScan Museo’s audio narration system uses a separateDocumentation Index
Fetch the complete documentation index at: https://mintlify.com/GustavoNightmare/InformacionMuseo/llms.txt
Use this file to discover all available pages before exploring further.
servertts microservice to pre-generate MP3 files for each species. The integration is push-based: Flask calls the TTS service whenever a species record is created, edited, or has its QR style updated — the TTS service never pulls data from Flask. There is no /api/public route registered in Flask; all species data flows outward from Flask to the TTS sidecar via its /internal/species/sync and /internal/species/delete endpoints.
How the push pipeline works
When an admin saves a species through the admin panel, Flask performs the following steps after committing the database change:- Builds a structured content payload with
build_species_tts_payload(). - Calls
sync_species_to_tts(), which POSTs that payload to the TTS sidecar’s/internal/species/syncendpoint, authenticated with theMUSEO_TTS_SHARED_KEYshared secret. - The TTS service stores the payload locally and pre-generates audio files in one or more narration styles.
delete_species_from_tts() instead, which POSTs to the TTS sidecar’s /internal/species/delete endpoint so the sidecar can purge the corresponding audio files.
The two environment variables that govern the integration are:
| Variable | Purpose |
|---|---|
MUSEO_TTS_INTERNAL_BASE_URL | Base URL of the TTS sidecar reachable from Flask (internal network). Falls back to MUSEO_TTS_PUBLIC_BASE_URL if unset. If both are empty, sync calls are silently skipped. |
MUSEO_TTS_SHARED_KEY | Shared secret sent as the X-API-Key header on every request Flask makes to the TTS sidecar. A missing or empty key causes sync_species_to_tts() and delete_species_from_tts() to raise RuntimeError. |
build_species_tts_payload()
Defined inapp.py, this function constructs the JSON object that Flask sends to the TTS sidecar. It reads directly from the Species model and applies no transformations other than replacing None with safe defaults.
Payload fields
The internal primary-key ID of the species (
Species.id).The QR slug. Falls back to
species_id when Species.qr_id is not set.Common display name (
nombre_comun). Empty string if not set.Scientific name (
nombre_cientifico). Empty string if not set.Free-text species description (
descripcion). Empty string if not set.Habitat description (
habitat). Empty string if not set.Diet description (
dieta). Empty string if not set.List of curiosity strings, deserialised from
curiosidades_json. Empty array if none are stored.Example payload
sync_species_to_tts()
Called automatically after every successful species create or edit (including QR style updates). Posts thebuild_species_tts_payload() result to POST {MUSEO_TTS_INTERNAL_BASE_URL}/internal/species/sync with a 180-second timeout. If the TTS service returns HTTP 400 or higher, a RuntimeError is raised and Flask shows a flash warning — the species record itself has already been saved.
When it is called
| Admin action | Triggers sync? |
|---|---|
Create new species (POST /admin/especies/nueva) | ✅ Yes |
Edit species (POST /admin/especies/<id>/editar) | ✅ Yes |
Save QR style (POST /admin/qr/<id>/personalizar) | ✅ Yes |
Delete species (POST /admin/especies/<id>/eliminar) | ❌ No — calls delete_species_from_tts() instead |
Reindex RAG (POST /admin/especies/<id>/reindex) | ❌ No |
delete_species_from_tts()
Called immediately after a species is deleted from the database. Posts a minimal JSON body toPOST {MUSEO_TTS_INTERNAL_BASE_URL}/internal/species/delete so the TTS sidecar can purge the corresponding audio files. Uses a 60-second timeout. Errors are silently swallowed at the call site to prevent a TTS failure from blocking the admin UI.
Delete request body
| Field | Type | Description |
|---|---|---|
species_id | string | Internal species ID (Species.id). Always present. |
qr_id | string | QR slug captured before the delete. Included when available so the TTS sidecar can locate audio files by slug. |
Environment variable reference
| Variable | Required | Description |
|---|---|---|
MUSEO_TTS_INTERNAL_BASE_URL | Recommended | Internal base URL of the TTS sidecar (e.g., http://servertts:8010). If empty, sync and delete calls are skipped silently. Takes precedence over MUSEO_TTS_PUBLIC_BASE_URL. |
MUSEO_TTS_PUBLIC_BASE_URL | Fallback | Public base URL used when MUSEO_TTS_INTERNAL_BASE_URL is not set. |
MUSEO_TTS_SHARED_KEY | Required when TTS URL is set | Shared secret sent as the X-API-Key header. Both Flask and the TTS sidecar must be configured with the same value. |
There is no Flask endpoint that the TTS sidecar calls to retrieve species data. The data flow is one-way: Flask → TTS sidecar. Kiosk apps and visitor-facing clients that need audio narration should request MP3 files directly from the TTS service (e.g.,
GET /tts/by-qr/<qr_id>?key=<TTS_API_KEY>), not from Flask.