简体   繁体   English

Web 语音 API 文本到语音:如何拥有一个适用于多个文本的 JavaScript 代码?

[英]Web Speech API text-to-speech : How to have one JavaScript code that works for several texts to be read?

Is it possible to have a single JavaScript code (with the help of PHP or something else) for all the different texts to be read instead of having a code for each text to be read as in my current code?是否可以使用单个 JavaScript 代码(在 PHP 或其他东西的帮助下)来读取所有不同的文本,而不是像我当前的代码那样为每个要读取的文本设置一个代码? In this example there is only 4 texts to be read but I have one web page that has around 130.在这个例子中,只有 4 个文本要阅读,但我有一个 web 页面,大约有 130 个。

Here is the HTML code in 4 PHP different pages (I use include php to add those buttons where needed):这是 4 个 PHP 不同页面中的 HTML 代码(我使用包括 php 在需要的地方添加这些按钮):

<div class="read"><button id="lectureObjectif">Écoutez</button>&nbsp<button id="pauseObjectif">Pause</button>&nbsp<button id="reprendreObjectif">Reprendre</button>&nbsp<button id="arretObjectif">Arrêtter</button></div>

<div class="read"><button id="lecturePourquoi">Écoutez</button>&nbsp<button id="pausePourquoi">Pause</button>&nbsp<button id="reprendrePourquoi">Reprendre</button>&nbsp<button id="arretPourquoi">Arrêtter</button></div>

<div class="read"><button id="lectureNouvelles">Écoutez</button>&nbsp<button id="pauseNouvelles">Pause</button>&nbsp<button id="reprendreNouvelles">Reprendre</button>&nbsp<button id="arretNouvelles">Arrêtter</button></div>

<div class="read"><button id="lectureDissonance">Écoutez</button>&nbsp<button id="pauseDissonance">Pause</button>&nbsp<button id="reprendreDissonance">Reprendre</button>&nbsp<button id="arretDissonance">Arrêtter</button></div>

