Google TV

APPS

Google TV (basat en Android TV) té accés a una gran part de l’ecosistema d’aplicacions d’Android, però no totes les aplicacions de Google Play Store són compatibles amb Google TV. La compatibilitat depèn de diversos factors:

  • L’aplicació ha de ser compatible amb Android TV o declarar suport per a pantalles grans i controls remots.
  • Algunes apps es mostren a Google TV només si estan optimitzades per a aquesta interfície (interfície de 10 peus – 10-foot UI).
  • Les aplicacions que requereixen touchscreen, sensors específics o funcionalitats no disponibles en TV (com càmera, GPS, etc.) sovint no es mostren a la botiga de Google TV.

Categories d’aplicacions disponibles a Google TV

Tot i que no existeix un llistat oficial complet i dinàmic mantingut per Google (la botiga es filtra dinàmicament segons el dispositiu), sí que es poden identificar categories i exemples comuns:

1. Streaming i vídeo

  • YouTube
  • YouTube TV
  • Netflix
  • Amazon Prime Video
  • Disney+
  • HBO Max / Max
  • Hulu
  • Apple TV+
  • Rakuten TV
  • Rakuten Viki
  • Crunchyroll
  • Plex
  • VLC (limitat)
  • Tubi
  • Peacock
  • Pluto TV
  • Sling TV

2. Música i àudio

  • Spotify
  • YouTube Music
  • Pandora
  • Tidal
  • Deezer
  • TuneIn Radio
  • iHeartRadio

3. Jocs (limitat)

  • Google Play Games (només jocs compatibles amb comandament)
  • Atari Flashback
  • Tetris
  • Solitaire
  • Chess.com
  • Stadia (descontinuat, però alguns dispositius encara el tenen)
  • Jocs de taula o casuals compatibles amb D-pad

4. Esports i notícies

  • ESPN
  • DAZN
  • CBS Sports
  • Sky News
  • BBC News
  • France 24

5. Educació i nens

  • PBS Kids
  • Khan Academy Kids
  • YouTube Kids
  • Lingokids

6. Productivitat i utilitats (molt limitat)

  • Google Chrome (com a navegador web senzill)
  • Google Photos
  • Google Drive (visualització bàsica)
  • Web Video Cast (per emetre contingut del mòbil)

7. Cast i control remot

  • Google Home
  • Android TV Remote Control
  • BubbleUPnP (per DLNA/UPnP)
  • Kodi (si instal·lat manualment)

Com trobar totes les apps disponibles per a Google TV

  1. Des del propi dispositiu Google TV:
  • Obre Google Play Store a la TV.
  • Ves a Apps o Categorias → només es mostren apps compatibles.
  1. Des del navegador (des del PC o mòbil):
  • Ves a https://play.google.com/store/apps
  • Accedeix des d’un compte vinculat al teu dispositiu Google TV.
  • Filtra per “Apps para Android TV” (normalment no apareix explícitament, però si cerques una app concreta, et diu “Compatible amb el teu dispositiu” si ho és).
  1. Instal·lació manual (APK):
  • Algunes apps no disponibles a la botiga es poden instal·lar manualment via ADB o Downloader, però no sempre funcionen bé sense interfície adaptada.

Limitacions importants

  • Cap accés directe a apps mòbils no optimitzades: per exemple, Instagram, WhatsApp, TikTok, etc., no estan disponibles.
  • La interfície depèn del fabricant: Hisense, Sony, TCL, etc., poden afegir o amagar apps segons acords comercials.
  • Google TV ≠ Android TV: Google TV és una capa d’interfície sobre Android TV. Totes les apps d’Android TV funcionen a Google TV, però la inversa no sempre és recomanada (si l’app no ha estat provada en entorn TV).

Si tens un tipus concret d’aplicació en ment (per exemple, “vull saber si hi ha apps de diccionari o TTS per a Google TV”), puc fer una cerca més específica.

Funció TTS dels navegadors: SpeechSynthesis

<?php

// 🔴 🔴 🔴 CANVI 1: Mapeig de codis curts ('cat', 'eng', etc.) a codis d'idioma vàlids
session_start();

// Mapeig de codis curts a codis d'idioma vàlids per a l'àudio
// Mapeig de codis curts a codis d'idioma vàlids per a l'àudio
$langMap = [
    'cat' => 'ca-ES', // Català (Espanya)
    'eus' => 'eu-ES', // Euskera / Basc (Espanya)
    'cas' => 'es-ES', // Castellà / Espanyol (Espanya)
    'eng' => 'en-US', // Anglès (Estats Units)
    'fra' => 'fr-FR', // Francès (França)
    'ger' => 'de-DE', // Alemany (Alemanya)
    'por' => 'pt-PT', // Portuguès (Portugal)
    'ita' => 'it-IT'  // Italià (Itàlia)
];

// Comprovem si $_SESSION['lang'] està definit i és vàlid
$shortLang = $_SESSION['lang'] ; // Assigna 'cat' si $_SESSION['lang'] no està definit

