diff --git a/modules/turnero/views/display_global.php b/modules/turnero/views/display_global.php index 635c76a..648b379 100644 --- a/modules/turnero/views/display_global.php +++ b/modules/turnero/views/display_global.php @@ -578,17 +578,41 @@ function playBeep() { // Selección de voz española — cargada una vez, reutilizada en cada anuncio let _vozES = null; +// Voces preferidas, por nombre. Sabina (Windows) y Paulina (macOS) son las +// mexicanas locales: salen del propio equipo, así que nunca se cortan. Una +// colombiana local no existe —la es-CO de Chrome es de Google y se baja de +// internet en cada llamado—, y para leer letras, números y un nombre propio +// el acento mexicano se oye natural aquí; el de España no. +const VOCES_PREFERIDAS = ['sabina', 'paulina']; + function getVozES() { if (_vozES) return _vozES; - const voices = window.speechSynthesis.getVoices(); - // Preferencia: es-CO → es-419 → es-MX → es-US → es-ES → cualquier es-* - for (const lang of ['es-CO','es-419','es-MX','es-US','es-ES']) { - const v = voices.find(v => v.lang === lang); - if (v) { _vozES = v; return v; } + const voces = window.speechSynthesis.getVoices().filter(v => v.lang && v.lang.toLowerCase().startsWith('es')); + if (!voces.length) return null; + + const locales = voces.filter(v => v.localService); + const elegir = v => { _vozES = v; return v; }; + + // 1. Las pedidas por nombre, si están instaladas + for (const nombre of VOCES_PREFERIDAS) { + const v = locales.find(v => v.name.toLowerCase().includes(nombre)); + if (v) return elegir(v); } - const v = voices.find(v => v.lang.startsWith('es')); - if (v) { _vozES = v; } - return _vozES; + // 2. Cualquier otra local latinoamericana + for (const lang of ['es-MX', 'es-419', 'es-US', 'es-CO']) { + const v = locales.find(v => v.lang === lang); + if (v) return elegir(v); + } + // 3. Cualquier local, aunque sea de España: peor acento, pero no se corta + if (locales.length) return elegir(locales[0]); + + // 4. Sin ninguna local, queda la remota. Suena mejor, pero depende del wifi: + // es la que venía entrecortándose. + for (const lang of ['es-CO', 'es-419', 'es-MX', 'es-US', 'es-ES']) { + const v = voces.find(v => v.lang === lang); + if (v) return elegir(v); + } + return elegir(voces[0]); } if ('speechSynthesis' in window) { window.speechSynthesis.onvoiceschanged = () => { _vozES = null; getVozES(); }; diff --git a/modules/turnero/views/voces.php b/modules/turnero/views/voces.php index e88a345..2306798 100644 --- a/modules/turnero/views/voces.php +++ b/modules/turnero/views/voces.php @@ -78,14 +78,27 @@ // El mismo texto que dice la pantalla de turnos, para juzgarlas en condiciones const TEXTO = 'Turno A 0 1, María Fernanda Gómez, pase a Consultorio 2'; -// Réplica de la preferencia que usa display_global.php hoy, para señalar -// cuál está sonando en este momento en el televisor. +// Réplica de la preferencia de display_global.php, para señalar cuál está +// sonando. Si allá se cambia el orden, hay que cambiarlo aquí también. +const VOCES_PREFERIDAS = ['sabina', 'paulina']; + function vozActual(voces) { + if (!voces.length) return null; + const locales = voces.filter(v => v.localService); + for (const nombre of VOCES_PREFERIDAS) { + const v = locales.find(v => v.name.toLowerCase().includes(nombre)); + if (v) return v; + } + for (const lang of ['es-MX','es-419','es-US','es-CO']) { + const v = locales.find(v => v.lang === lang); + if (v) return v; + } + if (locales.length) return locales[0]; for (const lang of ['es-CO','es-419','es-MX','es-US','es-ES']) { const v = voces.find(v => v.lang === lang); if (v) return v; } - return voces.find(v => v.lang.startsWith('es')) || null; + return voces[0]; } function probar(voz) {