処理の大枠、データの流れ

  1. ブラウザ(フロント) から /api/transcribe/upload にファイルが送信される。
  2. Expressサーバー がファイルを受け取り、S3 にアップロードする。
  3. AWS Transcribe に文字起こしジョブ(TranscriptionJob)を開始依頼。
  4. ジョブが完了すると、文字起こし結果JSONが S3 に保存される。
  5. /api/transcribe/status?jobName=xxx でジョブのステータスを確認。
  6. ジョブ完了後、S3からJSONを取得して、加工・整形してレスポンスする。

AWS SDK for Node.js の利用方法

SDKのセットアップ

  • AWS SDKのインストールと設定: AWS SDK for JavaScript (Node.js) をプロジェクトに導入します。
  • AWS認証情報(アクセスキーIDとシークレット、リージョン設定など)を環境変数や設定ファイルで用意します​docs.aws.amazon.com
  • AWSを操作する前に、AWSアカウントで適切なIAMユーザ/ロールと権限を設定しておきます。

インフラ担当者への権限付与の依頼

【目的】
音声ファイルのアップロードから文字起こし、AI分析までを行うアプリケーションの開発

【必要な権限】
1. AmazonS3FullAccess
   - 用途:音声ファイルの保存、文字起こし結果の取得
   
2. AmazonTranscribeFullAccess
   - 用途:音声の文字起こし処理

3. BedrockFullAccess
   - 用途:文字起こしされたテキストのAI分析

【対象ユーザー/ロール】
- ユーザー名:[開発用IAMユーザー名]

Transcribe API の使い方

  • クライアントの初期化: AWS SDKを読み込み、リージョンを設定してクライアントを初期化します。
// Transcribeクライアントの初期化
const transcribeClient = new TranscribeClient({
    region: process.env.AWS_REGION || 'ap-northeast-1',
    credentials: {
        accessKeyId: process.env.AWS_ACCESS_KEY_ID,
        secretAccessKey: process.env.AWS_SECRET_ACCESS_KEY,
    }
});

非同期バッチ処理とリアルタイム処理の比較

項目非同期バッチ処理リアルタイム処理
概要データをまとめて一括処理する受け取ったデータを即座に処理する
処理タイミングスケジュール(例:1時間ごと、夜間まとめて)イベント発生時すぐ
レスポンス速度遅い(まとめて処理するので、待ち時間あり)速い(即応)
使う場面大量データ処理、コスト重視、少し遅れてもいい場合チャット、株取引、ゲーム、即応性が命な場面
コスト安い(まとめ処理できるため効率良い)高い(常時稼働、インフラも強めが必要)
実装難易度低~中(処理後にまとめてレスポンス)高(並列処理、スケーラビリティ考慮が必要)
毎晩のデータ集計、ログ解析、請求バッチWebSocketチャット、ライブストリーミング、リアルタイム通知
AWSで例えるとAWS Batch, AWS Glue, S3 + LambdaAmazon API Gateway + Lambda, AWS Kinesis, WebSocket API

バッチジョブについて

▼ バッチ処理モードのAmazon Transcribeを使う場合の典型的な処理の流れ