// Assignem el codi d'àudio corresponent
$_SESSION['lang_audio'] = $langMap[$shortLang] ?? 'es-ES'; // Assegura que sigui 'ca-ES' si el codi no es troba al mapeig

// Mostrem el resultat
//echo "<br>SESSION['lang_audio']: " . $_SESSION['lang_audio'];

// 🔴 🔴 🔴 fi CANVI
?>
<?php 
//echo $_SESSION['resposta']; //prova per veure que entra bé
   // exit ('31');
?>
 <form id="cercaForm" method="POST" action="BD_conexions/conexio_diccionari_bd.php">
 
             <div class="search-container">
                <!-- Camp de cerca -->
                <input 
            type="text" 
            id="cercar" 
            name="cercar" 
            onkeyup="" 
            placeholder="cercar.." 
            autofocus 
            value="<?php echo isset($_SESSION['cercar']) ? htmlspecialchars($_SESSION['cercar'], 
                    ENT_QUOTES, 'UTF-8') : ''; ?>"
                    >
                <!-- Botó de cerca -->
                <button type="submit">Cercar/Confirmar</button>
                <button id="speakButton" title="Llegir en veu alta">
                <span>🔊</span> 
                </button>
            </div> 
    <div>
  
    <p>
    <input type="button" value="<?php echo '-num-'.  $_SESSION['num'].'--'; ?>" style="display:none;">
    <input type="button" value="<?php echo '-id-'.  $_SESSION['id'].'--'; ?>" style="display:none;">
    <input type="button" value="<?php echo '-retorn-'. $_SESSION['nom'].'--'; ?>" style="display:none;">
    <input type="button" value="<?php echo '--'.  $_SESSION['lang_r'].'--'; ?>" style="display:none;">
    <input type="button" value="<?php echo '-1-'. $_SESSION['diccionari'].'--'; ?>" style="display:none;">
    <input type="button" value="<?php echo '-2-'. $_SESSION['diccionari_r'].'--'; ?>" style="display:none;">
    <input type="button" value="<?php echo '-3-'. $_SESSION['dic'].'--'; ?>" style="display:none;">
    <input type="button" value="<?php echo '--'. $_SESSION['bd']; ?>" style="display:none;">
    <input type="button" value="<?php echo '--'. $_SESSION['bd_r']; ?>" style="display:none;">
    <input
        type="text" 
        id="dicionari_A"
        name="dicionari_AJ" 
        onkeyup="" 
        placeholder=<?php echo htmlspecialchars($_SESSION['diccionari']); ?>
        autofocus
        data-diccionari=<?php echo htmlspecialchars($_SESSION['diccionari']); ?>
        style="display:none;">
</p>
<script>
        // Capturar elements del DOM
        const entrada = document.getElementById('cercar'); // Primer camp de text
        const boto = document.getElementById('boto');       // Botó
        const sortida = document.getElementById('replicar'); // Segon camp de text

        // Afegir un event listener al botó
        boto.addEventListener('click', function() {
            // Obtenir el valor de la primera entrada
            const text = entrada.value;

            // Assignar el valor a la segona entrada
            sortida.value = text;
        });
        
    </script>



<script>
  
  document.addEventListener('DOMContentLoaded', () => {
    const inputElement = document.getElementById('cercar');
    const speakBtn = document.getElementById('speakButton');
    let voices = [];

    // 🔴 Carreguem l'idioma des de PHP
    const userLang = '<?php echo addslashes($_SESSION["lang_audio"]); ?>';

    function loadVoices() {
      voices = speechSynthesis.getVoices();
    }

    speechSynthesis.onvoiceschanged = loadVoices;
    loadVoices();

    function speakText() {
      const text = inputElement.value.trim();
      if (!text) return;

      const utterance = new SpeechSynthesisUtterance(text);

      // 🔴 Busquem una veu que suporti l'idioma de la sessió (ex: 'ca-ES')
      let selectedVoice = voices.find(v => v.lang === userLang);

      // Si no n'hi ha d'exacta, provem amb el codi base (ex: 'ca')
      if (!selectedVoice) {
        const baseLang = userLang.split('-')[0];
        selectedVoice = voices.find(v => v.lang.startsWith(baseLang));
      }

      // Assignem la veu trobada (o només l'idioma si no hi ha veu específica)
      if (selectedVoice) {
        utterance.voice = selectedVoice;
        utterance.lang = selectedVoice.lang;
      } else {
        utterance.lang = userLang; // el navegador triarà una veu
      }

      utterance.rate = 1;
      utterance.pitch = 1;

      speechSynthesis.cancel();
      speechSynthesis.speak(utterance);
    }

    speakBtn.addEventListener('click', (e) => {
      e.preventDefault();
      speakText();
    });
  });

</script>


    </div>
             <!-- Contenidor de l'autocompletat -->
             <div id="resultats_autocompletar_container">
                <ul id="resultats_autocompletar">
                    <!-- Resultats dinàmics via JavaScript -->
                </ul>
            </div>
            


        </form>
    