Here is the JavasCript code on 1 page (I don't want to use a third party JavaScript).这是一页上的 JavasCript 代码(我不想使用第三方 JavaScript)。 I am novice in programming and very novice in JavaScript.我是编程新手,在 JavaScript 中非常新手。

    //////////////////////////////// Obectif /////////////////////////////////////////  
    // pointer vers nos éléments
    let btnLectureObjectif = document.getElementById("lectureObjectif");
    let btnPauseObjectif = document.getElementById("pauseObjectif");
    let btnReprendreObjectif = document.getElementById("reprendreObjectif");
    let btnArretObjectif = document.getElementById("arretObjectif");
    let divObjectif = document.getElementById("objectif");

    btnArretObjectif.onclick = function () {
        speechSynthesis.cancel();
    }
    btnLectureObjectif.onclick = function () {
        speechSynthesis.cancel();
        /*let texte = "Coucou";*/
        let texteObjectif = divObjectif.textContent;
        // instancier un objet d'énonciation
        let parole = new SpeechSynthesisUtterance();
        parole.lang = 'fr-Fr'; // language, default is 'en-US'
        parole.text = texteObjectif;
        parole.pitch = 1; // 0 à 2 = hauteur
        parole.rate = 1.3; // 0.1 à 10 = vitesse
        parole.volume = 1; // 0 à 1 = volume
        // fair parler
        speechSynthesis.speak(parole);
    }
    btnPauseObjectif.onclick = function () {
        let texteObjectif = divObjectif.textContent;
        // instancier un objet d'énonciation
        let parole = new SpeechSynthesisUtterance();
        parole.text = texteObjectif;
        // fair une pause
        speechSynthesis.pause(parole);
    }
    btnReprendreObjectif.onclick = function () {
        let texteObjectif = divObjectif.textContent;
        // instancier un objet d'énonciation
        let parole = new SpeechSynthesisUtterance();
        parole.text = texteObjectif;
        // reprendre la lecture
        speechSynthesis.resume(parole);
    }

    ////////////////////////////// Pourquoi ///////////////////////////////////////////     
    // pointer vers nos éléments
    let btnLecturePourquoi = document.getElementById("lecturePourquoi");
    let btnPausePourquoi = document.getElementById("pausePourquoi");
    let btnReprendrePourquoi = document.getElementById("reprendrePourquoi");
    let btnArretPourquoi = document.getElementById("arretPourquoi");
    let divPourquoi = document.getElementById("pourquoi");

    btnArretPourquoi.onclick = function () {
        speechSynthesis.cancel();
    }
    btnLecturePourquoi.onclick = function () {
        speechSynthesis.cancel();
        /*let texte = "Coucou";*/
        let textePourquoi = divPourquoi.textContent;
        // instancier un objet d'énonciation
        let parole = new SpeechSynthesisUtterance();
        parole.text = textePourquoi;
        parole.pitch = 1; // 0 à 2 = hauteur
        parole.rate = 1; // 0.5 à 2 = vitesse
        parole.volume = 1; // 0 à 1 = volume
        // fair parler
        speechSynthesis.speak(parole);
    }
    btnPausePourquoi.onclick = function () {
        let textePourquoi = divPourquoi.textContent;
        // instancier un objet d'énonciation
        let parole = new SpeechSynthesisUtterance();
        parole.text = textePourquoi;
        // fair une pause
        speechSynthesis.pause(parole);
    }
    btnReprendrePourquoi.onclick = function () {
        let textePourquoi = divPourquoi.textContent;
        // instancier un objet d'énonciation
        let parole = new SpeechSynthesisUtterance();
        parole.text = textePourquoi;
        // reprendre la lecture
        speechSynthesis.resume(parole);
    }

    //////////////////////////////// Nouvelles /////////////////////////////////////////        
    // pointer vers nos éléments
    let btnLectureNouvelles = document.getElementById("lectureNouvelles");
    let btnPauseNouvelles = document.getElementById("pauseNouvelles");
    let btnReprendreNouvelles = document.getElementById("reprendreNouvelles");
    let btnArretNouvelles = document.getElementById("arretNouvelles");
    let divNouvelles = document.getElementById("nouvelles");

    btnArretNouvelles.onclick = function () {
        speechSynthesis.cancel();
    }
    btnLectureNouvelles.onclick = function () {
        speechSynthesis.cancel();
        /*let texte = "Coucou";*/
        let texteNouvelles = divNouvelles.textContent;
        // instancier un objet d'énonciation
        let parole = new SpeechSynthesisUtterance();
        parole.text = texteNouvelles;
        parole.pitch = 1; // 0 à 2 = hauteur
        parole.rate = 1; // 0.5 à 2 = vitesse
        parole.volume = 1; // 0 à 1 = volume
        // fair parler
        speechSynthesis.speak(parole);
    }
    btnPauseNouvelles.onclick = function () {
        let texteNouvelles = divNouvelles.textContent;
        // instancier un objet d'énonciation
        let parole = new SpeechSynthesisUtterance();
        parole.text = texteNouvelles;
        // fair une pause
        speechSynthesis.pause(parole);
    }
    btnReprendreNouvelles.onclick = function () {
            let texteNouvelles = divNouvelles.textContent;
            // instancier un objet d'énonciation
            let parole = new SpeechSynthesisUtterance();
            parole.text = texteNouvelles;
            // reprendre la lecture
            speechSynthesis.resume(parole);
        }
        ////////////////////////// Dissonance ////////////////////////////////
        // pointer vers nos éléments
    let btnLectureDissonance = document.getElementById("lectureDissonance");
    let btnPauseDissonance = document.getElementById("pauseDissonance");
    let btnReprendreDissonance = document.getElementById("reprendreDissonance");
    let btnArretDissonance = document.getElementById("arretDissonance");
    let divDissonance = document.getElementById("dissonance");

    btnArretDissonance.onclick = function () {
        speechSynthesis.cancel();
    }
    btnLectureDissonance.onclick = function () {
        speechSynthesis.cancel();
        /*let texte = "Coucou";*/
        let texteDissonance = divDissonance.textContent;
        // instancier un objet d'énonciation
        let parole = new SpeechSynthesisUtterance();
        parole.text = texteDissonance;
        parole.pitch = 1; // 0 à 2 = hauteur
        parole.rate = 1; // 0.5 à 2 = vitesse
        parole.volume = 1; // 0 à 1 = volume
        // fair parler
        speechSynthesis.speak(parole);
    }
    btnPauseDissonance.onclick = function () {
        let texteDissonance = divDissonance.textContent;
        // instancier un objet d'énonciation
        let parole = new SpeechSynthesisUtterance();
        parole.text = texteDissonance;
        // fair une pause
        speechSynthesis.pause(parole);
    }
    btnReprendreDissonance.onclick = function () {
        let texteDissonance = divDissonance.textContent;
        // instancier un objet d'énonciation
        let parole = new SpeechSynthesisUtterance();
        parole.text = texteDissonance;
        // reprendre la lecture
        speechSynthesis.resume(parole);
    }

Yes it's possible: By serious re-factoring your explicit code.是的,这是可能的:通过认真重构您的显式代码。 Basically, you need to abstract , ie.基本上,你需要抽象,即。 generate the variations based on the common patterns you've identified.根据您确定的常见模式生成变体。 I won't write all that code for you, however here's a walk-through with a generous serving of examples.我不会为您编写所有代码,但是这里有一个包含大量示例的演练。

First, let's take the code apart;首先,让我们把代码拆开; looking at just one of many repetitions.只看许多重复中的一个。 Below, we're sampling the necessary code for a single text, with the text name replaced with a {{ TEXTNAME }} placeholder to help you see what all is being duplicated.下面,我们对单个文本的必要代码进行抽样,将文本名称替换为{{ TEXTNAME }}占位符,以帮助您查看所有重复的内容。 For each text, you have HTML buttons as follows:对于每个文本,您都有 HTML 按钮,如下所示:

<button id="lecture{{ TEXTNAME }}">Écoutez</button>
<button id="pause{{ TEXTNAME }}">Pause</button>
<button id="reprendre{{ TEXTNAME }}">Reprendre</button>
<button id="arret{{ TEXTNAME }}">Arrêtter</button>

Then, you have JavaScript as follows.然后,您有 JavaScript 如下。

/* You don't really need the following five "let"s. 
   Get the relevant DOM objects inside the functions. */

let btnLecturet{{ TEXTNAME }} = document.getElementById("lecture{{ TEXTNAME }}");
let btnPause{{ TEXTNAME }} = document.getElementById("pause{{ TEXTNAME }}");
let btnReprendre{{ TEXTNAME }} = document.getElementById("reprendre{{ TEXTNAME }}");
let btnArret{{ TEXTNAME }} = document.getElementById("arret{{ TEXTNAME }}");
let div{{ TEXTNAME }} = document.getElementById("{{ TEXTNAME }}");

/* Here we have four *explicit* functions that are 
   unnecessarily repeated for each event handler definition: */

btnArret{{ TEXTNAME }}.onclick = function () {
    speechSynthesis.cancel();
}
btnLecture{{ TEXTNAME }}.onclick = function () {
    speechSynthesis.cancel();
    /*let texte = "Coucou";*/
    let texte{{ TEXTNAME }} = div{{ TEXTNAME }}.textContent;
    // instancier un objet d'énonciation
    let parole = new SpeechSynthesisUtterance();
    parole.lang = 'fr-Fr'; // language, default is 'en-US'
    parole.text = texte{{ TEXTNAME }};
    parole.pitch = 1; // 0 à 2 = hauteur
    parole.rate = 1.3; // 0.1 à 10 = vitesse
    parole.volume = 1; // 0 à 1 = volume
    // fair parler
    speechSynthesis.speak(parole);
}
btnPause{{ TEXTNAME }}.onclick = function () {
    let texte{{ TEXTNAME }} = div{{ TEXTNAME }}.textContent;
    // instancier un objet d'énonciation
    let parole = new SpeechSynthesisUtterance();
    parole.text = texte{{ TEXTNAME }};
    // fair une pause
    speechSynthesis.pause(parole);
}
btnReprendre{{ TEXTNAME }}.onclick = function () {
    let texte{{ TEXTNAME }} = div{{ TEXTNAME }}.textContent;
    // instancier un objet d'énonciation
    let parole = new SpeechSynthesisUtterance();
    parole.text = texte{{ TEXTNAME }};
    // reprendre la lecture
    speechSynthesis.resume(parole);
}

You will notice that the Javascript functions above contain unnecessary explicit information ("TEXTNAME").您会注意到上面的 Javascript 函数包含不必要的显式信息(“TEXTNAME”)。 This makes them non-reusable.这使得它们不可重复使用。 It'd be fine to do that if you had one or two fixed implementations only;如果您只有一两个固定的实现,那么这样做会很好; but you have lots, and you want to update things easily.但是你有很多,你想轻松地更新东西。

Now, the cool thing about functions: they can take arguments that qualify their action or return value, allowing you to re-use the same code for any number of variant cases.现在,关于函数的一个很酷的事情是:它们可以采用 arguments 来限定它们的操作或返回值,从而允许您对任意数量的变体情况重用相同的代码。 Suppose you did the following instead (for an example, you'd do a similar "generalization" for the remaining functions):假设您改为执行以下操作(例如,您将对其余函数进行类似的“概括”):

function doPause(textName) {
    // instancier un objet d'énonciation
    let parole = new SpeechSynthesisUtterance();
    /* simply get the DOM object right here: */
    parole.text = document.getElementById(textName).textContent;
    // fair une pause
    speechSynthesis.pause(parole);
}

Then, we have a generic pause-action function that takes the text's name/identifier as an argument , which can be applied to any number of cases (example below follows your old code):然后,我们有一个通用的暂停操作 function 将文本的名称/标识符作为参数,它可以应用于任意数量的情况(下面的示例遵循您的旧代码):

btnPauseWHATEVERTEXT.onclick = doPause("WHATEVERTEXT");
btnPauseQUESTCEQUECEST.onclick = doPause("QUESTCEQUECEST");

That's already much more manageable, right?这已经更易于管理了,对吧? You'd only need to declare one set of functions: doArret(textName) , doLecture(textName) , doPause(textName) , and doReprendre(textName) .您只需要声明一组函数: doArret(textName)doLecture(textName)doPause(textName)doReprendre(textName)

Then, all that remains is spelling out the buttons and the event handlers.然后,剩下的就是拼出按钮和事件处理程序。 Now, switching to PHP.现在,切换到 PHP。 Suppose you had the following function:假设您有以下 function:

function make_buttons($textname) {
    $buttons = [];
    $buttons[] = '<button id="lecture' . $textname . '">Écoutez</button>';
    $buttons[] = '<button id="pause' . $textname . '">Pause</button>';
    $buttons[] = '<button id="reprendre' . $textname . '">Écoutez</button>';
    $buttons[] = '<button id="arret' . $textname . '">Arrêtter</button>';
    return implode("&nbsp;", $buttons);
}

You'd have your little "button factory" right there.你的小“按钮工厂”就在那里。 And then you could have another generic function that deals with making button event handler sets:然后你可以有另一个通用的 function 来处理按钮事件处理程序集:

function make_events($textname) {
    $clicks = [];
    $clicks[] = "document.getElementById('lecture{$textname}').onclick = doLecture('{$textname}');";
    $clicks[] = "document.getElementById('pause{$textname}').onclick = doPause('{$textname}');";
    $clicks[] = "document.getElementById('reprendre{$textname}').onclick = doReprendre('{$textname}');";
    $clicks[] = "document.getElementById('arret{$textname}').onclick = doArret('{$textname}');";
    return implode("\n", $clicks);
}

This would give you the JS code for creating the on-clicks for a given text.这将为您提供用于为给定文本创建点击的 JS 代码。 Now, all you need to do is put it all together, with something like this (again with PHP):现在,你需要做的就是把它们放在一起,像这样(再次使用 PHP):

$texts = ['Objectif', 'Subjectif', 'Reflectif', 'Asterix', 'Obelix'];

$buttons = [];
$events = [];

foreach($texts as $text) {
    $buttons[$text] = make_buttons($text);
    $events[$text] = make_events($text);
}

// If you want to flatten the $buttons array into a string,
// do this; and put $buttons to wherever all the buttons go
$buttons = implode("\n", $buttons); 

// or otherwise, you can get a particular text's buttons like this:
echo "<div>Voici les buttons pour text Reflectif: {$buttons['Reflectif']}</div>";

// and put the events where your JS is, after the generic "doStuff()" functions
$events = implode("\n", $events);

With the above measures, you can spare yourself from a lot of unnecessary repetition.通过以上措施,您可以避免很多不必要的重复。 Let's recap:让我们回顾一下:

  1. Clean up your explicit JS functions into generic functions (with an argument) that can be assigned to onclick-events;将您的显式 JS 函数清理为可以分配给 onclick 事件的通用函数(带有参数);
  2. Create PHP functions that generate the buttons and the event handlers.创建生成按钮和事件处理程序的 PHP 函数。
  3. Loop through your text names for a given page using these functions;使用这些函数遍历给定页面的文本名称; and put the HTML and the JS where they belong.并将 HTML 和 JS 放在它们所属的位置。
  4. Spend more time pondering and learning how you can abstract and reuse your code.花更多时间思考和学习如何抽象重用代码。

There are certainly other ways of handling this.当然还有其他方法可以处理这个问题。 You could generate more with JS only at client-end, for example.例如,您只能在客户端使用 JS 生成更多内容。 Since you're just getting started with programming, this is more of a simple and educational refactoring;由于您刚刚开始编程,因此这更像是一种简单且具有教育意义的重构; not the final word in slick and optimized;不是光滑和优化的最终决定; but it should make your life a fair bit easier.但它应该让你的生活更轻松一些。 Happy homeworks, let us know how your code evolves!快乐的作业,让我们知道你的代码是如何演变的! =(^o^)=

Here is where I'm at: Things are starting to take shape but the reading is no happening.这就是我所处的位置:事情开始成形,但阅读没有发生。

I just use, for this exercise, one PHP file:对于这个练习,我只使用一个 PHP 文件:

<body>
<?php 
    
    //  "id"s  of the "div"s to be spoken
$texts = ['Objectif', 'Pourquoi'];
    
    
$buttons = [];
$events = [];

foreach($texts as $text) {
    $buttons[$text] = make_buttons($text);
    $events[$text] = make_events($text);
}
    
    function make_buttons($textname) {
    $buttons = [];
    $buttons[] = '<button id="lecture' . $textname . '">Écouter</button>';
    $buttons[] = '<button id="pause' . $textname . '">Pause</button>';
    $buttons[] = '<button id="reprendre' . $textname . '">Reprendre</button>';
    $buttons[] = '<button id="arret' . $textname . '">Arrêtter</button>';
    return implode("&nbsp;", $buttons);
    
}
    function make_events($textname) {
    $clicks = [];
    $clicks[] = "document.getElementById('lecture{$textname}').onclick = doLecture('{$textname}');";
    $clicks[] = "document.getElementById('pause{$textname}').onclick = doPause('{$textname}');";
    $clicks[] = "document.getElementById('reprendre{$textname}').onclick = doReprendre('{$textname}');";
    $clicks[] = "document.getElementById('arret{$textname}').onclick = doArret('{$textname}');";
    return implode("\n", $clicks);
}   
        
    ?>
    
    <?php   // Show buttons for the div with the id Objectif to be spoken
    echo "<div>{$buttons['Objectif']}</div>";?>

    <!-- The div (with the Objectif id) to be spoken -->
    <div id="Objectif" class="moi-wrap-text">
        <p>L'objectif de ce site est important. </p>
    </div>

    <?php   // Show buttons for the div with the id Pourquoi to be spoken
    echo "<div>{$buttons['Pourquoi']}</div>";?>

    <!-- The div (with the Pourquoi id) to be spoken -->
    <div id="Pourquoi" class="moi-wrap-text">
        <p>Pourquoi est-il important de savoir?</p>
    </div>

    <!-- External JavaScript file -->
    <script src="scrypte.js" defer></script>
</body>

And here is my JavaScript file这是我的 JavaScript 文件

// Function for Speak
function doLecture(textName) {
    /* Removes all utterances from the utterance queue and
    if an utterance is currently being spoken, speaking will stop */
    speechSynthesis.cancel();
    // instancier un objet d'énonciation
    let parole = new SpeechSynthesisUtterance();
    parole.lang = 'fr-Fr'; // language, default is 'en-US'
    parole.pitch = 1; // 0 à 2 = hauteur
    parole.rate = 1.3; // 0.1 à 10 = vitesse
    parole.volume = 1; // 0 à 1 = volume
    // Get the DOM object
    parole.text = document.getElementById(textName).textContent;
    // Speak
    speechSynthesis.speak(parole);
}

// Function for Pause
function doPause(textName) {
    // instancier un objet d'énonciation
    let parole = new SpeechSynthesisUtterance();
    // Get the DOM object
    parole.text = document.getElementById(textName).textContent;
    // Pause speaking
    speechSynthesis.pause(parole);
}

// Function for Resume
function doReprendre(textName) {
    // instancier un objet d'énonciation
    let parole = new SpeechSynthesisUtterance();
    // Get the DOM object
    parole.text = document.getElementById(textName).textContent;
    // Resume speaking
    speechSynthesis.resume(parole);
}

// Function for Stop
function doArret(textName) {
    // instancier un objet d'énonciation
    let parole = new SpeechSynthesisUtterance();
    // Get the DOM object
    parole.text = document.getElementById(textName).textContent;
    // Stop speaking
    speechSynthesis.stop(parole);
}

$events = implode("\n", $events);

I finally succeeded to make it worked (except for my mobile phone browsers).我终于成功让它工作了(除了我的手机浏览器)。

I had to replace this code:我不得不替换这段代码:

    function make_events($textname) {
    $clicks = [];
    $clicks[] = "document.getElementById('lecture{$textname}').onclick = doLecture('{$textname}');";
    $clicks[] = "document.getElementById('pause{$textname}').onclick = doPause('{$textname}');";
    $clicks[] = "document.getElementById('reprendre{$textname}').onclick = doReprendre('{$textname}');";
    $clicks[] = "document.getElementById('arret{$textname}').onclick = doArret('{$textname}');";
    return implode("\n", $clicks);
} 

By this code:通过此代码:

function make_events( $textname ) {
    $clicks = [];
    $clicks[] = "document.getElementById('lecture{$textname}').onclick = function(){doLecture('{$textname}');};";
    $clicks[] = "document.getElementById('pause{$textname}').onclick = function(){doPause('{$textname}');};";
    $clicks[] = "document.getElementById('reprendre{$textname}').onclick = function(){doReprendre('{$textname}');};";
    $clicks[] = "document.getElementById('arret{$textname}').onclick = function(){doArret('{$textname}');};";
    return implode( "\n", $clicks );
}

Thanks, again, Markus AO for your help.再次感谢 Markus AO 的帮助。

But, again, this doesn't work (or work properly) in my mobile phone browsers.但是,同样,这在我的手机浏览器中不起作用(或正常工作)。 In some browser I can make speak, for instance, the first text and than stop it, but the other text are not playable.例如,在某些浏览器中,我可以说出第一个文本然后停止它,但其他文本不可播放。 For all browsers the Pause and Resume don't work at all.对于所有浏览器,暂停和恢复根本不起作用。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM