サルでもわかるWEBプログラミング

フリーソフトのみでホームページ作成

ユーザ用ツール

サイト用ツール


サイドバー

目次

サルでもわかる機械学習

sidebar

12.vue.jsとwebspeechapiで音声認識アプリ:index.html


Vue.jsとWebSpeechAPIとFirestoreで音声認識アプリ(ボイスレコーダー)

以下の本を衝動買いしたところ、Web Speech APIというWEBブラウザChromeで動作する簡単音声認識システムがあることを知りました。

Web Speech APIを使ったアプリはChromeでのみ動作します

Internet ExplorerやSafariでは動作しません。

このアプリの音声認識機能を利用するためには、パソコンでも、スマホでも、Chromeをインストールする必要があります。

手元のZenfone 4 Maxでは、Chromeにて音声認識することはできました。PWA(Progressive Web Apps)なので、スマホにアプリとして登録し、オフラインで使用可能です。

なお、iPhone8のChromeでtryしましたが、STARTボタンの“START”が表示されず、クリックしても音声認識が開始されませんでした。(残念、、、)

方針をたてる

  1. マイクのついた端末で、Chromeでアプリを開いてもらうことが前提
  2. スタートボタンを押して、マイクに話しかけると、話しかけた内容が文字で表示される
  3. ストップボタンで文字おこし中止
  4. 文字におこしたテキストを、Firebase Firestoreに保存し、メモ一覧を表示し、検索、削除できる

今回は、以下のコードを参考にさせていただきました。

ソースコード
https://codesandbox.io/s/71yznl2zwq

できたもの

デモサイト1
https://csb-71yznl2zwq.netlify.com/

デモサイト2

0.用意するもの(開発環境)

パソコン
Chrome(くろーむ、WEBブラウザの一つ)
GitHubアカウント作成済み(無料)
Googleアカウント作成済み(無料)

パソコンは、Windowsパソコンでも、Macでも、かまいませんが、私の場合はWindows 10 Proとなります。今回は、Web Speech APIを利用するため、アプリを利用する人にもChromeは必須です。Internet Exploler、Safari、Firefox、Edgeなどではうまく動かないそうです。

今回利用するもの

CodeSandbox
Firebase Firestore

Vue 2.5.2
Vuetify
firebase
moment

Codesandboxで新規Vue.jsアプリの作成

  • CodeSandboxでVueアプリを新規作成
  • Dependencyで、Vuetifyを追加
  • index.htmlとsrc/main.jsの編集し、Vuetifyを利用できるようにします。

src/App.vueにVuetifyのテンプレートを適用

src/App.vueにヘッダーとフッター、カードを追加します。

text-areaとbuttonを設定

Card内のimgを消して、textareaで置き換えます。button名もStartとStopに変更します。

src/App.vue

<template>
  <div id="app">
    <v-app id="inspire">
      <v-toolbar color="indigo" dark fixed app>
        <v-toolbar-title>Vue WebSpeechAPI Recognition</v-toolbar-title>
      </v-toolbar>

      <v-content>
        <v-container fluid>
          <v-flex xs12 sm6 offset-sm3>
            <v-card>
              <v-textarea
                outline
                name="input-7-4"
                label="Speech Recognition"
                v-model="text"
              ></v-textarea>
              <v-btn color="info" @click="startSpeech">{{
                recognitionText
              }}</v-btn>
              <v-card-title primary-title>
                <div>
                  Startボタンをクリックして、日本語で話しかけてください。終了したら、Stopボタンをクリックしてください。
                </div>
              </v-card-title>
            </v-card>
          </v-flex>
        </v-container>
      </v-content>
    </v-app>
  </div>
</template>

<script>
export default {
  data() {
    return {};
  }
};
</script>

参考:https://vuetifyjs.com/ja/components/textarea

初期データの設定

以下、src/App.vueの<sciprt>内にコードを編集していきます。
data: function() {} 内に、初期データを記載します。

  data: function() {
    return {
      text: "",
      recognition: new webkitSpeechRecognition(),
      recognitionText: "音声入力開始"
    };
  }

Web Speech APIを利用するためには、以下の2行を記載します。

const speech = new webkitSpeechRecognition();
speech.lang = 'ja-JP';

methods()関数とcreated()関数を定義

音声認識開始buttonをクリックすると、recognition.onstartで音声認識開始し、認識された時点(recognition.onresult)で認識結果をtextに代入します。
以下のコードをsrc/App.vueの<script>内に追加します。

created: function() {
    this.recognition.onstart = () => {
      this.recognitionText = "音声入力中...";
    };
    this.recognition.onend = () => {
      this.recognitionText = "音声入力開始";
    };
    this.recognition.onresult = event => {
      if (event.results.length > 0) {
        this.text = event.results[0][0].transcript;
      }
    };
  },
  methods: {
    startSpeech: function() {
      this.recognition.start();
    }
  }

