Re: re text to speech

トップ ページ

このメッセージに返信
著者: Patrice Karatchentzeff
日付:  
To: Yves Gufflet
CC: guilde
題目: Re: re text to speech
Merci Gilles. Tu peux attacher un fichier, ça fonctionne sur la GUILDE.

Ton truc fonctionne sous FF, mais pas sous Chromium chez moi.

C'est un tout petit trop léger pour moi : la voix est vraiment limite
audible/compréhensible.

Merci quand même :)

PK

Le lun. 20 nov. 2023 à 12:48, Yves Gufflet <yves.gufflet@???> a écrit :
>
> Bonjour,
>
> Le fichier joint répond à la demande (j'ai du mal à expédier le fichier
> en html non supporté par la liste, il faut recopier le texte et le
> mettre dans un fichier html)
>
> Il s'agit d'un simple fichier que l'on peut ouvrir avec son navigateur
> et sans besoin d'un serveur web.
>
> Il utilise la fonctionnalité SpeechSynthetizer du navigateur.
>
> Cette fonctionnalité est expérimentale et certaines choses bugs en
> fonction du navigateur : ici le curseur ne suit pas le texte lu et la
> pause et le résume ne marche pas.
>
> Les voix sous chrome sont naturelles. Sous FF elles sont très robotisés.
>
> Yves
>
> <!DOCTYPE html>
> <html lang="fr-FR">
>    <head>
>      <meta charset="UTF-8" />
>      <meta name="viewport" content="width=device-width,
> initial-scale=1.0" />
>      <title>Text to Speech</title>
>      <style>

>
> html,
> body
> {
>         width : 100%;
>         height : 100%;
>         margin : 0px;
>         padding : 0px;
> }

>
> #texttospeak,
> #textbeingspoken
> {
>         margin:0px;
>         width : 50%;
>         height : 50%;
> }

>
> #controllers
> {
>         position:absolute;
>         top:0px;
>         right:0px;
>         width : 50%;
>         height : 100%;
>         display:flex;
>         flex-direction:column;
>         row-gap:20px;
>         align-items : center;
>         padding : 20px;
> }

>
> #controllers > *
> {
>         display:flex;
> }

>
> .speecharg label
> {
>         margin-right:10px;
>         font-weight:bold;
>         width : 100px;
>         text-align:right;
> }

>
> .speecharg input,
> .speecharg select
> {
>         width : 200px;
> }

>
> #start
> {
>         margin:10px;
>         font-weight:bold;
> }

>
> #start.started
> {
>         background: red;
> }

>
> #marker
> {
>         position:absolute;
>         top:0px;
>         left:0px;
>         z-index:10;
>         width:10px;
>         height:10px;
>         background:black;
> }

>
>      </style>

>
>      <script>

>
> var texttospeak;
> var textbeingspoken;
> var marker;
> var range;
> var firstBoundary;
> var voices = [];
> var utterance;
>
> function populateVoiceList()
> {
>         voices = window.speechSynthesis.getVoices();
>         var selectElm = document.querySelector('#voice');
>         selectElm.innerHTML = '';

>
>         voices.sort ((a, b) => { return a.name > b.name; })

>
>         var selected = false;

>
>         for (var i=0;i < voices.length;i++)
>         {
>                 var option = document.createElement('option');
>                 option.innerHTML = voices[i].name + ' (' + voices[i].lang + ')';
>                 option.setAttribute('value', voices[i].voiceURI);
>                 option.voice = voices[i];
>                 if (!selected && (voices[i].lang == "fr-FR"))
>                 {
>                         selected = true;
>                         option.selected = true;
>                 }
>                 selectElm.appendChild(option);
>         }
> }

>
> function stop()
> {
>         speechSynthesis.cancel();
> }

>
> function pauseresume()
> {
>         if (speechSynthesis.paused)
>                 speechSynthesis.resume();
>         else
>                 speechSynthesis.pause();
> }

>
> function start()
> {
>         firstBoundary = true;

>
>         utterance = new SpeechSynthesisUtterance(texttospeak.value);

>
>         textbeingspoken.textContent = texttospeak.value;

>
>         utterance.voice = voices[document.getElementById('voice').selectedIndex];
>         utterance.volume = document.getElementById('volume').value;
>         utterance.pitch = document.getElementById('pitch').value;
>         var rate = document.getElementById('rate').value;
>         utterance.rate = Math.pow(Math.abs(rate) + 1, rate < 0 ? -1 : 1);

>
>         utterance.addEventListener('start', function ()
>         {
>                 marker.classList.remove('animate');
>                 document.body.classList.add('speaking');
>         });

>
>         utterance.addEventListener('start', handleSpeechEvent);
>         utterance.addEventListener('end', handleSpeechEvent);
>         utterance.addEventListener('error', handleSpeechEvent);
>         utterance.addEventListener('boundary', handleSpeechEvent);
>         utterance.addEventListener('pause', handleSpeechEvent);
>         utterance.addEventListener('resume', handleSpeechEvent);

>
>         speechSynthesis.speak(utterance);
> }