🌟🌟Simple text a veu

Conversor de text a veu

🔊 Conversor de text a veu

<!DOCTYPE html>
<html lang="ca">
<head>
  <meta charset="UTF-8">
  <title>Conversor de text a veu</title>
  <style>
    body {
      font-family: sans-serif;
      padding: 2em;
      background-color: #f4f4f4;
    }
    input {
      font-size: 1.2em;
      padding: 0.5em;
      margin-top: 1em;
      width: 100%;
      max-width: 500px;
    }
    #speakBtn {
      font-size: 2em;
      background: none;
      border: none;
      cursor: pointer;
      margin-top: 1em;
    }
    #speakBtn:hover {
      color: #0078D7;
    }
  </style>
</head>
<body>
  <h2>🔊 Conversor de text a veu</h2>
  <input type="text" id="cercar" placeholder="Escriu el text que vols escoltar">
  <button id="speakBtn" title="Escolta el text">🔊</button>

  <script>
    document.addEventListener('DOMContentLoaded', () => {
      const inputElement = document.getElementById('cercar');
      const speakBtn = document.getElementById('speakBtn');
      let voices = [];

      function loadVoices() {
        voices = speechSynthesis.getVoices();
      }

      speechSynthesis.onvoiceschanged = loadVoices;
      loadVoices();

      function speakText() {
        const text = inputElement.value.trim();
        if (!text) return;

        const utterance = new SpeechSynthesisUtterance(text);
        const zira = voices.find(v => v.name === 'Microsoft Zira - English (United States)');

        if (zira) {
          utterance.voice = zira;
          utterance.lang = zira.lang;
        }

        utterance.rate = 1;
        utterance.pitch = 1;

        speechSynthesis.cancel();
        speechSynthesis.speak(utterance);
      }

      speakBtn.addEventListener('click', speakText);

      // 🔁 Repetir cada 10 segons
      setInterval(speakText, 10000);
    });
  </script>
</body>
</html>

Verbe avoir — 3ᵉ groupe

Présent verbe avoir

j’ai

tu as

il a

nous avons

vous avez

ils ont

Passé Composé

j’ai eu

tu as eu

il a eu

nous avons eu

vous avez eu

ils ont eu

Imparfait

j’avais

tu avais

il avait

nous avions

vous aviez

ils avaient

Plus-que-parfait

j’avais eu

tu avais eu

il avait eu

nous avions eu

vous aviez eu

ils avaient eu

Futur Simple

j’aurai

tu auras

il aura

nous aurons

vous aurez

ils auront

Futur Antérieur

j’aurai eu

tu auras eu

il aura eu

nous aurons eu

vous aurez eu

ils auront eu

Passé Simple

j’eus

tu eus

il eut

nous eûmes

vous eûtes

ils eurent

Passé Antérieur

j’eus eu

tu eus eu

il eut eu

nous eûmes eu

vous eûtes eu

ils eurent eu

Subjonctif

Présent

que j’aie

que tu aies

qu’il ait

que nous ayons

que vous ayez

qu’ils aient

Passé

que j’aie eu

que tu aies eu

qu’il ait eu

que nous ayons eu

que vous ayez eu

qu’ils aient eu

Imparfait

que j’eusse

que tu eusses

qu’il eût

que nous eussions

que vous eussiez

qu’ils eussent

Plus-que-parfait

que j’eusse eu

que tu eusses eu

qu’il eût eu

que nous eussions eu

que vous eussiez eu

qu’ils eussent eu

Conditionnel

Présent

j’aurais

tu aurais

il aurait

nous aurions

vous auriez

ils auraient

Passé 1ère Forme

j’aurais eu

tu aurais eu

il aurait eu

nous aurions eu

vous auriez eu

ils auraient eu

Passé 2e Forme

j’eusse eu

tu eusses eu

il eût eu

nous eussions eu

vous eussiez eu

ils eussent eu

Impératif

Présent

aie

ayons

ayez

Passé

aie eu

ayons eu

ayez eu

Participe

Présent

ayant

Passé

eu

eue

eus

eues

Participe passé surcomposé

ayant eu

Infinitif

Présent

avoir

Passé

avoir eu

Gérondif

Présent

en ayant

Passé

en ayant eu

avoir

3e groupe

Transitif direct

conjugué avec l’auxiliaire avoir


Interruptor Intel·ligent Compatible amb Alexa, Google Home, Interruptor WiFi amb Control de Veu, Control Remot i Funció de Temps, TEVA App i Smart Life

Sobre aquest producte Tensió de funcionament: AC 90-240V, 50/60Hz.

Wi-Fi 2.4GHz.