音声入力開始ボタンをクリックして、実行してみる

  1. 音声入力開始ボタンをクリック
  2. 最初だけ、ポップアップ画面が出てくるので、マイクの使用に対して「許可」をクリック
  3. 「音声入力開始」ボタンをクリックして、パソコンに向かって「テスト」と話しかける

すると、以下のように、「テスト」と表示されました。

複数文の認識と、認識している途中にも結果を得る

参考:https://qiita.com/hmmrjn/items/4b77a86030ed0071f548

// 認識しっぱなしにする
recognition.continuous = true;

// 認識している途中にも結果を得る
recognition.interimResults = true;
  • “STOP”ボタンを設置し、stopSpeech()関数で音声入力終了とする

  • 音声入力の途中経過も表示する


動作確認します。
STARTボタンを押して、マイクに話しかけて、STOPボタンを押すと、以下のように表示されました。
テキストボックスの中身は編集することができます。

音声認識結果をFirebtase(Firestore)に保存する

http://i-doctor.sakura.ne.jp/web/doku.php?id=11.vue.js%E3%81%A8firebase%E3%81%A7%E7%94%BB%E5%83%8F%E3%82%A2%E3%83%83%E3%83%97%E3%83%AD%E3%83%BC%E3%83%80%E3%83%BC:index.html#%E6%96%B0%E8%A6%8Ffirebase%E3%82%A2%E3%83%97%E3%83%AA%E3%81%AE%E4%BD%9C%E6%88%90

と同様に、DatabaseのCloud Firestoreを使用できるように設定します。

https://console.firebase.google.com

から、

  1. 新規Firebaseアプリの作成
  2. apiキーなどをメモ帳などに保存
  3. Database > Cloud Firestoreの、「データベースを作成」をクリック
  4. 一時的に、テストモードにする

CodeSandboxでFirebaseを使用できるようにDependencyの追加とindex.htmlとsrc/main.jsの編集

  1. Dependencyで、さらに、firebaseを追加
  2. index.htmlの編集(不要かも?)
  3. src/main.jsの編集(こちらに、FirebaseのAPIキーなどをコピペします)
  4. src/App.vueの<script>直下にimport文を記載

テキストの内容をFirestoreに保存(src/App.vue)

src/App.vue
<template>にsaveText()のボタンを追加し、
<script>のmethods:{}内に、saveText()関数を定義します。

吹き込んでみます。SAVEボタンを押すと、Firestoreのrecognitionsに音声認識されたテキストが保存されていることが確認できます。

Firestoreに保存したテキストをリスト表示

参考:
https://qiita.com/MasanobuAkiba/items/6a0f4e3007816dd54bec

https://www.webopixel.net/javascript/1227.html

CodeSandboxのDependencyでmomentを追加

// <template>の一部
<v-card>
  <v-card-title primary-title>
  <h2>List</h2>
    <ul class="list-group">
      <li class="list-group-item" v-for="(note, index) in notes" :key="note.index">
        <div>{{ note.text }} ( {{ note.timestamp | moment }} )</div>
      </li>
    </ul>
  </v-card-title>
</v-card>

// <script>の一部
import moment from "moment";

export default {
  filters: {
    moment: function (date) {
      return moment(date).format('MM/DD HH:mm');
    }
  },
  
  methods: {
    saveText: function() {
      db.collection("recognitions").add({
        text: this.text,
        timestamp: Date.now()
      });
      this.text = "";
      this.getNotes();
    }
  }
}

誤認識などで、テキストフィールドに表示された内容を変更したいときは、テキストを編集後にSAVEボタンをクリックすれば、変更内容はアップロードするテキストに反映されます。

リストをVuetifyのData tablesで表示

リストの、以下の部分を、VuetifyのData tablesを用いて表示します。
(変更前)

<ul class="list-group">
  <li class="list-group-item" v-for="(note, index) in notes" :key="note.index">
    <div>{{ note.text }} ( {{ note.timestamp | moment }} )</div>
  </li>
</ul>

(変更後)

<v-data-table :headers="headers" :items="notes" :pagination.sync="pagination" class="elevation-1">
  <template slot="items" slot-scope="props">
    <td>{{ props.item.text }}</td>
    <td class="text-xs-right">{{ props.item.timestamp | moment }}</td>
  </template>
</v-data-table>

// 以下、<script>内
data: function() {
  return {
    headers: [
      {
        text: 'テキスト',
        align: 'left',
        sortable: false,
        value: 'text'
      },
      { 
        text: '時刻', 
        value: 'timestamp' 
      },
    ],
    pagination: {
      sortBy: 'timestamp',
      descending: true,
    },
  };
},

変更後は、以下のようになります。

参考:https://vuetifyjs.com/ja/components/data-tables

