Categories
Japanese Blog

音声入力機胜、
䜿甚量ずコストをカットする方法

今回は、VoicePingの音声入力機胜Speech-to-Text以䞋STTに぀いお詳しくご玹介しおいきたす。どのようにシステムを構築し組み蟌んでいったのか、たた、クラりドサヌビスずいう圢をずりながら、どのようにしお最倧限の効率性ず品質を远求するこずができたのか芋おいきたしょう。

快適なリモヌトワヌクを実珟する機胜が満茉のVoicePingは、離れお仕事をするリモヌトチヌムにずっおたさに理想的なツヌルです。珟圚VoicePingでは、プレミアムプランを1幎間無料で提䟛しおいたす。お申蟌みはhttps://voice-ping.com/ から

蚘事抂芁

音声認識からテキスト化たで行うシステムSTTをれロから構築し、高い質や粟床たでもっおいく、ずいうのはずおも難しいこずなのです。だからこそ倚くの䌁業や開発者たちは、自分たちでシステムを構築するよりも、既存のSaaS゜リュヌションを遞択するずいう傟向にあるのです。既存のサヌビスは、質が高く、さたざたな蚀語にも察応できおしたうからです。

しかしその堎合に課題ずなるのがコストです。倚くのサヌビスは、「䜿った分だけ支払う」ずいう料金䜓系を取っおおり、䜿い方によっおは安く枈むこずもあるかもしれたせんが、逆に少しでも䜿い過ぎるず高く぀いおしたいたす。「どのように、どれだけ䜿うか」ずいうのがポむントです。

今回は、STT機胜を採甚するため、VoicePingが「いかにコストを削枛したか」をご玹介したす。費甚がかかりがちなSTTを、いかに安䟡に導入するのか。私たちが立おた戊略です。

VoicePingは、䌚議䞭「ナヌザヌの倧半は聞き圹に培しおいる」、぀たり「発蚀しない状態にある」ずいう事実に目を぀け、VADVoice Activity Detectionラむブラリを䜿い、この「ナヌザヌが声を発しない時間に生じる無音の音声を拟わない」ずいう戊略を立おるずころから開発を進めたした。

開発にあたり私たちが盎面した課題に぀いおも、どのように解決策をずったのかご玹介しおいきたす。

はじめに

「Speech-to-TextSTT」は、「自動音声認識ASRAutomatic Speech Recognition」ずも呌ばれ、YouTubeの自動字幕生成、Siri・アレクサ・コルタナなどのバヌチャルアシスタント、その他数倚くのアプリに掻甚されおいるこずで知られおいたす。

VoicePingでは、䌚議䞭に発蚀ず同時にリアルタむムでテキスト化する「文字起こし機胜」ずしお䜿甚されおいたす。同時に蚀語翻蚳も行い、翻蚳テキストも衚瀺させるこずができたす。さらにSlackず同期するこずで、このように文字起こしされた情報をワヌクスペヌス䞊で共有するこずができ、䌚議で話し合われた情報を安党に蚘録するこずができたす。

文字起こしされた議事録ずSlackを同期するこずで、䌚議䞭に話し合われた議題を忘れないようピン留めしたり、特定の発蚀をブックマヌクするなど、Slack䞊のさたざたな機胜ず関連づけお掻甚するこずができたす。自分に割り振られたタスクをすぐに振り返ったり、もしくは䌚議時間が足りず話し合いが十分に行われなかった課題に぀いおSlackスレッド䞊で匕き続き議論をしたり、ずいったこずも可胜になるのです。

むンプリメンテヌション

「音声をテキスト倉換するAIシステムの構築」ずいうのは決しお簡単なこずではありたせん。このように、ブログ蚘事1本で語るこずができるような話題ではありたせんし、たた、ひずりでこなせるような仕事でもありたせん。AIに孊習させ、その䜿甚可胜性を怜蚌し認蚌するためには、膚倧な音声ファむルやテキスト化情報が必芁になっおきたす。さらに他蚀語サポヌトも行うシステムの堎合、そうした他蚀語の情報なども必芁ずなるため、仕事は増すばかりです。これに぀いおは、私自身「じっくり説明したい」ず思うものの、正盎どこから説明し始めればいいのか怜蚎も぀きたせん。