Capacitat Màxima de Cablejat: 10mm² al costat d’alimentació (Power) i al costat de càrrega (Load). MÒDUL DIY PER A LA LLAR UNIVERSAL CONNECTAT: Amb l’interruptor intel·ligent SY1, pots convertir els petits electrodomèstics de casa teva de dispositius tradicionals a intel·ligents en menys de 10 minuts. Amb aquest interruptor WiFi compacte, podeu convertir un llum, un ventilador o un calefactor en un objecte connectat. APP CONTROL REMOT: Podeu controlar els vostres electrodomèstics a través de l’APP “Smart Life” o “TEUA”. No hi ha cap limitació de distància i temps. L’APP Smart Life es pot descarregar des d’App Store i Google Play.

CONTROL DEL CONSUM D’ENERGIA: Analitza el consum d’energia en temps real i històric dels dispositius connectats, vista en temps real del corrent de càrrega, tensió i potència, registre (hores, dies, mesos i anys). INTERRUPTOR WIFI AMB CONTROL PER VEU: L’interruptor WiFi connectat és compatible amb la funció de control per veu d’Amazon Alexa, Google Assistant. Per poder engegar o apagar el dispositiu amb una ordre de veu. Amb l’interruptor SY1, pots alliberar les mans.

4 MODES DE TEMPS: L’interruptor intel·ligent disposa de mode de temps/ mode de compte enrere/ temps de cicle/ astre temporitzador. L’interruptor universal connectat evita que us oblideu d’apagar els electrodomèstics. Ajusteu el temps de funcionament dels aparells segons les vostres necessitats per evitar pèrdues innecessàries d’energia i aconseguir un estalvi energètic. FÀCIL D’INSTAL·LAR I AMPLIAMENT APLICABLE: Podeu connectar l’interruptor intel·ligent al dispositiu en menys de deu minuts. Només cal pressionar i inserir el cable per completar el cablejat. Els cargols es poden prémer i afluixar fàcilment amb un tornavís. MATERIALS D´ALTA QUALITAT: L´interruptor intel·ligent està fet de materials d´alta qualitat, el coure té una bona conductivitat elèctrica i el material PA66 és resistent al foc, que és resistent al´alta temperatura i millora efectivament la seguretat de l´ús de l´interruptor.

Activar mut el lector de microsoft Edge en pàgina web (Ctrl + Shift + U)



El que veus amb Ctrl + Shift + U (la funció “Llegeix en veu alta” d’Edge) fa servir les veus “Online (Natural)” — com Microsoft Jordi, Enric (Natural), Joana (Natural) — que tenen una qualitat molt superior (són neurals, de tipus Azure Cognitive Services).

Però… 😕 aquestes no estan disponibles per a ús directe amb JavaScript ni amb l’API web speechSynthesis.


Conversor de text a veu

🔊 Conversor de text a veu

🌟🌟 Conversor de text a veu

Caixa Comodí – Text a veu

🔊 Text a veu

to run into somebody.
have a good trip.
to pass on greetings.
there’s a restroom in the café.
📌 Selecciona un idioma i prem “🔊” per veure quina veu s’utilitza.

——————————

<!DOCTYPE html>
<html lang="ca">
<head>
  <meta charset="UTF-8">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <title>Caixa Comodí - Text a veu</title>
  <link rel="icon" href="calculadora.ico" type="image/x-icon">
  <style>
    body {
      font-family: Arial, sans-serif;
      margin: 0;
      padding: 0;
      display: flex;
      justify-content: center;
      align-items: flex-start;
      background-color: #f0f0f0;
      height: 100vh;
    }

    .container {
      background-color: rgb(213, 225, 225);
      padding: 20px;
      border-radius: 10px;
      box-shadow: 0 0 10px rgba(0, 0, 0, 0.1);
      max-width: 440px;
      width: 100%;
      height: 60%;
      margin-top: 30px;
      box-sizing: border-box;
      display: flex;
      flex-direction: column;
      overflow: hidden;
    }

    h2 {
      text-align: center;
      color: #333;
      margin: 0 0 15px 0;
      font-size: 1.4em;
    }

    #editor {
      font-size: 1.3em;
      padding: 8px;
      margin: 8px 0;
      width: 100%;
      height: 320px;
      overflow-y: auto;
      border: 1px solid #ccc;
      white-space: pre-wrap;
      background: white;
      border-radius: 5px;
      box-sizing: border-box;
    }

    select {
      font-size: 1em;
      padding: 6px;
      margin: 6px 4px 0 0;
      width: calc(50% - 8px);
      height: 36px;
      border: 1px solid #ccc;
      border-radius: 5px;
      box-sizing: border-box;
    }

    #debugInfo {
      margin: 10px 0;
      padding: 8px;
      background: #fff;
      border-radius: 5px;
      font-size: 0.9em;
      color: #333;
      border: 1px solid #ccc;
    }

    .controls {
      display: flex;
      justify-content: center;
      gap: 16px;
      margin-top: 12px;
    }

    #speakBtn, #toggleBtn {
      font-size: 24px;
      background: #007bff;
      color: white;
      border: none;
      border-radius: 8px;
      width: 50px;
      height: 50px;
      cursor: pointer;
      display: flex;
      align-items: center;
      justify-content: center;
    }

    #speakBtn:hover, #toggleBtn:hover {
      background: #0056b3;
    }

    .linia {
      display: block;
      padding: 0.2em;
      transition: background-color 0.3s ease;
    }

    .activa {
      background-color: hsl(180, 1%, 72%);
    }
  </style>
</head>
<body>
  <div class="container">
    <h2>🔊 Text a veu</h2>

    <div id="editor" contenteditable="true" placeholder="Escriu el text que vols escoltar">
to run into somebody.<br>
have a good trip.<br>
to pass on greetings.<br>
there’s a restroom in the café.
    </div>
    <div>
      <select id="voiceSelect">
        <option value="">Idioma</option>
        <option value="en-US">🇺🇸 Anglès (US)</option>
        <option value="en-GB">🇬🇧 Anglès (UK)</option>
        <option value="fr-FR">🇫🇷 Francès</option>
        <option value="de-DE">🇩🇪 Alemany</option>
        <option value="it-IT">🇮🇹 Italià</option>
        <option value="pt-PT">🇵🇹 Portuguès</option>
        <option value="es-ES">🇪🇸 Espanyol</option>
        <option value="ca-ES">🎗️ Català</option>
      </select>

      <select id="pauseSelect">
        <option value="1">⏱️ Pausa x1</option>
        <option value="2">⏱️ Pausa x2</option>
        <option value="3">⏱️ Pausa x3</option>
        <option value="4">⏱️ Pausa x4</option>
        <option value="10">⏱️ Pausa x10</option>
      </select>
    </div>

    <!-- 🔍 Indicador de diagnòstic -->
    <div id="debugInfo">
      📌 Selecciona un idioma i prem "🔊" per veure quina veu s'utilitza.
    </div>

    <div class="controls">
      <button id="speakBtn" title="Escolta el text">🔊</button>
      <button id="toggleBtn" title="Atura o reprèn">⏹️</button>
    </div>
  </div>

  <script>
    document.addEventListener('DOMContentLoaded', () => {
      const editor = document.getElementById('editor');
      const speakBtn = document.getElementById('speakBtn');
      const toggleBtn = document.getElementById('toggleBtn');
      const voiceSelect = document.getElementById('voiceSelect');
      const pauseSelect = document.getElementById('pauseSelect');
      const debugInfo = document.getElementById('debugInfo');

      let voices = [];
      let isSpeaking = false;
      let liniesGuardades = [];
      let currentIndex = 0;

      function loadVoices() {
        voices = speechSynthesis.getVoices();
        // Opcional: mostra totes les veus disponibles al carregar (per depuració)
        // console.log('Veus disponibles:', voices.map(v => `${v.name} (${v.lang})`));
      }

      speechSynthesis.onvoiceschanged = loadVoices;
      loadVoices();

      const idiomaGuardat = localStorage.getItem('idiomaSeleccionat');
      if (idiomaGuardat) {
        voiceSelect.value = idiomaGuardat;
      }

      voiceSelect.addEventListener('change', () => {
        localStorage.setItem('idiomaSeleccionat', voiceSelect.value);
        // Actualitzem el missatge quan es canvia l'idioma
        debugInfo.textContent = `📌 Idioma seleccionat: ${voiceSelect.options[voiceSelect.selectedIndex].text}`;
      });

      function getLinies() {
        const text = editor.innerText || editor.textContent;
        return text.split('\n').map(l => l.trim()).filter(l => l);
      }

      function marcarLinia(index) {
        const linies = editor.querySelectorAll('.linia');
        linies.forEach((el, i) => {
          el.classList.toggle('activa', i === index);
        });
      }

      function prepararEditor() {
        const linies = getLinies();
        editor.innerHTML = '';
        linies.forEach((text, i) => {
          const span = document.createElement('span');
          span.className = 'linia';
          span.textContent = text;
          editor.appendChild(span);
          editor.appendChild(document.createElement('br'));
        });
      }

      function getPausaEntreLinies() {
        const factor = parseInt(pauseSelect.value || '1');
        return 500 * factor;
      }

      // 🔍 Funció per trobar la millor veu i mostrar informació
      function getBestVoiceAndReport(langCode) {
        if (!langCode) {
          debugInfo.innerHTML = `ℹ️ Cap idioma seleccionat. S'utilitzarà la veu per defecte.`;
          return null;
        }

        // Normalitzem per a comparacions flexibles
        const normalizedTarget = langCode.replace('-', '_').toLowerCase();

        // 1. Cerca exacta (amb normalització)
        let best = voices.find(v => 
          v.lang.replace('-', '_').toLowerCase() === normalizedTarget
        );

        if (best) {
          debugInfo.innerHTML = `✅ Idioma demanat: <strong>${langCode}</strong><br>🗣️ Veus trobada: <strong>${best.name}</strong> (${best.lang})`;
          return best;
        }

        // 2. Cerca per prefix (p. ex., "ca" per a "ca-ES")
        const prefix = langCode.split('-')[0].toLowerCase();
        best = voices.find(v => v.lang.toLowerCase().startsWith(prefix));

        if (best) {
          debugInfo.innerHTML = `⚠️ Idioma demanat: <strong>${langCode}</strong><br>🗣️ Veus aproximada: <strong>${best.name}</strong> (${best.lang})`;
          return best;
        }

        // 3. No s'ha trobat cap veu
        debugInfo.innerHTML = `❌ Idioma demanat: <strong>${langCode}</strong><br>🚫 Cap veu trobada. Comprova que tens l'idioma instal·lat a Android.`;
        return null;
      }

      function speakLinia() {
        if (currentIndex >= liniesGuardades.length) {
          isSpeaking = false;
          setTimeout(() => {
            speakText();
          }, 2000);
          return;
        }

        const linia = liniesGuardades[currentIndex];
        const utterance = new SpeechSynthesisUtterance(linia);

        const selectedLang = voiceSelect.value;
        const voice = getBestVoiceAndReport(selectedLang);
        if (voice) {
          utterance.voice = voice;
        }

        utterance.rate = 1;
        utterance.pitch = 1;

        utterance.onstart = () => {
          isSpeaking = true;
          marcarLinia(currentIndex);
        };

        utterance.onend = () => {
          currentIndex++;
          setTimeout(() => {
            speakLinia();
          }, getPausaEntreLinies());
        };

        speechSynthesis.speak(utterance);
      }

      function speakText() {
        if (isSpeaking) return;
        prepararEditor();
        liniesGuardades = getLinies();
        currentIndex = 0;
        speechSynthesis.cancel();
        speakLinia();
      }

      speakBtn.addEventListener('click', speakText);

      toggleBtn.addEventListener('click', () => {
        if (isSpeaking) {
          speechSynthesis.cancel();
          isSpeaking = false;
        } else {
          speakLinia();
        }
      });
    });
  </script>
</body>
</html>


Simple text to speak


Per afegir aquest codi de sota cal usar el connector Enlighter, afegir un bloc a la entrada amb el mateix nom i descarregat el codi del porta-retalls

<!DOCTYPE html>
<!-- Declara que aquest document és HTML5 -->
<html lang="ca">
<!-- L'idioma principal del contingut és el català -->
<head>
  <meta charset="UTF-8">
  <!-- Assegura la correcta visualització de caràcters especials i emojis -->
  <title>Conversor de text a veu</title>
  <!-- Títol que apareix a la pestanya del navegador -->

  <style>
    /* Estils generals de la pàgina */
    body {
      font-family: sans-serif;        /* Tipus de lletra llegible */
      padding: 2em;                   /* Espai al voltant del contingut */
      background-color: hsl(194, 91%, 91%); /* Fons blau clar suau */
    }

    /* Estil comú per al camp de text i el selector d'idioma */
    input, select {
      font-size: 1.2em;               /* Mida de lletra una mica més gran */
      padding: 0.5em;                 /* Espai interior dins dels camps */
      margin-top: 1em;                /* Separació superior */
      width: 100%;                    /* Ocupen tot l'ample disponible */
      max-width: 500px;               /* Però no més de 500px */
    }

    /* Estil del botó d'altaveu (🔊) */
    #speakBtn {
      font-size: 2em;                 /* Molt gran per facilitar la interacció */
      background: none;               /* Sense fons */
      border: none;                   /* Sense vores */
      cursor: pointer;                /* Cursor en forma de mà en passar-hi */
      margin-top: 1em;                /* Separació respecte als elements anteriors */
    }

    /* Efecte visual quan l'usuari passa el ratolí pel botó */
    #speakBtn:hover {
      color: #c8e3f8;                 /* Canvia a un blau més clar */
    }
  </style>
</head>