https://commis.hatenablog.com/entry/2018/05/29/102606

●VuetifyのData tableを指定列の降順で初期表示する方法

  1. <template>で、v-data-tableにpagination.syncプロパティを指定する。
  2. <script>で、data: function() {return {}} 内に、pagination: {sortBy: 'id', descending: true,}のように記載する。

Vuetifyのdata tableで検索(フィルタ)

Vuetifyのdata tableでは、検索(フィルタリング)はかなり簡単に行うことができます。

<template>内に、以下を追加。
特に、<v-data-table :search=“search” > がポイントです。

 <v-card>
    <v-card-title>
      List
      <v-spacer></v-spacer>
      <v-text-field
        v-model="search"
        append-icon="search"
        label="Search"
        single-line
        hide-details
      ></v-text-field>
          </v-card-title>
            <v-data-table 
              :headers="headers" 
              :items="notes" 
              :pagination.sync="pagination"
              :search="search" 
              class="elevation-1"
            >
     (略)
              <v-alert slot="no-results" :value="true" color="error" icon="warning">
                Your search for "{{ search }}" found no results.
              </v-alert>
            </v-data-table>
 </v-card>     
<code>
さらに、<script>内に、以下を追加
<code>
data: function() {
    return {
      search: '',   // ←これを追加!!
    }
}  

Vuetifyのdata tableで削除ボタン

<scipt>のdata:のheaders: []内の最後に以下を追加

        { 
          text: '削除',
          value: 'name',
          sortable: false 
        }

getNotes()内の、array.pushの中に、idも追加するように編集。(後で、idを用いて、Firestore内のデータを削除するため。)

<template>内に、削除ボタンを追加(deleteItem関数を設置)

<script>のmethods内に、deleteItem関数を定義

    deleteItem: function(item) {
      const index = this.notes.indexOf(item)
      console.log(index);
      //const obj = this.notes[this.index]
      //console.log(obj);
      const id = this.notes[index].id;
      console.log(id);
      console.log(this.notes)
      db.collection("recognitions").doc(id).delete();
      this.getNotes();
    }

(ちなみに、data内の、index: 0 は削除しました。)

これで、メモの検索と削除ができるようになりました。

以上となります。

ソースコード

ソースコード
https://codesandbox.io/s/71yznl2zwq

できたもの

デモサイト(パソコンまたはスマホの、Chromeで開く必要があります。)

Web Speech APIに関するリンク

https://qiita.com/hmmrjn/items/4b77a86030ed0071f548

https://qiita.com/Sa2Knight/items/a7deb5b5d07820f6f19e
@Sa2Knight
2018年05月05日に投稿
[Vue] 音声入力できる入力コンポーネントを作る

https://qiita.com/GalapagosOf/items/b0df73a0a53a29b40388
@GalapagosOf
2018年07月28日に投稿
WebSpeechAPIの概略

https://qiita.com/yorifuji/items/9988f9a31c48bae31def
@yorifuji
2018年12月19日に更新
SkyWay Advent Calendar 201819日目
リアルタイム翻訳機能の付いたWeb会議を作ってみた
https://github.com/yorifuji/webrtc-realtime-translation

https://qiita.com/TakeshiNickOsanai/items/7a486085b039c2128217
@TakeshiNickOsanai
2018年12月06日に投稿
Web Speech API を 利用して 英単語の音声確認をするアプリを作る

https://qiita.com/tomsato/items/22735755b30a41e9a7e4
@tomsato
2018年08月27日に更新
Vue.jsとWebSpeechAPIを利用して音声文字起こし補助サイトを作った話

Vue.jsとCloud FirestoreでTODOアプリのリンク

https://grokonez.com/frontend/vue-js/vue-js-firestore-example-vue-js-crud-serverless-with-firebase-cloud-firestore

https://qiita.com/rubytomato@github/items/78087a2c69389f642760
@rubytomato@github
2018年05月09日に更新
Cloud Firestore with Vue.jsで簡単なメモアプリを実装する

Vuetifyのdata tableに関するリンク

https://qiita.com/nobu-maple/items/f0322bc99dce2d8eda40
@nobu-maple
2018年12月18日に更新
STEP05:Laravel5.7 + Vue2.5 で Vuetifyのダイアログを使ってユーザ情報を更新

https://qiita.com/d-yosh/items/9299389b32c496a9b64c
@d-yosh
2018年03月16日に更新
Vuetify.jsのData tablesでフィルタリングを行う

https://medium.freecodecamp.org/how-to-build-a-real-time-editable-data-table-in-vue-js-46b7f0b11684
How to build a real-time editable data table in Vue.js
Peter Mbanugo
Jun 23, 2018

リンク


12.vue.jsとwebspeechapiで音声認識アプリ/index.html.txt · 最終更新: 2019/05/11 by adash333