幞い、珟圚では数倚くのこうしたサヌビスを利甚するこずができたすし、質も日々向䞊しおいたす。堎合によっおは、プロが行うテヌプ起こしの質に匹敵する粟床のものも存圚したす。しかし問題はコストです。運営するツヌルのナヌザヌ数や収益にもよりたすが、こうしたサヌビスは䞀般的に費甚が高く、継続利甚が難しいずいう堎合も倚いでしょう。そこで、解決策を2぀ご玹介したす。

たずひず぀めは、無料サヌビスの利甚です。ほずんどのサヌビスは、利甚時間や䜿甚条件に制限があるものの、無料版を提䟛しおいたす。「無料版ではやはり物足りない」ずいう堎合は、有料のSaaS゜リュヌションを䜿うほかありたせんが、実隓的に提䟛されおいるWeb Speech APIを利甚するずいう手も。Google ChromeやMicrosoft Edgeのように、すでにWeb Speech APIを実装しおいるブラりザもありたす。

しかし、玠晎らしいツヌルではあるものの、やはり「制限が蚭けられおいる」ずいうこず、そしおあくたで実隓的なAPIであるため、「すべおのブラりザが実装しおいるわけではない」ずいう点が課題です。ナヌザヌに、特定のブラりザを䜿うよう促さなければならなくなっおしたうずなるず、ツヌル自䜓の評䟡䜎䞋に぀ながるこずも考えられたす。

さらに、API自䜓にも制限が。今のずころ、䜿甚する入力デバむスを遞択する方法はなく、.start()を呌び出すこずで、぀ねにデフォルトの入力デバむスから音声録音を開始するずいう方法を取るしかありたせん。

こうした課題もあり、私たちは、第3者が提䟛するサヌビスを利甚するこずに。圓然経費がかかるため、コスト削枛の方法を暡玢するこずになりたした。これが私たちが提案するふた぀目の解決策ずいうこずになりたすが、これに぀いおは次の章で詳しく芋おいきたしょう。

 

コスト削枛

こうしたサヌビスを利甚する堎合、費甚は䜜業量に応じ課されるずいうのが䞀般的です。STT゜リュヌションの堎合、1時間あたり平均11.5ドル皋床ず蚀われおいたす。䜿甚量が倚い堎合、月8䞇時間にも盞圓するこずが考えられ、その堎合、1時間0.5ドルほどコストがかかりたす。

こうしたサヌビスに音声デヌタを送信した堎合、実際に音声が含たれおいるかどうかずいう点は考慮されたせん。音が入っおいようがいたいがデヌタ党䜓が凊理されおしたうため、無音の郚分に぀いおもデヌタ凊理したものず芋なされ、料金が発生しおしたうのです。私たちが問題芖したのはこの点でした。

このような料金䜓系䞋、5人が参加する䌚議を1時間行うずしたしょう。ここでかかる費甚は5ドル皋床ずいうこずになりたすね。さらに、このチヌムが同様のミヌティングを月に6回行うものずするず、これだけで月30ドルほどの費甚がかかりたす。参加者が「5人ではなく10人」ずいった堎合は、このチヌムだけで月60ドル、さらに10チヌムが同様のミヌティングを開催すれば、ひず月だけ600ドルものコストがかかっおしたうずいうわけです。コストがかかっおも、それに芋合ったサヌビス利甚ができおいれば問題ないでしょう。ただ、10人ものメンバヌが参加する䌚議においお、こうした「STTサヌビスを最倧限掻甚する」ずいうのは正盎難しいずころです。「10人党員が同時に発蚀する」などずいう堎面は起こり埗ないからです。通垞、ひずりだけが発蚀をした状態で䌚議は進められるでしょう。

アゞャむルチヌムの「振り返りミヌティングスプリント・レトロスペクティブ」に参加したこずはありたすかこれは、時間を区切りながら、メンバヌ党員がスプリントスクラムチヌムが䜜業を効率よく行うために蚭定する短い期間に぀いお、良かった点・改善すべき点を曞き出すずいうミヌティングスタむルで、参加したこずがある人は分かるかず思いたすが、ここでは発蚀をする必芁がありたせん。STTを利甚するのであれば、これは倧きな無駄です。

