🗣️

AWS re:Invent 2023のために英日同時通訳アプリを試作した

に公開

概要

AWS re:Invent 2023に行くけど英語に自信がない人(自分)用に同時通訳アプリを作りました。
趣味の延長で試作したプロトタイプ版なので改善点はいっぱいありますが、「英語音声から日本語訳文に変換する」という最低限の部分は実装済みです。

もっとよくしたいところを後述しています

アーキテクチャ

mulata_proto.drawio.png

解説

画面

スクリーンショット 2023-11-13 8.02.06.png
画面はこんな感じ。
STARTボタンを押すと録音が開始されます。
翻訳結果と英語原文を上下でリアルタイムに表示します。

使用技術

  • AWS
    • Amazon Transcribe
    • Amazon Translate
    • Amazon S3
    • AWS Lambda
  • Application
    • Go(gin)
    • HTML/CSS/JS(Vanilla JS)

ソースコードはこちら↓

https://github.com/tttol/mulata-ws5/tree/main

ロジック

ロジックの流れをざっくり記載します。

1.JSで音声データを取得してWebSocket通信でバックエンドに送信

let mediaRecorder;

document.querySelector("#startRecord").addEventListener("click", function () {
    navigator.mediaDevices.getUserMedia({ audio: true })
        .then(stream => {
            mediaRecorder = new MediaRecorder(stream);
            audioChunks = [];

            mediaRecorder.ondataavailable = event => {
                ws.send(event.data);

                // WebSocket.OPEN: 1
                if (ws.readyState === 1) {
                    ws.send(event.data);
                    console.log("send audio data");
                } else {
                    console.log("Failed to send audio data.");
                }
            };

            startRecording();
            getTranslateResult();
            getTranscribeResult();
        }); 
});

2.バックエンド処理で.webm → .mp3に変換

func toMp3(inputFile string) ([]byte, error) {
	cmd := exec.Command("ffmpeg", "-i", inputFile, "-f", "mp3", "-")
	var out bytes.Buffer
	var stderr bytes.Buffer
	cmd.Stdout = &out
	cmd.Stderr = &stderr
	if err := cmd.Run(); err != nil {
		return nil, fmt.Errorf("error encoding audio: %v (stderr: %s)", err, stderr.String())
	}
	return out.Bytes(), nil
}

3.S3にmp3をアップロード

func uploadToS3(sess *session.Session, bucket, key string, data []byte) error {
	s3Svc := s3.New(sess)
	input := &s3.PutObjectInput{
		Bucket: aws.String(bucket),
		Key:    aws.String(key),
		Body:   bytes.NewReader(data),
	}
	_, err := s3Svc.PutObject(input)
	return err
}

4.mp3をAmazon Transcribeが解析して英文文字列のJSONに変換

5.英文JSONをAmazon Translateが日本語に翻訳して結果をS3にアップロード(JSON)

もっとよくしたいところ

  • MediaRecorder.start(timeslice)を使って連続的に録音処理をしたい
    • 現アプリはtimesliceなしでMediaRecorder.start()MediaRecorder.stop()を5秒毎に繰り返して録音を実施している
    • これではstop →startの間の数ミリ秒間の音声が拾えない
    • MediaRecorder.start(timeslice)でtimeslice秒ごとに音声データを区切ってPOSTできそう
    • しかし、区切ると音声データ(.webmファイル)のヘッダー情報が2個目以降欠損する
    • ヘッダがないとバックエンド(Go)で解析に失敗する
    • 参考:https://www.slideshare.net/slideshow/embed_code/key/3dL9PrhnQ3hVQ7
  • 翻訳結果の取得をAPI GatewayのWebSocket APIでやりたい
    • 現アプリは定期的にS3を見に行っている
    • WebSocket通信で翻訳結果到着を検知してリアルタイムに取得したい
    • API Gateway力が足らんかった
  • GoアプリをAWSサービス上で動かしたい
    • 現状localhostで動かすことしかできない
    • ECSで動かしてみたい
  • テストコード書きたい
    • 書け

Discussion