本文由Edwin ReynosoMark Brown进行同行评审。 感谢所有SitePoint的同行评审人员使SitePoint内容达到最佳状态!

Web Speech API是一种JavaScript API,使Web开发人员可以将语音识别和合成功能集成到他们的Web页面中。

这样做有很多原因。 例如,为了增强残疾人(特别是有视力障碍的用户或动手能力有限的用户)的体验,或者允许用户在执行其他任务(例如驾驶)时与Web应用程序进行交互。

如果您从未听说过Web Speech API,或者想快速入门,那么阅读Aurelio De Rosa的文章介绍Web Speech APISpeech Sythesis APITalking Form可能是个好主意。

浏览器支持

浏览器供应商直到最近才开始实现语音识别API语音合成API 。 如您所见,对这些工具的支持还远远不够完善,因此,如果您按照本教程进行操作,请使用适当的浏览器。

此外,语音识别API当前需要Internet连接,因为语音通过导线传递并将结果返回到浏览器。 如果连接使用HTTP,则用户必须允许站点在每个请求上使用其麦克风。 如果连接使用HTTPS,则仅需要一次。

语音识别库

图书馆可以帮助我们管理复杂性,并确保我们保持向前的兼容性。 例如,当另一个浏览器开始支持语音识别API时,我们不必担心添加供应商前缀。

这样的图书馆之一就是Annyang ,它非常容易使用。 告诉我更多



要初始化安阳,我们将其脚本添加到我们的网站:

<script src="//cdnjs.cloudflare.com/ajax/libs/annyang/1.6.0/annyang.min.js"></script>

我们可以像这样检查API是否受支持:

if (annyang) { /*logic */ }

并使用一个对象添加命令,该对象的命令名称为键,而回调为方法。 :

var commands = {
  'show divs': function() {
    $('div').show();
  },
  'show forms': function() {
    $("form").show();
  }
};

最后,我们只需添加它们并使用以下命令开始语音识别:

annyang.addCommands(commands);
annyang.start();



声控音频播放器

在本文中,我们将构建一个语音控制的音频播放器。 我们将同时使用语音合成API(通知用户开始播放哪首歌曲或未识别命令)和语音识别API(将语音命令转换为将触发不同应用逻辑的字符串)。




使用Web Speech API的音频播放器的优点在于,用户将能够浏览其浏览器中的其他页面,或者最小化浏览器并执行其他操作,同时仍然能够在歌曲之间进行切换。 如果播放列表中有很多歌曲,我们甚至可以请求一首特定的歌曲而无需手动搜索(当然,如果我们知道其名称或歌手)。

我们将不依赖第三方库进行语音识别,因为我们希望展示如何使用API而不在项目中添加额外的依赖关系。 语音控制的音频播放器将仅支持支持interimResults属性的浏览器。 最新版本的Chrome应该是一个不错的选择。

与以往一样,您可以在GitHub上找到完整的代码 ,并在CodePen 上找到一个演示

入门-播放列表

让我们从一个静态播放列表开始。 它由一个数组中包含不同歌曲的对象组成。 每首歌曲都是一个新对象,包含文件的路径,歌手的姓名和歌曲的名称:

var data = {
  "songs": [
    {
      "fileName": "https://www.ruse-problem.org/songs/RunningWaters.mp3",
      "singer" : "Jason Shaw",
      "songName" : "Running Waters"
    },
    ...

我们应该能够将新对象添加到songs数组,并将新歌曲自动包含在音频播放器中。

音频播放器

现在我们来看看播放器本身。 这将是一个包含以下内容的对象:

  • 一些设置数据
  • 与UI有关的方法(例如,填充歌曲列表)
  • 与语音API有关的方法(例如,识别和处理命令)
  • 与音频操作有关的方法(例如播放,暂停,停止,上一个,下一个)

设定数据

这是相对简单的。

var audioPlayer = {
  audioData: {
    currentSong: -1,
    songs: []
  },

currentSong属性是指用户当前正在播放的歌曲的索引。 例如,当我们必须播放下一首/上一首歌曲或停止/暂停这首歌时,这很有用。

songs数组包含用户已收听的所有歌曲。 这意味着下一次用户收听同一首歌曲时,我们可以从数组中加载它,而不必下载它。

您可以在此处查看完整的代码

UI方法

UI将由可用命令列表,可用轨迹列表和上下文框组成,以将当前操作和上一个命令通知用户。 我不会详细介绍UI方法,而是提供简要概述。 您可以在此处找到这些方法的代码

加载

这会遍历我们先前声明的播放列表,并将歌曲名称以及艺术家名称附加到可用曲目列表中。

changeCurrentSongEffect

这将指示当前正在播放的歌曲(将其标记为绿色并在其旁边添加一副耳机)以及已播放完毕的歌曲。




播放歌曲

这向用户指示歌曲正在播放或何时结束。 它通过changeStatusCode方法执行此操作,该方法将此信息添加到框中,并通过Speech API将此更改通知用户。

changeStatusCode

如上所述,这更新了上下文框中的状态消息(例如,指示正在播放一首新歌曲),并利用speak方法向用户宣布此更改。

changeLastCommand

一个小助手,用于更新最后一个命令框。

toggleSpinner

隐藏或显示微调器图标的小帮手(向用户指示其语音命令当前正在处理)。

播放器方法

播放器将对您可能期望的行为负责,即:开始,停止和暂停播放,以及在曲目中前后移动。 同样,我不想详细介绍这些方法,而是希望您将其指向我们的GitHub repo

这将检查用户是否已经听过歌曲。 如果不是,它将启动歌曲,否则它将仅调用我们先前在当前缓存的歌曲上讨论过的playSong方法。 这位于audioData.songs并与currentSong索引相对应。

暂停歌曲

取决于第二个参数传递的内容,这会暂停或完全停止(将播放时间返回到歌曲的开头)。 它还会更新状态码,以通知用户歌曲已停止或暂停。

这会根据歌曲的第一个也是唯一的参数来暂停或停止播放歌曲:

上一个

这将检查是否已缓存了上一首歌曲,如果已缓存,则会暂停当前歌曲,递减currentSong并再次播放当前歌曲。 如果新歌曲不在数组中,它将执行相同的操作,但首先从对应于递减的currentSong索引的文件名/路径中加载歌曲。

下一个

如果用户以前听过歌曲,则此方法尝试将其暂停。 如果我们的data对象(即我们的播放列表)中有下一首歌曲,它将加载并播放。 如果没有下一首歌曲,它只会更改状态代码并通知用户他们已经到达了最后一首歌曲。

搜索特定歌曲

这将关键字作为参数,并在播放第一个匹配项之前对歌曲名称和歌手进行线性搜索。

语音API方法

语音API非常容易实现。 实际上,只需两行代码即可使Web应用程序与用户对话:

var utterance = new SpeechSynthesisUtterance('Hello');
window.speechSynthesis.speak(utterance);

我们在这里所做的是创建一个包含我们希望说出的文字的utterance对象。 speechSynthesis接口(可在窗口对象上使用)负责处理此utterance对象并控制所生成语音的回放。




继续并在浏览器中尝试一下。 就这么简单!

说话

我们可以在speak方法中看到这一点,该方法大声读取作为参数传递的消息:

speak: function(text, scope) {
  var message = new SpeechSynthesisUtterance(text.replace("-", " "));
  message.rate = 1;
  window.speechSynthesis.speak(message);
  if (scope) {
    message.onend = function() {
      scope.play();
    }
  }
}

如果有第二个参数( scope ),则在消息播放完毕后,我们在scope (将是Audio对象)上调用play方法。

processCommands

这种方法并不令人兴奋。 它接收命令作为参数,并调用适当的方法对其进行响应。 它检查用户是否要播放带有正则表达式的特定歌曲,否则,它输入switch语句以测试不同的命令。 如果没有一个与收到的命令相对应,它将通知用户该命令未被理解。

您可以在此处找到其代码

捆绑在一起

audioPlayer ,我们已经有了一个代表播放列表的data对象,以及一个代表播放器本身的audioPlayer对象。 现在,我们需要编写一些代码来识别和处理用户输入。 请注意,这仅在webkit浏览器中有效。

让用户与您的应用对话的代码与以前一样简单:

var recognition = new webkitSpeechRecognition();
recognition.onresult = function(event) {
  console.log(event)
}
recognition.start();

这将邀请用户允许页面访问其麦克风。 如果您允许访问,则可以开始交谈,并且在停止时将触发onresult事件,从而使语音捕获的结果可用作JavaScript对象。

参考: HTML5语音识别API

我们可以在我们的应用程序中实现此操作,如下所示:

if (window['webkitSpeechRecognition']) {
  var speechRecognizer = new webkitSpeechRecognition();

  // Recognition will not end when user stops speaking
  speechRecognizer.continuous = true;

  // Process the request while the user is speaking
  speechRecognizer.interimResults = true;

  // Account for accent
  speechRecognizer.lang = "en-US";

  speechRecognizer.onresult = function (evt) { ... }
  speechRecognizer.onend = function () { ... }
  speechRecognizer.start();
} else {
  alert("Your browser does not support the Web Speech API");
}

如您所见,我们测试window对象上是否存在webkitSpeechRecognition 。 如果有,那么我们就走了,否则,我们会通知用户浏览器不支持它。 如果一切顺利,我们将设置几个选项。 在这些lang中,有趣的是lang可以根据您来自何处来改善识别结果。

然后,在使用start方法开始之前,我们为onresultonend事件声明处理程序。

处理结果

至少在当前语音识别的实现和我们的需求的背景下,当语音识别器获得结果时,我们需要做一些事情。 每次有结果时,我们都希望将其保存在一个数组中,并设置超时时间以等待三秒钟,以便浏览器可以收集其他结果。 几秒钟之后,我们要使用收集的结果并以相反的顺序遍历它们(较新的结果更有可能获得准确的结果),并检查识别的笔录是否包含我们可用的命令之一。 如果是这样,我们将执行命令并重新启动语音识别。 我们这样做是因为等待最终结果可能需要一分钟的时间,这使我们的音频播放器似乎反应迟钝且毫无意义,因为单击按钮会更快。

speechRecognizer.onresult = function (evt) {
  audioPlayer.toggleSpinner(true);
  results.push(evt.results);
  if (!timeoutSet) {
    setTimeout(function() {
      timeoutSet = false;
      results.reverse();
      try {
        results.forEach(function (val, i) {
          var el = val[0][0].transcript.toLowerCase();
          if (currentCommands.indexOf(el.split(" ")[0]) !== -1) {
            speechRecognizer.abort();
            audioPlayer.processCommands(el);
            audioPlayer.toggleSpinner();
            results = [];
            throw new BreakLoopException;
          }
          if (i === 0) {
            audioPlayer.processCommands(el);
            speechRecognizer.abort();
            audioPlayer.toggleSpinner();
            results = [];
          }
        });
      }
      catch(e) {return e;}
    }, 3000)
  }
  timeoutSet = true;
}

由于我们没有使用库,因此我们必须编写更多代码来设置语音识别器,遍历每个结果并检查其成绩单是否与给定的关键字匹配。

最后,我们在语音识别结束后立即重新启动:

speechRecognizer.onend = function () {
  speechRecognizer.start();
}

您可以在此处查看此部分完整代码

就是这样。 现在,我们有一个功能齐全且声音控制的音频播放器。 我敦促从Github下载代码并尝试一下,或者查看CodePen演示 。 我还提供了通过HTTPS提供服务的版本

结论

我希望本实用教程对Web Speech API可能带来的影响是健康的介绍。 我认为随着实现的稳定和新功能的添加,我们将看到该API的使用不断增长。 例如,我看到了一个完全由语音控制的未来YouTube,在这里我们可以观看不同用户的视频,播放特定的歌曲并仅通过语音命令在歌曲之间移动。

Web Speech API还可以在许多其他领域带来改进或带来新的可能性。 例如,浏览电子邮件,浏览网站或搜索网络-一切都用您的声音进行。

您在项目中使用此API吗? 我希望在下面的评论中收到您的来信。

From: https://www.sitepoint.com/voice-controlled-audio-player-web-speech-api/