>
> function handleSpeechEvent(e)
> {
>         console.log('Speech Event:', e);

>
>         switch (e.type)
>         {
>                 case 'start':
>                         marker.classList.remove('animate');
>                         document.body.classList.add('speaking');
>                         break;
>                 case 'end':
>                 case 'endEvent':
>                 case 'error':
>                         document.body.classList.remove('speaking');
>                         marker.classList.remove('moved');
>                 break;
>                 case 'boundary':
>                 {
>                         if (e.name != 'word')
>                         break;

>
>                         var substr = speechtext.slice(e.charIndex);
>                         var rex = /\S+/g;
>                         var res = rex.exec(substr);

>
>                         if (!res) return;

>
>                         var startOffset = res.index + e.charIndex;
>                         var endOffset = rex.lastIndex + e.charIndex;

>
>                         range.setStart(textbeingspoken.firstChild, startOffset);
>                         range.setEnd(textbeingspoken.firstChild, endOffset);

>
>                         var rect = range.getBoundingClientRect();
>                         var delta = 0;

>
>                         var parentRect = textbeingspoken.getBoundingClientRect();

>
>                         if (rect.bottom > parentRect.bottom) delta = rect.bottom -
> parentRect.bottom;
>                         if (rect.top < parentRect.top) delta = rect.top - parentRect.top;

>
>                         textbeingspoken.scrollTop += delta;

>
>                         texttospeak.scrollTop = textbeingspoken.scrollTop;

>
>                         marker.style.top = rect.top - delta - 1;
>                         marker.style.left = rect.left - 1;
>                         marker.style.width = rect.width + 1;
>                         marker.style.height = rect.height + 1;
>                         marker.classList.add('moved');

>
>                         if (firstBoundary)
>                         {
>                                 firstBoundary = false;
>                                 marker.classList.add('animate');
>                         }

>
>                         break;
>                 }
>                 default:
>                   break;
>         }
> }

>
> window.onload = () =>
> {
>         texttospeak = document.getElementById('texttospeak');
>         textbeingspoken = document.getElementById('textbeingspoken');
>         marker = document.getElementById('marker');
>         range = document.createRange();

>
>         populateVoiceList();

>
>         if (speechSynthesis.onvoiceschanged !== undefined)
> speechSynthesis.onvoiceschanged = populateVoiceList;
> };

>
>      </script>

>
>         </head>
>         <body>
>                 <textarea id="texttospeak">Pour lire ce texte appuyez sur PLAY.
> Pour mettre en pause et résumer la lecture, cliquez sur PAUSE/RESUME.
> Cette fonctionnalité buggue en fonction des plateformes.
> Pour arrêter la lecture, cliquez sur STOP.
> Vous pouvez modifier les paramètres de lecture en ajustant les paramètres.
> Vous devez arrêter et reprendre la lecture pour qu'ils soient pris en
> compte.</textarea>
>                 <textarea id="textbeingspoken"></textarea>
>                 <div id="marker"></div>
>                 <div id="controllers">
>                         <div class="speecharg">
>                                 <label for="voice">Voice</label><select id="voice"></select>
>                         </div>
>                         <div class="speecharg">
>                                 <label for="pitch">Pitch</label><input id="pitch" type="range"
> value="0.5" min="0" max="1" step="0.05">
>                         </div>
>                         <div class="speecharg">
>                                 <label for="rate">Rate</label><input id="rate" type="range"
> value="0" min="-3" max="3" step="0.25">
>                         </div>
>                         <div class="speecharg">
>                                 <label for="volue">Volume</label><input id="volume" type="range"
> value="1" min="0" max="1" step="0.05">
>                         </div>
>                         <button id="start"type="button"
> onmousedown="start();"><strong>PLAY</strong></button>
>                         <button type="button" aria-label="Pause/Resume" title="Pause/Resume"
> onmousedown="pauseresume();"><strong>RESUME/PAUSE</strong></button>
>                         <button type="button" aria-label="Cancel" title="Cancel"
> onmousedown="stop();"><strong>STOP</strong></button>
>                         <div class="bottom"></div>
>                 </div>
>         </body>
> </html>

>



-- 
      |\      _,,,---,,_           Patrice KARATCHENTZEFF
ZZZzz /,`.-'`'    -.  ;-;;,_   mailto:patrice.karatchentzeff@gmail.com
     |,4-  ) )-,_. ,\ (  `'-'
    '---''(_/--'  `-'\_)