AWS SDK による文字起こし実装フロー AWS SDK初期化 const AWS = require(‘aws-sdk’); AWS.config.update({ region: ‘ap-northeast-1’ }); S3への音声ファイルアップロード const s3 = new AWS.S3(); const uploadParams = { Bucket: bucketName, Key: keyName, Body: fileContent }; s3.upload(uploadParams, callback); Transcribeジョブ開始 const transcribe = new AWS.TranscribeService(); const params = { TranscriptionJobName: ‘MyJob’, LanguageCode: ‘ja-JP’, Media: { MediaFileUri: `s3://${bucketName}/${keyName}` }, Subtitles: { Formats: [‘srt’] } ジョブ完了後、S3から結果JSONと字幕ファイルを取得して処理

docs.aws.amazon.com

const AWS = require('aws-sdk');
const fs = require('fs');
AWS.config.update({ region: 'ap-northeast-1' });              // リージョン設定
const s3 = new AWS.S3();
const transcribe = new AWS.TranscribeService();

// 1. S3に音声ファイルをアップロード
const filePath = 'audio.wav';                                 // ローカルの音声ファイル
const bucketName = 'my-audio-bucket';                         // アップロード先S3バケット
const keyName = 'uploads/audio.wav';                          // S3上での保存キー
const fileContent = fs.readFileSync(filePath);
const uploadParams = { Bucket: bucketName, Key: keyName, Body: fileContent };
s3.upload(uploadParams, (err, data) => {
  if (err) {
    console.error('S3 Upload Error:', err);
    return;
  }
  console.log('S3 Upload Success:', data.Location);

  // 2. アップロードしたファイルを指定してTranscribeジョブを開始
  const jobName = 'example-transcription-job';
  const params = {
    TranscriptionJobName: jobName,
    LanguageCode: 'ja-JP',
    MediaFormat: 'wav',
    Media: { MediaFileUri: `s3://${bucketName}/${keyName}` },
    OutputBucketName: bucketName // 結果も同じバケットに保存
  };
  transcribe.startTranscriptionJob(params, (err, data) => {
    if (err) {
      console.error('Transcribe Error:', err);
    } else {
      console.log('Transcription Job started:', data.TranscriptionJob.TranscriptionJobName);
    }
  });
});
  • 上記コードでは、audio.wavファイルを指定のS3バケットにアップロードし、アップロード完了後にそのファイルを入力として文字起こしジョブを開始しています。実際の運用では、ジョブ開始後にgetTranscriptionJobでジョブのステータスを確認し、完了したら結果を取得するといった処理も必要です。

S3 の使用について

音声ファイルの保存・取得(一般的なユースケース)

  • 音声データの保存: 音声ファイルはAmazon S3に保存して扱うのが一般的です。Amazon Transcribeのバッチ処理では、対象の音声をS3バケット上のオブジェクトとして入力に指定します​docs.aws.amazon.com。アプリケーションから音声データを受け取ったら、まずS3バケットにそのファイルを保存します。上記のサンプルコードのようにAWS SDK経由でputObjectuploadメソッドを使ってプログラム的にアップロードできます​docs.aws.amazon.com
  • 音声データの取得: 音声ファイルを使用して文字起こしを行う際、Transcribeサービス自体がS3からファイルを読み取ります。アプリケーション側では、一度アップロードしてしまえば、あとはTranscribeにそのS3 URIを渡すだけで文字起こしが実行されます。また、Transcribeの出力結果(JSONや字幕ファイル)がS3に保存された場合、それをgetObjectで取得したり、S3コンソールやHTTP(S)経由でダウンロードしたりできます。
AWS Transcribe 文字起こしの基本フロー アプリケーション S3バケット (入力) AWS Transcribe S3バケット (出力) JSONまたは字幕 1. 音声ファイルアップロード 2. ジョブ開始 (startTranscriptionJob) 3. 処理結果保存 4. 結果取得 制限事項 ・最大4時間/2GBの音声ファイル ・対応フォーマット: MP3, MP4, WAV等

バケットの構成と権限(推奨設定)

  • バケット構成: 音声入力用と文字起こし結果用にバケットやプレフィックスを分けて管理すると整理しやすくなります。例えば、my-audio-bucket/uploads/に音声ファイル、my-audio-bucket/transcripts/に結果JSONを保存する、といった構成です。また、Transcribeジョブを実行するリージョンと音声ファイルが存在するリージョンを一致させることを推奨します。リージョンが異なるとジョブ作成時にエラーとなる場合があるため、基本的には同一リージョン内で完結させます。
  • アクセス権限: S3バケットおよびオブジェクトには適切なIAMポリシーやバケットポリシーを設定し、必要最小限のアクセス権を付与します。文字起こしを行うIAMユーザ/ロールには、対象バケットに対するGetObject権限(入力音声の読み取り)とPutObject権限(出力結果の書き込み)を与えてください​docs.aws.amazon.com。特に、OutputBucketNameに自分のバケットを指定する場合は、Amazon Transcribeにそのバケットへの書き込み権限を事前に付与しておく必要があります​docs.aws.amazon.com。これはIAMロールを使用する場合、信頼ポリシーでTranscribeサービス(transcribe.amazonaws.com)を信頼し、S3アクセス権を持つロールを指定する方法などで実現できます。
  • バケットの公開設定: バケットやオブジェクトは原則非公開とし、必要に応じて一時的な署名付きURL(Presigned URL)を使って限定的にアクセスさせるのが安全です。誤ってバケットをpublicに開放することはセキュリティ上避けましょう。また、不要になったファイルはライフサイクルルールで自動削除するなど、保管期間を決めて運用するとストレージコスト管理に役立ちます。

制限事項

AWS Transcribe の制限

  • ファイル長・サイズ: Amazon Transcribeのバッチ処理では、1回のAPI呼び出しあたり最長4時間または最大2GBまでの音声ファイルしか処理できません​aws.amazon.com。4時間を超える長時間の音声や2GBを超える大容量ファイルはそのままでは処理できないため、必要に応じて音声を分割するなどの対策が必要です。
  • 入力フォーマットの制限: 入力できる音声ファイルの形式も限定されています。対応フォーマットは例えばMP3、MP4(M4A)、WebM、WAV(リニアPCM)、FLAC、Ogg(Ogg Opusを含む)、AMR などです​dev.classmethod.jpdocs.aws.amazon.com。動画ファイル(MP4やWebM)の場合も、その中の音声トラックが文字起こしの対象になります。またサンプルレートは8,000 Hz(電話音質)から48,000 Hz(高音質)まで対応し、**音声チャンネルは1チャンネル(モノラル)または2チャンネル(ステレオ)**までサポートされています。3チャンネル以上の音源は事前にミックスダウンしておく必要があります。
  • 出力に関する制限: 文字起こし結果は通常JSONで提供されますが、Amazon Transcribe側でジョブの情報を保持している期間は90日間です​docs.aws.amazon.com。デフォルトでは、ジョブ完了後90日が経過すると(サービス管理のバケット上に置かれた)トランスクリプトデータは削除されます。自分のS3バケットに出力を保存していれば消えずに残りますが、サービス側ではジョブ履歴が90日で消える点に注意が必要です。

S3 に関する制限

  • オブジェクトのサイズ: Amazon S3に保存できる1ファイル(オブジェクト)のサイズは最大5TBです​aws.amazon.com。非常に大きなファイルも扱えますが、1回のPUT操作でアップロードできるオブジェクトは最大5GBまでという別の制限があります​aws.amazon.com。5GBを超える場合はマルチパートアップロード(分割アップロード)機能を使ってアップロードする必要があります​aws.amazon.com。なお、AWS SDKのuploadメソッドは内部で一定サイズ以上のファイルを自動的にマルチパートに分割して送信するため、大容量ファイルでも透過的にアップロード可能です。
  • ストレージ容量: S3全体としての保存容量やバケット内のオブジェクト数に上限はありません。合計ストレージは無制限に利用できます​aws.amazon.com(使用量に応じた課金となります)。したがって、音声ファイルや文字起こし結果が増加しても、S3の容量面で制約となることは基本的にありません。
  • バケット数: S3バケットの作成数にはAWSアカウントごとにサービスクォータ(上限)が設定されています。2023年現在、デフォルトで1アカウントあたり最大1万個のバケットを作成可能です​docs.aws.amazon.com(以前は100個まででしたが、AWSにより上限が引き上げられました​tekton.cloud)。通常のアプリケーションでそこまで大量のバケットを使うことは稀ですが、必要に応じてAWSサポートへの依頼で上限緩和も可能です。

タイムスタンプ付きや話者ラベル付きの出力方法

出力されるJSONの形式は下記のとおりです

{
  "jobName": "transcribe-1745644213169",
  "accountId": "855020928922",
  "status": "COMPLETED",
  "results": {
    "transcripts": [
      { "transcript": "全文(ただし区切りなし)" }
    ],
    "speaker_labels": {
      "speakers": 2,
      "segments": [
        {
          "start_time": "0.56",
          "end_time": "17.629",
          "speaker_label": "spk_0",
          "items": [ { "start_time": ..., "end_time": ..., "speaker_label": "spk_0" }, ... ]
        },
        ...
      ]
    },
    "items": [
      {
        "type": "pronunciation" または "punctuation",
        "alternatives": [
          { "content": "発話された言葉", "confidence": "確信度" }
        ],
        "start_time": "開始秒",
        "end_time": "終了秒",
        "speaker_label": "話者ラベル"
      },
      ...
    ],
    "audio_segments": [
      {
        "id": 0,
        "transcript": "まとまった発言内容",
        "start_time": "0.56",
        "end_time": "17.629",
        "speaker_label": "spk_0",
        "items": [ 0, 1, 2, ... ] // itemsのインデックス
      },
      ...
    ]
  }
}
パート名説明
jobNameジョブを一意に識別するID(だいたいtranscribe-タイムスタンプみたいな形)
statusジョブのステータス(COMPLETED / IN_PROGRESS / FAILED)
results.transcriptsただ全文をベタっとまとめたもの(区切りなし・話者区別なし)
results.speaker_labels発話ごとの時間範囲+話者ラベル(例:spk_0, spk_1など)
results.items実際に聞き取った単語(または句読点)リスト、confidence付き
results.audio_segmentsまとまった単位の発言(だいたい話者&時間帯ベースでまとめられてる)
  • 出力フォーマット: Amazon Transcribeの文字起こし結果はJSON形式で提供されます​docs.aws.amazon.com。JSONには、全文テキスト(transcriptsセクション)と、単語ごとの詳細情報(itemsセクション)が含まれています​docs.aws.amazon.com。各単語の開始時刻(start_time)、終了時刻(end_time)、認識された単語(content)と信頼度(confidence)などのデータが含まれており、タイムスタンプに基づいて音声中のどの位置でその単語が発せられたかが分かります​docs.aws.amazon.com
  • タイムスタンプ情報の活用: 取得したJSONを解析することで、文字起こしテキストを時間情報付きで表示したり、字幕を生成したりできます。例えば、Node.js上でJSON文字列を読み込み各単語に対して開始時間とテキストを出力する処理は以下のように実装できます:
const transcriptData = JSON.parse(transcriptJsonString);
for (const item of transcriptData.results.items) {
  if (item.type === 'pronunciation') {
    const startSec = parseFloat(item.start_time);
    const word = item.alternatives[0].content;
    console.log(`${startSec}s: ${word}`);
  }
}

このようにして各単語の開始秒数と内容を出力できます。応用すれば所定のフォーマットに整形して字幕ファイル(例えばSRT形式)を生成することも可能です。items内でtypepronunciationの要素が実際の発話単語で、punctuationの要素は句読点なので、これらを組み合わせて元の文章を再現します。タイムスタンプ情報を利用することで、映像と同期したテロップ表示や、クリック時にその時間に音声をジャンプする機能など、さまざまなインタラクションを実現できます。字幕ファイルとしての出力: Amazon Transcribeは結果JSONだけでなく、**タイムスタンプ付きの字幕ファイル(WebVTTやSRT形式)**を直接出力することも可能です​

AWS Transcribe 出力結果と時間情報の活用 JSON出力形式 { “results”: { “transcripts”: [ { “transcript”: “こんにちは。今日の会議についてお話します。” } ], “items”: [ { “start_time”: “0.0”, “end_time”: “0.68”, “alternatives”: [ { “confidence”: “0.9925”, “content”: “こんにちは” } ], “type”: “pronunciation” }, … } タイムスタンプ情報の活用 SRTファイル例 1 00:00:00,000 –> 00:00:00,680 こんにちは タイムスタンプ処理例 (Node.js) const data = JSON.parse(transcriptJsonString); for (const item of data.results.items) { if (item.type === ‘pronunciation’) { const startSec = parseFloat(item.start_time); const word = item.alternatives[0].content; console.log(`${startSec}s: ${word}`); } } 文字起こし結果を使って動画字幕、テロップ表示、 タイムライン作成などへ応用可能

docs.aws.amazon.com。ジョブのリクエストパラメータでSubtitlesオプションを指定し、例としてFormats: ['srt']と設定すると、自動的にS3に字幕ファイル(.srt形式)が保存されます。例えば先述のStartTranscriptionJobのパラメータに:

Subtitles: { Formats: ['srt'] }
  • を追加すると、ジョブ完了時に <TranscriptionJobName>.srt というファイルが結果バケットに出力され、各発話に対応した開始・終了時刻付きの字幕テキストが得られます。必要に応じてこの機能も活用すると良いでしょう。

以上、AWS SDKを用いたAmazon Transcribe実装のポイントを整理しました。S3を介した音声ファイルの管理やTranscribeサービスの制限を踏まえ、適切に設計・実装することで、音声の文字起こしアプリケーションを効率的に構築できます。

docs.aws.amazon.com「プロジェクト環境のセットアップ(SDKのインストールなど)と共有設定ファイルによる認証情報の配置」が必要です。また、SDK利用前にこれらの準備を完了させます。

docs.aws.amazon.comAWS SDK for JavaScript(v3)のコード例。StartTranscriptionJobCommandに渡すパラメータとして、ジョブ名、言語コード、メディアフォーマット、メディアファイルのS3 URI、および出力バケット名を設定しています。

docs.aws.amazon.comAWS SDK for JavaScript(v2)での設定例。require('aws-sdk')でSDKを読み込み、AWS.config.update({ region: "リージョン" })でリージョンを設定してからサービスオブジェクトを生成します。

docs.aws.amazon.comAWS SDKを使ったS3ファイルアップロードのコード例。s3.upload(params, ...);でファイルをアップロードし、コールバック内で結果を処理しています。

docs.aws.amazon.com「Amazon Transcribe は、音声データを Amazon S3 バケット内のファイルとして受け取りテキストに変換します。S3に保存されたメディアファイルを文字起こしする場合、バッチ文字起こしを実行します。」

docs.aws.amazon.com「自分の所有する Amazon S3 バケットにトランスクリプトを保存する場合は、文字起こしリクエストでバケットのURIを指定します。バッチ文字起こしジョブを開始する前に、必ずこのバケットのAmazon Transcribe書き込みアクセス許可を付与してください。」とあり、Transcribeに出力先バケットへの書き込み権限を与える必要が述べられています。

aws.amazon.com「Amazon Transcribe のサービス呼び出しは、バッチサービスの API コール 1 回につき 4 時間 (あるいは 2 GB) に制限されます。」と記載されています。

dev.classmethod.jp「Amazon Transcribeの場合、音声時間は最大4時間、サイズは最大2GBまでです。また、対応しているファイル形式は、mp3、mp4、webm、wav、amr、flac、oggです。」とあり、Transcribeの時間・サイズ制限と対応フォーマットが示されています。

docs.aws.amazon.comデベロッパーガイドに記載の対応メディア形式一覧。バッチ文字起こしでAMR、FLAC、M4A、MP3、MP4、Ogg、WebM、WAV形式がサポートされています。

docs.aws.amazon.com「Amazon S3 バケットを指定しない場合、Transcribeはサービスマネージドバケットを使用し、一時的なダウンロードURIを提供します。一時URIは15分間有効です… デフォルトバケットを選択した場合、ジョブの有効期限(90日)になると、トランスクリプトは削除されます。」と、出力の保持期間について説明されています。

aws.amazon.com「Amazon S3 に格納可能なデータの総量とオブジェクトの数には制限はありません。個別の Amazon S3 オブジェクトのサイズは、最低 0 バイトから最大 5 TB までさまざまです。1 つの PUT にアップロード可能なオブジェクトの最大サイズは 5 GB です。100 MB を超えるオブジェクトの場合は、マルチパートアップロード機能を使うことをお考えください。」と、S3オブジェクトサイズの上限が示されています。

docs.aws.amazon.comS3ユーザーガイドのバケットクォータに「デフォルトでAWSアカウントあたり1万個のバケットを作成可能」と記載されています。

tekton.cloudAWSのアップデート情報。「AWSはS3バケット作成上限を従来の100個から1000個に増加しました」と解説されています(現在はさらに上限が引き上げられていますが、過去との比較として参考)。

docs.aws.amazon.com「文字起こし出力は JSON形式です。トランスクリプトの最初の部分には段落形式の全文が含まれ、その後に単語ごとの開始時間、終了時間、信頼スコアなどの追加データが続きます。」と、出力JSONにタイムスタンプが含まれることが説明されています。

docs.aws.amazon.com文字起こし出力JSONの例の説明。「基本的なバッチ文字起こし結果はtranscripts(全文)とitems(単語ごとのデータ)の2つの主要部分から構成されます」と述べられています。

docs.aws.amazon.com「Subtitlesオプションを指定すると入力メディア用の字幕ファイルを生成します。WebVTT(.vtt)とSubRip(.srt)形式を指定できます。」と、字幕出力機能について記載があります。