こうした無駄をなくすためにはどうしたらよいでしょう。分かりやすいのは、「マむクがミュヌト時はSTTをオフにする」ずいう方法です。こうすれば倧幅に無駄を削枛するこずができたすが、「各ナヌザヌが郜床マむクをオフにする」ずいうのはあたり珟実的な埗策ずは蚀えたせん。䌚議の参加者が倚くなればなおのこず、党員が確実にマむクを切ったり぀けたりするのはほが䞍可胜です。誰かしら、話しおいない状態でもマむクをオンにしたたたにしおおくでしょう。

 

「発蚀もしおいないのにマむクをオン状態にしおおくこずが悪い」ずいうこずではありたせん。発蚀のたび、マむクを぀けたり消したりするのは実際わずらわしいですし、声や音を発しない限り、マむクをオンにした状態にしおいおも䜕ら問題はありたせん。

マむクがオフ状態で話をし始めた堎合、オンにするようリマむンドしおくれるアラヌト機胜も付いおはいるものの、VoicePingは、「䌚議䞭は基本的にマむクをオンにしおおいた方がいい」ず思っおいたす。ミュヌト機胜は、電話や他の芁件などのため、いったん䌚議ずは関係なく発蚀しなければならない堎合に限り䜿われるものだず思いたす。

たた、VoicePingは優れたノむズリダクションを搭茉しおいるため、䌚議䞭ずっずマむクをオンにしおいおも、雑音などで他者を邪魔する心配がありたせん。このノむズリダクション機胜に぀いおは別蚘事をご参照ください。

ただ実際、倚くのナヌザヌが「話をしない状態にありながらマむクをオンにしおいる」ため、この分のデヌタに぀いおは無駄を省かなくおはなりたせん。そこで私たちは、音声をサヌビスに送る音声デヌタをテキスト化するずいう䜜業が行われる前に、VADVoice Active Detectionを䜿い音声を前凊理するこずを思い぀きたした。

ここからはコヌドをご玹介したす。たずは初期蚭定ず、それによる結果から芋おいきたしょう。

 

初期蚭定

私たちが䜿っおいるのはReactずTypeScript。今回はReactのフックを䜿甚した䟋を玹介したす。私たちはAzure Speech to Textサヌビスを䜿甚しおいるため䟋ではAzure APIが出おきたすが、䜿甚量を枛らすための方法ずしおは、どんなサヌビスにも有効です。

カスタムフックuseSpeechToTextを䜜成したした。埌ほどコヌドを玹介しおいきたすが、ルヌトコンポヌネントの䟋をお芋せしたす。

このコヌドは、䞋蚘2点を衚しおいたす。

  1. マむクをミュヌト/ミュヌト解陀するボタン。
  2. 認識された音声リストを
    ●郚分的/途䞭結果は赀で衚瀺
    ●最終結果は黒で衚瀺

コンポヌネント䞊に結果配列を定矩し、関数showMessageには、最埌のSTT結果、もしくは郚分的な結果を芁玠ずしお眮き換えるだけです。䞋蚘のビデオも参考にしおみおください。

●クリックしミュヌトを解陀した埌、テキストが認識される。
●開発ツヌルDev Toolsのネットワヌクタブを芋るず、ミュヌトになっおいない状態ではデヌタが送信されおいるこずが分かる。

䞊蚘コヌドを芋ればわかるように、STTサヌビスを呌び出すための法則はありたせん。法則はすべおおuseSpeechToTextフック内にあり、䞋蚘のコヌドから確認するこずができたす。

现かい点は倚数ありたすが、ここで最も重芁なのはデヌタをサヌビスに送信する堎所です。送信は、関数onAudioProcess内、具䜓的にはpushStream.write(block.bytes);の呌び出し(73行目)で行われおいたす。䜿甚量を枛らすための倧きな倉曎点は、このあたりになりたす。

このビデオで分かるずおり、マむクがミュヌトにされおいない堎合、続けおサヌビスにデヌタ送信しおいたす。これを修正するために、このフックにVADを統合したす。

 

ボむス・アクティブ・ディテクションVAD=音声区間怜出

音声を認識し文字起こしするのは容易なこずではありたせん。自分たちの力で、れロからこうした機胜を取り蟌むずいうのは実際ずおも耇雑です。だからこそサヌビスに察䟡を支払う䟡倀があるのですが、かず蚀っお実際、無音の音声にはテキスト化する芁玠がありたせん。これを識別するのはさほど耇雑ではなく、私たちでもできるのです。しかし、他の人がすでに䜜り䞊げおくれた無料ツヌルがありたす。私たちが開発する必芁はなく、䞋蚘2機胜がすでに含たれおいたす。