<body>
  <!-- Títol visible de la pàgina amb un emoji d'altaveu -->
  <h2>🔊 Conversor de text a veu</h2>

  <!-- Camp on l'usuari escriu el text a sintetitzar -->
  <input type="text" id="cercar" placeholder="Escriu el text que vols escoltar">

  <!-- Selector per triar la veu/idioma desitjat -->
  <select id="voiceSelect">
    <option value="">Selecciona idioma</option>
    <option value="en-US">🇺🇸 Anglès (US)</option>
    <option value="en-GB">🇬🇧 Anglès (UK)</option>
    <option value="fr-FR">🇫🇷 Francès</option>
    <option value="de-DE">🇩🇪 Alemany</option>
    <option value="it-IT">🇮🇹 Italià</option>
    <option value="pt-PT">🇵🇹 Portuguès</option>
    <option value="es-ES">🇪🇸 Espanyol</option>
    <option value="ca-ES">🎗️ Català</option>
    <!-- Els valors (value) són codis d'idioma estàndard BCP 47 -->
  </select>

  <!-- Botó per iniciar la síntesi de veu -->
  <button id="speakBtn" title="Escolta el text">🔊</button>

  <script>
    // S'executa quan tot el contingut HTML ha carregat
    document.addEventListener('DOMContentLoaded', () => {
      // Referències als elements HTML que necessitarem
      const inputElement = document.getElementById('cercar');      // Camp de text
      const speakBtn = document.getElementById('speakBtn');        // Botó d'altaveu
      const voiceSelect = document.getElementById('voiceSelect');  // Selector d'idioma
      let voices = [];  // Array per emmagatzemar les veus disponibles

      // Funció per carregar la llista de veus del sistema
      function loadVoices() {
        voices = speechSynthesis.getVoices();
        // Aquesta API pot trigar a carregar les veus en alguns navegadors
      }

      // Assegurem-nos que les veus es carreguin, fins i tot si arriben més tard
      speechSynthesis.onvoiceschanged = loadVoices;
      loadVoices(); // Intentem carregar-les ja des del principi

      // Funció principal: converteix el text a veu
      function speakText() {
        const text = inputElement.value.trim(); // Obtenim i netegem el text
        if (!text) return; // Si està buit, no fem res

        const selectedLang = voiceSelect.value; // Idioma seleccionat per l'usuari
        const utterance = new SpeechSynthesisUtterance(text); // Creem l'objecte de parla

        // Busquem una veu que coincideixi exactament amb l'idioma triat
        const voice = voices.find(v => v.lang === selectedLang);

        if (voice) {
          // Si la trobem, l'assignem
          utterance.voice = voice;
          utterance.lang = voice.lang;
        } else {
          // Si no, mostrem un avís a la consola (per depuració)
          console.log('No s\'ha trobat cap veu per a ' + selectedLang);
          // Nota: l'API pot usar una veu per defecte si no s'assigna cap
        }

        // Paràmetres opcionals de parla
        utterance.rate = 1;   // Velocitat normal (1 = 100%)
        utterance.pitch = 1;  // To normal

        // Cancel·lem qualsevol parla anterior per evitar solapaments
        speechSynthesis.cancel();
        // Iniciem la nova síntesi de veu
        speechSynthesis.speak(utterance);
      }

      // Quan l'usuari fa clic al botó, es llegeix el text
      speakBtn.addEventListener('click', speakText);

      // ⚠️ Aquesta línia fa que el text es llegeixi AUTOMÀTICAMENT cada 10 segons
      // Pot ser útil per a demostracions, però pot resultar molest en ús normal
      setInterval(speakText, 10000);
    });
  </script>
</body>
</html>

<!DOCTYPE html>
<html lang="ca">
<head>
  <meta charset="UTF-8">
  <title>Conversor de text a veu</title>
  <style>
    body {
      font-family: sans-serif;
      padding: 2em;
      background-color: #f4f4f4;
    }
    input {
      font-size: 1.2em;
      padding: 0.5em;
      margin-top: 1em;
      width: 100%;
      max-width: 500px;
    }
    #speakBtn {
      font-size: 2em;
      background: none;
      border: none;
      cursor: pointer;
      margin-top: 1em;
    }
    #speakBtn:hover {
      color: #0078D7;
    }
  </style>
</head>
<body>
  <h2>🔊 Conversor de text a veu</h2>
  <input type="text" id="cercar" placeholder="Escriu el text que vols escoltar">
  <button id="speakBtn" title="Escolta el text">🔊</button>

  <script>
    document.addEventListener('DOMContentLoaded', () => {
      const inputElement = document.getElementById('cercar');
      const speakBtn = document.getElementById('speakBtn');
      let voices = [];

      function loadVoices() {
        voices = speechSynthesis.getVoices();
      }

      speechSynthesis.onvoiceschanged = loadVoices;
      loadVoices();

      function speakText() {
        const text = inputElement.value.trim();
        if (!text) return;

        const utterance = new SpeechSynthesisUtterance(text);
        const zira = voices.find(v => v.name === 'Microsoft Zira - English (United States)');

        if (zira) {
          utterance.voice = zira;
          utterance.lang = zira.lang;
        }

        utterance.rate = 1;
        utterance.pitch = 1;

        speechSynthesis.cancel();
        speechSynthesis.speak(utterance);
      }

      speakBtn.addEventListener('click', speakText);

      // 🔁 Repetir cada 10 segons
      setInterval(speakText, 10000);
    });
  </script>
</body>
</html>

Nova funció Polidic

Polidic, voldria afegir una funció nova a polidic: afegir un botó nou a continuació de l’entrada ‘cercar’ i el botó cercar/confirmar, aquest botó conte un altaveu com icona, de forma que al pemèr-lo converteix el text de l’entrada en àudio (veu anglesa). És complicat?

No, no és gaire complicat! Afegir un botó amb un icona d’altaveu que llegeixi en veu alta (text-to-speech, TTS) el contingut de l’entrada de cerca en anglès és una funcionalitat bastant estàndard en navegadors moderns, gràcies a l’API Web Speech API, concretament la part de SpeechSynthesis.

