Upgrade to Pro — share decks privately, control downloads, hide ads and more …

JAWS FESTA 2025でリリースしたほぼリアルタイム文字起こし/翻訳機能の構成について

JAWS FESTA 2025でリリースしたほぼリアルタイム文字起こし/翻訳機能の構成について

JAWS FESTA 2025 向けに、ブラウザからの音声をほぼリアルタイムで文字起こしするための機能を実装しました。本セッションでは、その技術選定と構成上の工夫を紹介します。
技術選定としては下記を選定しています。
・音声入力:MediaStream API+AudioWorklet など
・音声認識と翻訳:Amazon Transcribe SDKとTranslate SDK
音声入力に関しては安定性を考慮しました。その詳細な構成について説明させていただきます。
音声認識と翻訳はリアルタイム性と使いやすさを意識しました。UIにおける工夫も述べさせていただきます。
音声入力でWeb Speech API 、音声認識と翻訳でChime SDK や、API Gateway+Lambdaも候補に上がりましたが、それらを不採用とし、今回のリソースを採用した理由についても説明させていただきます。

Avatar for 木村直紀

木村直紀

March 07, 2026
Tweet

More Decks by 木村直紀

Other Decks in Technology

Transcript

  1. #jawsug #jawsdays2026 #jawsdays2026_x 自己紹介 名前:木村 直紀 エンジニア歴:営業から転職して5年目 資格:G検定、LPIC1 2024-2025年 All

    Certification Engineer 2024年 AWS Top Engineer 2026年 AWS Community Builders(Cloud Operations) 好きなAWSサービス:AWSサポート、ECS
  2. #jawsug #jawsdays2026 #jawsdays2026_x リリースしたアプリの説明 JAWS FESTAで左の図のようなアプリケーシ ョンをリリースしました。 対応機能 • 音声のリアルタイム文字起こし

    • 日→ 英 翻訳 使われる場面 • キーノートセッション なんのために作ったか? より多くの参加者がセッション内容を理解でき るようにするため • 聴覚に障害を持つ方 ⇨リアルタイム字幕で内容を理解 • 英語話者の参加者 ⇨ 日→英の翻訳で内容を理解
  3. #jawsug #jawsdays2026 #jawsdays2026_x • Amazon Chime SDKを使った文字起こし • API Gateway

    + LambdaでTrancribe API/ Translation APIを呼び出し • Trancribe SDK/ Translation SDK 今回試したAWS構成 AWSの構成について
  4. #jawsug #jawsdays2026 #jawsdays2026_x Chime SDKを使った場合 AWSの構成について メリット • リアルタイム音声・ビデオ通信(通話/会 議)を

    自前で構築する必要がない • 話者付きテキスト生成が可能 デメリット • ユーザー名、会議室などの情報の入力が必要 →会議が始まる前に入力してもらうののが手間 ボタンを押すだけで、ユーザー名などの情報をダミー値で入力されるようにしたが、その後にtokenの処理も 必要になり、ボタンを押しても「文字起こしが中々始まらない…」となった。 話者分離も必要ないので、今回は別の方法でという形で見送った…
  5. #jawsug #jawsdays2026 #jawsdays2026_x LambdaからそれぞれのAPIを呼び出した場合 AWSの構成について メリット • API Gatewayで認証・認可、CORSの設 定ができてセキュリティ的にいい

    デメリット • API Gateway → Lambda → AWSサービスと段 階が増えて、少し遅い リアルタイム性という観点では少し遅いな…という印象で、他の方法を探しました。
  6. #jawsug #jawsdays2026 #jawsdays2026_x SDKを使用して各APIを呼び出す場合 AWSの構成について メリット • フロントエンドから直接呼び出している ので、レイテンシが低い デメリット

    • IAMアクセスキーの管理が発生し、セキュリテ ィリスクが発生する 「IAMアクセスキーの管理」というところは、一般公開されているサービスでは致命的に感じますが、 今回あくまで、「JAWS Festaで一時的に使われるサービス」というところで、レイテンシーの低さを重視して、 この構成を採用としました。
  7. #jawsug #jawsdays2026 #jawsdays2026_x • Web Speech API • MediaDevices API/

    MediaStream APIなど 音声の入力で試したもの 音声の入出力について
  8. #jawsug #jawsdays2026 #jawsdays2026_x Web Speech APIとは、ウェブブラウザ上で「音声認識(文字起こし)」と「音声合 成(文字の読み上げ)」を実現するためのAPIです。 Web Speech API

    音声の入出力について メリット • このAPI単体で以下のことが可能 • マイクからの音声の読み取り • 文字起こし デメリット • 一定時間無音であると認識が終わったものとみなされ て停止される(数秒〜数分で停止していた…) →このデメリットが致命的だった
  9. #jawsug #jawsdays2026 #jawsdays2026_x MediaDevices API/ MediaStreamなど(概要) 音声の入出力について それぞれの機能について • MediaDevices

    API マイクやカメラなどのメディアデバイスにアクセスするため のブラウザ標準API • MediaStream MediaDevices API でマイクやカメラにアクセスした際に返 されるオブジェクト • Web Audio API ブラウザ上で音声を処理・加工・再生するための標準API • ReadableStream データを少しずつ読み取るためのブラウザ標準オブジェクト
  10. #jawsug #jawsdays2026 #jawsdays2026_x 音声の入出力について 可憐なAmazon Transcribeという花への水やりに例えてみた 水源 (マイク) 水道局 (ブラウザ)

    配管 (MediaStream) 水道 (Web Audio API) 問い合わせ 許可 契約者 (MediaDevices API) ホース (ReadableStream) 水の届け先 (Amazon Transcribe) ④必要な分だけ出す ②マイクと繋ぐ ③音声を加工して、 出力できる状態にする ①マイクと繋げられるよう リクエストを投げる
  11. #jawsug #jawsdays2026 #jawsdays2026_x 音声の入出力について MediaDevices API/ MediaStream 項目 設定値 目的

    サンプリングレート 16kHz 音声認識の標準 チャンネル数 1ch 軽量化 エコー除去 ON スピーカー音を除去 ノイズ抑制 ON 環境音を除去 音量自動調整 ON 声の大小を均一化 サンプルサイズ 16 Transcribeの要求するbit 音声設定 説明 MediaDevices API を使用してマイクにアクセスし、音声認識 に最適化された設定で MediaStream を取得 処理フロー ブラウザ → マイクにアクセス許可を要求 → 音声データを取得 参考文献:https://developer.mozilla.org/en-US/docs/Web/API/MediaTrackConstraints
  12. #jawsug #jawsdays2026 #jawsdays2026_x 音声の入出力について Web Audio API(概要) 項目 内容 ①

    AudioNodeに変換 MediaStream を処理可能な AudioNode に変換 ② バッファリング 128サンプルずつ来るデータを2048サンプルに蓄積 ③ PCM変換 Float32(-1.0〜1.0)→ PCM16(整数)に変換 参考文献:https://developer.mozilla.org/ja/docs/Web/API/Web_Audio_API
  13. #jawsug #jawsdays2026 #jawsdays2026_x 音声の入出力について Web Audio APIの部分(①AudioNodeに変換) 処理の説明 MediaStreamをAudioNodeに変換 また、AudoWorkletに接続

    • MediaStreamは音声処理が行えるように AudioNodeに変換する必要があるため 参考文献: https://developer.mozilla.org/ja/docs/Web/API/AudioNode • AudoWorkletに接続することで、音声処理を別ス レッドを行えるようになり、フロント側の処理と は分けて、音声処理を行えるようになるため 参考文献:https://developer.mozilla.org/ja/docs/Web/API/AudioWorklet この処理を行う理由 別スレッドへ
  14. #jawsug #jawsdays2026 #jawsdays2026_x 音声の入出力について Web Audio APIの部分(②バッファリング) 説明 バッファを貯めてメインスレッドに送信 •

    データを細切れに送ると、送信回数が増え、通信の オーバーヘッドになる 参考文献:https://en.wikipedia.org/wiki/Packet_aggregation • Amazon Transcribeへのデータ送信量のベストプラ クティスに収めるため 参考文献:https://docs.aws.amazon.com/transcribe/latest/dg/streaming.html この処理を行う理由 効率悪い 効率良い
  15. #jawsug #jawsdays2026 #jawsdays2026_x 音声の入出力について Web Audio APIの部分(③PCM変換) 説明 Float32(-1.0〜1.0)の値をPCM16(整数)に変換 Amazon

    Transcribeにデータを送信するために、 Float32(-1.0 〜 1.0)の範囲のデータを、 PCM16(-32768 〜 32767)の範囲に変換する必要があるため ( Amazon TranscribeではPCM16でのデータ送信が推奨されている) 参考文献:https://docs.aws.amazon.com/transcribe/latest/dg/streaming.html この処理を行う理由 ※0x8000, 0x7FFFは16進数の数値。 0x8000 = 32768、0x7FFF = 32767となる。
  16. #jawsug #jawsdays2026 #jawsdays2026_x 音声の入出力について MediaDevices API/ MediaStream 処理の説明 これまで作ってきた処理で、下記の順番でパイプに流 す処理を実行している。

    ①AudioWorkletからのメッセージを取得 ②メッセージを処理してFloat32からPCM16に変換 ③音声データをPCM16 をバイト配列に変換してパイ プに流し込む 参考文献:https://developer.mozilla.org/ja/docs/Web/API/ReadableStream
  17. #jawsug #jawsdays2026 #jawsdays2026_x 画面の工夫 ①色 ①色は色盲の方でも区別がつきやすい色を採用 ②マーク ④AutoScroll ③区切り ②①と同様の理由で、マークをつけることで左右で違うものだと認識しやすいようにした

    ④自動で一番下のブロックまでスクロールするように設定。それによって、左右のブロックを横並びになるようにした ③会話の区切りをブロックで分けることで、文章を認識しやすくした
  18. #jawsug #jawsdays2026 #jawsdays2026_x AWS Transcribeから出力されたtextをキャッシュ機能で既出 のテキストならすぐに出力するように設定しました。 既出のtextはMAPオブジェクトに登録されます。 例えば、「こんにちは」とtextが既に入力されていればMAP 内には下記のように登録されます。 登録されていれば、「MAPより翻訳結果を取り出し」

    未登録なら、「AWS Translation APIを呼び出す」とするこ とで少しでも出力の時間を削減するように設定しています。 キャッシュ機能で少しでも早く翻訳結果を返す Translation SDKの部分 Map (translationCache) ├─ キー: “こんにちは_en_auto" │ └─ 値: { originalText: “こんにちは", translatedText: "Hello", ... } └─ キー: "ありがとう_en_auto" └─ 値: { originalText: "ありがとう", translatedText: "Thank you", ... }
  19. #jawsug #jawsdays2026 #jawsdays2026_x 課題 ① Speakerの喋り方によってはブ ロックが大きくなってしまう ② 文字がもう少し大きくてもよ かった

    ③ 時々文字を、別の文言に変換 してしまっていたり 例)地震→自身 暖かい拍手→戦い拍手