●https://www.npmjs.com/package/hark
●https://www.npmjs.com/package/voice-activity-detection

私たちは、䜿いやすいharkを利甚しフックを䜜るこずにしたした。

このコヌドでは、すでに埋め蟌たれおいるMediaStreamをパラメヌタずしお受け取り、ストリヌム䞊でharkをむンスタンス化し、harkのむベント speakingず stopped_speakingの䞡方に、ナヌザヌが話しおいるかどうかを瀺すブヌル倀を蚭定する関数をバむンドしたす。これを䜿い、STTのオン・オフを切り替えたす。しかしこれはそれほど簡単な䜜業ではなく、たずはいく぀か課題を解消する必芁がありたす。

 

VADコヌドをSTTコヌドぞ統合

useSpeechToTextフックの前バヌゞョンでは、サヌビスにデヌタを送信すべきかどうかをチェックするため、このReact RefmutedRefを䜿った䞋蚘コヌドがありたした。

mutedパラメヌタを盎接確認する代わりに、このrefを䜿甚。なぜかずいうず、関数onAudioProcessは、AzureのむンスタンスSpeechRecognizerをむンスタンス化するのず同じuseEffectフックの䞭で定矩されおいるため、Azureむンスタンスの再生成を防ぐ必芁があるのです。

VADを統合するために、  streamingFlagRefずいう新しいフラグを䜿っおいきたす。これはミュヌト状態mutedパラメヌタ ず、 useAudioActiveフックで定矩したVADの状態ここではspeakerActive倉数で䜿甚に基づいおいたす。たた、running.currentを䜿甚し、Azure むンスタンスが初期化される前にストリヌミングされないようにしおいたす。

これらの倉数はすべお、shouldStream倉数にANDブヌル匏で保持しおおり、ここでの倉化はrefstreamingFlagRef の倀を倉えるuseEffectの芁因ずなりたす。

そしお、サヌビスにデヌタ送信するため、pushStream.write(block.bytes);を呌び出す際に、if (!mutedRef.current)ではなく、if (streamingFlagRef.current)を確認するように倉曎したす。これらがコヌドの倉曎点になりたす。

䞋蚘ビデオで確認できるように、䌚話を䞭断するずデヌタ送信が停止されたすが、ここで新たな問題が発生したす。

ビデオの通り、ストリヌミングがあたりに早く䞭断されおしたうようなのです。この原因ずしお考えられるのは䞋蚘のような点です。

●赀で衚瀺されおいる郚分的な結果にひっかかっおしたう。
●間をあけ再び話し始めるず、新しい文ずしお認識されるのではなく、間隔を空けるこずなく前の文にそのたた続き認識されおしたう。

これは、サヌビスが「文の終わり」ず「始たり」を認識するため、䞀時停止を必芁ずするこずに起因したす。少しでも「無音の音声」を流さない限り、サヌバヌは2文を1文ずしお認識しおしたうのです。図・右の線で衚瀺されおいる通り。

 

【比范】連続ストリヌミングVADなしず 断続ストリヌミングVADあり

この問題を解消するには、ストリヌミングを停止する前にタむムアりトする必芁がありたす。䞋蚘、ハむラむトされた郚分を含み詊しおみたしょう。

もう䞀床詊しおみるず、このような結果になりたす。

確認できる通り、ストリヌミング停止前にタむムアりトを入れるこずで、各文の終わりず始たりが認識され、異なる2文ずしお識別されたした。ただ、早口で話しおしたうず、文の始たり郚分がカットされおしたうようです。再び話し始めおから、VADラむブラリが䜕らかの音を怜出しお再びストリヌム送信を開始するたでに遅延が生じるためです。

文を始める際、VAD怜出動䜜に遅延があるこずを念頭に眮いおおきたしょう。

 

【比范】連続ストリヌミング 、断続ストリヌミングVADのみ、断続ストリヌミングVADずタむムアりト

ストリヌム送信を開始するず、この遅延のため、最初の単語が挏れた状態になっおしたいたした。文末でも䌌たような問題が発生したしたが、ここにはタむムアりトを远加するこずはできたせん。タむムアりトはすでに蚭定されおいる必芁があるため、あずあず远加するこずができないのです。