Aquí tens una guia senzilla per implementar-ho a Polidic:


✅ Passos per afegir el botó de lectura en veu alta

1. Afegir el botó al HTML

Suposant que tens una entrada de text amb id searchInput i un botó de cerca, afegeix un botó nou al costat:

<input type="text" id="searchInput" placeholder="Cerca...">
<button id="searchButton">Cercar</button>
<button id="speakButton" title="Llegir en veu alta">
  <span>🔊</span> <!-- o usa un ícona SVG o Font Awesome -->
</button>

💡 Si vols un ícona més professional, pots fer servir una llibreria com Font Awesome (<i class="fas fa-volume-up"></i>) o un SVG.


2. Afegir el JavaScript per fer la lectura

document.getElementById('speakButton').addEventListener('click', () => {
  const text = document.getElementById('searchInput').value.trim();
  if (!text) return; // No diu res si està buit

  // Cancel·la qualsevol parla anterior
  speechSynthesis.cancel();

  const utterance = new SpeechSynthesisUtterance(text);
  utterance.lang = 'en-US'; // Veu en anglès (USA)
  utterance.rate = 1;       // Velocitat normal
  utterance.pitch = 1;      // To normal

  // Opcional: escull una veu específica en anglès si vols
  // speechSynthesis.getVoices() es carrega asíncronament, així que cal esperar
  utterance.addEventListener('start', () => {
    // Opcional: canviar l’estat del botó (ex: desactivar temporalment)
  });

  speechSynthesis.speak(utterance);
});

⚠️ Nota important: speechSynthesis.getVoices() pot trigar a carregar. Si vols triar una veu concreta (per exemple, “Google US English”), cal esperar almenys un esdeveniment voiceschanged:

let voicesLoaded = false;
speechSynthesis.addEventListener('voiceschanged', () => {
  voicesLoaded = true;
});

// I dins del botó:
if (voicesLoaded) {
  const voices = speechSynthesis.getVoices();
  const englishVoice = voices.find(voice => voice.lang === 'en-US');
  if (englishVoice) utterance.voice = englishVoice;
}

Però no és obligatori: si només poses utterance.lang = 'en-US', el navegador triarà automàticament una veu en anglès disponible.


3. Estils (opcional)

Per fer que el botó quedi bé:

#speakButton {
  background: none;
  border: none;
  font-size: 1.2em;
  cursor: pointer;
  padding: 0 8px;
  color: #333;
}
#speakButton:hover {
  color: #007bff;
}

✅ Comprovacions finals

  • Funciona en Chrome, Edge, Firefox (Safari també, però amb menys veus).
  • No requereix connexió externa: és nativa del navegador.
  • Respecta la privacitat: el text no surt del navegador.

🧪 Prova ràpida

Obre la consola del navegador i prova això:

const u = new SpeechSynthesisUtterance("Hello, this is a test.");
u.lang = "en-US";
speechSynthesis.speak(u);

Si ho llegeix en anglès, ja tens el suport actiu!


Vols que t’ajudi a integrar-ho directament al codi actual de Polidic? Si em passes un tros del HTML/JS on està la barra de cerca, et puc donar el codi exacte per enganxar.

Fet:

Llistat de punts a solucionar o millorar (15-12-2025)

stud/Index:

1 Agenda visual. Algunes preguntes es mostren sense imatge treballant amb Agenda visual

2 Implementar Preguntes a respostes (Preg <> Resp)

En una primera fase l’enllas Preg <> Resp està en color verd que és la posició per defecte. Pregunta el camp2 (‘castellà) i s’ha de respondre el camp1 (‘català). Si es prem ha de canviar a color vermell, on inverteix el mode a camp1-> camp2

3 Si estem a Stud (estad ‘jugant’) menús d’idiomes, diccionaris, cerques -> bloquejats (no es despleguen)

Per fer una línia recta horitzontal

Per fer una línia recta horitzontal a Photoshop, tens diverses opcions segons el tipus de línia que vulguis (forma vectorial, píxel, o traç amb pinzell). Aquí tens les dues més comunes:


🟦 Opció 1: Amb la eina Línia

  1. Selecciona la eina Línia des de la barra d’eines (pot estar agrupada amb la forma rectangle).
  2. A la barra superior, tria el mode “Forma” si vols una línia editable.
  3. Estableix el gruix (per exemple, 3 px).
  4. Fes clic al punt d’inici, mantén premuda la tecla Majúscules (Shift) i arrossega cap a la dreta per assegurar que sigui recta.
  5. Deixa anar el clic: ja tens la línia!

🖌️ Opció 2: Amb la eina Pincell

  1. Selecciona la eina Pincell i tria el gruix desitjat. (5px)
  2. Fes clic al punt d’inici.
  3. Mantén premuda la tecla Majúscules (Shift) i fes clic al punt final: Photoshop traçarà una línia recta entre els dos punts.

Vols que et generi una guia visual pas a pas amb captures o que t’ajudi a fer-ho amb una acció automatitzada?