見出し画像

「音声翻訳サービス」を使ってみた

みなさん、こんにちは
SOMPOシステムズのクラウドエンジニアです。
AWSの音声翻訳サービスを使ってみましたので、ご紹介します。


1.全体概要

1-1. 目的・背景

皆さんは、海外の企業との会議で英語がわからず苦労したことはありませんか?私は、日本語以外の言語には知識が乏しく苦労したことが何度かあります。そんなとき、自身の理解できる言語に翻訳でき、簡単に実装できるクラウドサービスはないかと思い調べたのが、今回のテーマのきっかけです。
以下が、今回のテーマの目的になります。

  • AWS上で触れたことのないサービスを利用してみること

  • 他言語の打ち合わせ時に活用できるサービスを見つけること

1-2. 構成イメージ

構成イメージ図はこちらになります。

1.構成イメージ図

今回実現したのは、任意の言語の動画ファイル(MP4)を、任意の言語に翻訳し、音声ファイル(MP3)として出力することです。

2.主要サービス

2-1. Amazon Transcribe

完全マネージド型の自動音声認識サービス。リアルタイムの文字起こしが実現可能のようです。
会議メモなどとしても有効活用できるため、Amazon Transcribe単体でも優秀です。

2-2. Amazon Translate

言語翻訳サービス。大量のテキストの翻訳が可能なようです。
Amazon Transcribeと同様、リアルタイム翻訳またはバッチ翻訳に対応しています。

2-3. Amazon Polly

リアルタイムな音声読み上げサービス。テキストを幅広い言語に対応した音声に変換することが可能です。


3.構築手順

使用リソース

  • Lambda:python 3.12

  • Amazon Transcribe

  • Amazon Translate

  • Amazon Polly

  • Amazon S3

  • AWS IAM:S3バケット読み取り、書き込み権限、上記サービスの読み取り、書き込み権限

3-1. 動画のテキスト化

動画ファイルのテキスト化のため、Lambda関数を作成します。
イベントトリガーでAmazon Transcribeジョブを実行し、実行結果として出力されるテキストファイルを任意のS3バケットに出力する仕様です。
※トリガーとなるイベントは、動画ファイル(MP4)を特定のS3バケットにアップロードすることとしています。

import json
import boto3
import urllib.parse

def lambda_handler(event, context):
    # TranscribeとS3クライアントの初期化
    transcribe = boto3.client('transcribe')
    s3 = boto3.client('s3')
    
    # S3イベントからファイル情報を取得
    bucket_name = event['Records'][0]['s3']['bucket']['name']
    object_key = urllib.parse.unquote_plus(event['Records'][0]['s3']['object']['key'])
    file_uri = f"s3://{bucket_name}/{object_key}"
    
    # Transcribeジョブ名の生成(ファイル名から拡張子を除いたもの)
    job_name = object_key.split('.')[0]
    
    # Transcribeジョブの開始
    try:
        response = transcribe.start_transcription_job(
            TranscriptionJobName=job_name,
            Subtitles={'Formats': ['srt']},
            Media={'MediaFileUri': file_uri},
            MediaFormat='mp4',
            LanguageCode='ja-JP',  # この例では日本語の音声を想定
            OutputBucketName='任意のバケット名'  # 結果を保存するS3バケット(オプション)
        )
        return {
            'statusCode': 200,
            'body': json.dumps('Transcription job started successfully.')
        }
    except Exception as e:
        print(e)
        raise e

3-2. テキストを任意の言語へ翻訳

テキストを任意の言語へ翻訳するための、Lambda関数を作成します。
3-1と同様、イベントトリガーで実行する関数とし、Translateメソッドの呼び出しを行い、任意の言語に翻訳します。
翻訳されたテキストは、任意のS3バケットに出力する仕様です。
※トリガーとなるイベントは、テキストファイルを任意のS3バケットにアップロードすることです。

import boto3
import urllib.parse

# Amazon Translateクライアントの初期化
translate = boto3.client(service_name='translate', use_ssl=True)

def lambda_handler(event, context):
    # S3クライアントの初期化
    s3 = boto3.client('s3')

    # S3イベントからファイル情報を取得
    bucket_name = event['Records'][0]['s3']['bucket']['name']
    object_key = urllib.parse.unquote_plus(event['Records'][0]['s3']['object']['key'])

    # SRTファイルの読み込み
    srt_file = s3.get_object(Bucket=bucket_name, Key=object_key)
    srt_content = srt_file['Body'].read().decode('utf-8')
    text_content = extract_text_from_srt(srt_content)

    # テキストの翻訳
    translated_text = translate_text(text_content)

    # 翻訳されたテキストの保存
    output_key = object_key.rsplit('.', 1)[0] + '-translated.txt'
    s3.put_object(Bucket='任意のバケット名', Key=output_key, Body=translated_text.encode('utf-8'))

    return {
        'statusCode': 200,
        'body': json.dumps('Translation and saving process completed successfully.')
    }

def extract_text_from_srt(srt_content):
    lines = srt_content.split('\n')
    text_lines = [line for line in lines if not line.isdigit() and '-->' not in line and line.strip() != '']
    text_content = ' '.join(text_lines)
    return text_content

def translate_text(text, source_language_code='ja', target_language_code='en'):
    response = translate.translate_text(Text=text,
                                        SourceLanguageCode=source_language_code,
                                        TargetLanguageCode=target_language_code)
    return response.get('TranslatedText')

3-3. テキストを音声ファイルへ変換

テキストを音声ファイルに変換するためのLambda関数を作成します。
アップロードしたテキストファイルを読み込み、Pollyメソッドを呼び出すことで、テキストを音声ファイル(MP3)へ変換します。
変換した音声ファイルは、任意のS3バケットにアップロードする仕様です。
※トリガーとなるイベントは、任意のS3バケットにテキストファイルをアップロードすることです。

import boto3

def lambda_handler(event, context):
    # S3とPollyクライアントの初期化
    s3_client = boto3.client('s3')
    polly_client = boto3.client('polly')
    
    # イベントからファイル情報を取得
    bucket_name = event['Records'][0]['s3']['bucket']['name']
    file_key = event['Records'][0]['s3']['object']['key']
    
    # S3からテキストファイルを読み込む
    file_obj = s3_client.get_object(Bucket=bucket_name, Key=file_key)
    text = file_obj['Body'].read().decode('utf-8')
    
    # Pollyを使用してテキストを音声に変換
    response = polly_client.synthesize_speech(
        Text=text,
        OutputFormat='mp3',
        VoiceId='Joanna'
    )
    
    # 音声ファイルをS3に保存
    if 'AudioStream' in response:
        output_bucketname = "任意のバケット名"
        output_key = file_key.rsplit('.', 1)[0] + '.mp3'
        s3_client.put_object(
            Bucket=output_bucketname,
            Key=output_key,
            Body=response['AudioStream'].read()
        )
    
    return {
        'statusCode': 200,
        'body': f'Successfully converted text in {file_key} to speech and saved as {output_key}'
    }

4.翻訳サービスを使ってみた感想

今回、3段階(テキスト化⇒翻訳⇒読み上げ)に分けて実装を行ってみました。そこで、3つのサービスに独立した利用用途があると感じました。

1つ目のAmazon Transcribeは、打ち合わせのメモの用途として利用し、業務効率化を実現できます。
2つ目のAmazon Translateは、自身の主要言語を翻訳し、他言語を扱う人に伝えることができます。
3つ目のAmazon Pollyは、電子文書などを視覚的にではなく聴覚でインプットすることができます。

また、3つのサービスを組み合わせた利用用途としても今回のような動画ファイルから音声を翻訳するのではなく、リアルタイムに音声を翻訳できると効果的だと思いました。