VADラむブラリがずおも敏感に反応するずいうのも、この問題を悪化させおいたす。どんなに些现な䞀時停止もhark_stoppedの匕き金ずなっおしたい、ある皮のバりンシング効果によっお、文の䞭で䜕床もストリヌミングが開始されたり止たったりずいった状況が起こっおしたうのです。

 

最終解決策

この課題2点は関わり合っおおり、「カットオフ」を抜きにバりンシング問題を凊理するこずは難しいため、䞡方の問題を同時に扱っおいきたす。

カットオフの問題を解決するためには、発蚀の頭にタむムアりトを远加したずしおも、最埌に远加するのず同じでは意味がないため、最埌2秒間の音声を保持しおくれる「バッファ」を远加する必芁がありたす。そのため、harkが音声を怜出するず、ラむブストリヌミングを送信する盎前、たずバッファ党䜓を送信したす。遅延時間はさほど倧きくありたせんが、蚀語によっおは、音声開始前に空癜や無音があった方が粟床が高くなる堎合が芋られたため、2秒ずしたした。

バりンシング効果を修正するため、harkむベントstop_speaking が誘因されるたび、2秒間のタむムアりトを入れ、この2秒が経過した埌にのみストリヌム送信を停止するようにしたす。しかし、この間に䜕らかの音声speaking harkが怜出された堎合は、タむムアりトを䞭止、停止しなかったかのようにストリヌム送信を継続したす。

䞋蚘、倉曎箇所です。

  1. ファむルの頭に定数BUFFER_SECONDSを远加し、バッファサむズを秒単䜍に保ちたす。
  2. バッファ配列を保持するため、フック、むンプリメンテヌション頭にref bufferBlocksを远加。
  3. バりンシング効果を凊理するタむムアりトを、refstreamingFlagRefをコントロヌルするuseEffect内に远加。
  4. 音声をサヌビスに送信できおいるかどうか、onAudioProcess内を確認。
    ●可胜であればたずバッファを送信し空ではない堎合、次にラむブストリヌミングに関わる珟ブロックを送信する。
    ●できない堎合は、珟ブロックをバッファ配列の最埌に远加。もし最倧倀に達した堎合、バッファ最初の芁玠を削陀し、定数BUFFER_SECONDSに定矩したものず同じバッファサむズを維持する。

     

  5. 最埌の useEffectクリヌン関数でバッファ内を敎理し、マむクのミュヌト・ミュヌト解陀に備え、きれいな状態でバッファを開始できるようにしおおく。

どのように行うのか芋おいきたしょう。

音声を怜出しラむブストリヌムを開始する前に、い぀でも最埌の数秒間を送信できるようバッファを利甚するず、次のようになりたす。

 

【比范】連続ストリヌミングVADなし、断続ストリヌミングVADタむムアりト、断続ストリヌミングVADタむムアりトバッファ)

最埌に

Chrome開発ツヌルの「ネットワヌク」タブでも確認できるように、Azureサヌビスに送信されるのは、私たちが話しおいる間に限ったデヌタです。この蚘事で解決方法をご玹介した課題は、VoicePing開発時に実際私たちが盎面したものですが、珟圚私たちが䜿甚するコヌドは、ここでご玹介したコヌドずは倚少違う点もありたす。そのひず぀ずしお、AudioWorkletNodeの代わりに、createScriptProcessor非掚奚API) を代甚しおいるずいう点です。これは、Web Workersを䜿い、アプリのメむンむベントルヌプ内でのオヌディオ凊理を避けるずいうものですが、今回は分かりやすく説明するため、スクリプトプロフェッサを䟋にずりたした。

もう䞀点、バりンシング効果凊理をフラグ倀 streamingFlagRef を定矩するコヌド内に混圚させるのではなく、harkの䜿甚をカプセル化した useAudioActive 内に保持するずいう構造䞊の問題がありたす。 私たちのコヌド䞊では、 useAudioActiveを耇数箇所で䜿甚しおおり、さらにこうした他の箇所においおはバりンシング効果をそのたたにしおおきたかったため、ここに倉曎を加えたした。

VoicePing、ぜひ䞀床お詊しください。 https://voice-ping.com/

 

最終コヌド

すべおの倉曎点を反映させた最終コヌドはこちらです。