長い音声ファイルの文字変換

このページでは、非同期音声認識を使用して、長い音声ファイル(1 分以上)をテキストに変換する方法について説明します。

非同期音声認識では、音声処理オペレーションの長時間実行が開始されます。60 秒を超える音声を文字起こしするには、非同期音声認識を使用します。短い音声の場合は、同期音声認識を使用したほうが早くて簡単です。

音声コンテンツをローカル ファイルから Speech-to-Text に直接送信し、非同期処理を行うことができます。ただし、ローカル ファイルの音声時間制限は 60 秒です。60 秒を超えるローカル音声ファイルを音声文字変換しようとすると、エラーが発生します。60 秒を超える音声を文字変換するには、データを Google Cloud Storage バケットに保存する必要があります。

オペレーションの結果は、google.longrunning.Operations メソッドを使用して取得できます。結果が残されて取得可能な期間は、5 日間(120 時間)です。Google Cloud Storage バケットに結果を直接アップロードすることもできます。

Google Cloud Storage ファイルを使用した長い音声ファイルの文字変換

次のサンプルでは、長時間の音声文字変換処理用の生の音声入力データを格納するために、Cloud Storage バケットを使用しています。 一般的な longrunningrecognize オペレーション レスポンスの例については、リファレンス ドキュメントをご覧ください。

プロトコル

詳細については、speech:longrunningrecognize API エンドポイントをご覧ください。

同期音声認識を実行するには、POST リクエストを作成し、適切なリクエスト本文を指定します。次は、curl を使用した POST リクエストの例です。この例では、Google Cloud Cloud SDK を使用して、プロジェクト用に設定されたサービス アカウントのアクセス トークンを扱います。Cloud SDK のインストール、サービス アカウントがあるプロジェクトの設定、アクセス トークンの取得などの手順については、クイックスタートをご覧ください。

curl -X POST \
     -H "Authorization: Bearer "$(gcloud auth application-default print-access-token) \
     -H "Content-Type: application/json; charset=utf-8" \
     --data "{
  'config': {
    'language_code': 'en-US'
  },
  'audio':{
    'uri':'gs://gcs-test-data/vr.flac'
  }
}" "https://speech.googleapis.com/v1/speech:longrunningrecognize"

リクエスト本文の構成について詳しくは、RecognitionConfigRecognitionAudio のリファレンス ドキュメントをご覧ください。

リクエストが成功すると、サーバーは 200 OK HTTP ステータス コードと JSON 形式のレスポンスを返します。

{
  "name": "7612202767953098924"
}

ここで、name はリクエストに対して作成された長時間実行オペレーションの名前です。

処理が完了するまで待ちます。処理時間はソース音声によって異なります。ほとんどの場合、ソース音声の半分の時間で結果が得られます。長時間実行オペレーションのステータスは、https://speech.googleapis.com/v1/operations/ エンドポイントにGET リクエストを行うことによって取得できます。your-operation-namelongrunningrecognize リクエストから返された name に置き換えます。

curl -H "Authorization: Bearer "$(gcloud auth application-default print-access-token) \
     -H "Content-Type: application/json; charset=utf-8" \
     "https://speech.googleapis.com/v1/operations/your-operation-name"

リクエストが成功すると、サーバーは 200 OK HTTP ステータス コードと JSON 形式のレスポンスを返します。

{
  "name": "7612202767953098924",
  "metadata": {
    "@type": "type.googleapis.com/google.cloud.speech.v1.LongRunningRecognizeMetadata",
    "progressPercent": 100,
    "startTime": "2017-07-20T16:36:55.033650Z",
    "lastUpdateTime": "2017-07-20T16:37:17.158630Z"
  },
  "done": true,
  "response": {
    "@type": "type.googleapis.com/google.cloud.speech.v1.LongRunningRecognizeResponse",
    "results": [
      {
        "alternatives": [
          {
            "transcript": "okay so what am I doing here...(etc)...",
            "confidence": 0.96096134,
          }
        ]
      },
      {
        "alternatives": [
          {
            ...
          }
        ]
      }
    ]
  }
}

オペレーションが完了していない場合は、レスポンスの done プロパティが true になるまで GET リクエストを繰り返し行うことにより、エンドポイントをポーリングできます。

gcloud

詳しくは、recognize-long-running コマンドをご覧ください。

非同期音声認識を行うには、gcloud コマンドライン ツールを使用し、そこにローカル ファイルまたは Google Cloud Storage URL のパスを指定します。

gcloud ml speech recognize-long-running \
    'gs://cloud-samples-tests/speech/brooklyn.flac' \
     --language-code='en-US' --async

リクエストが成功すると、サーバーは長時間実行オペレーションの ID を JSON 形式で返します。

{
  "name": OPERATION_ID
}

次のコマンドを実行すると、オペレーションに関する情報を取得できます。

gcloud ml speech operations describe OPERATION_ID

また、次のコマンドを実行して、オペレーションが完了するまでオペレーションをポーリングすることもできます。

gcloud ml speech operations wait OPERATION_ID

オペレーションが完了すると、音声の文字起こしが JSON 形式で返されます。

{
  "@type": "type.googleapis.com/google.cloud.speech.v1.LongRunningRecognizeResponse",
  "results": [
    {
      "alternatives": [
        {
          "confidence": 0.9840146,
          "transcript": "how old is the Brooklyn Bridge"
        }
      ]
    }
  ]
}

Go


func sendGCS(w io.Writer, client *speech.Client, gcsURI string) error {
	ctx := context.Background()

	// Send the contents of the audio file with the encoding and
	// and sample rate information to be transcripted.
	req := &speechpb.LongRunningRecognizeRequest{
		Config: &speechpb.RecognitionConfig{
			Encoding:        speechpb.RecognitionConfig_LINEAR16,
			SampleRateHertz: 16000,
			LanguageCode:    "en-US",
		},
		Audio: &speechpb.RecognitionAudio{
			AudioSource: &speechpb.RecognitionAudio_Uri{Uri: gcsURI},
		},
	}

	op, err := client.LongRunningRecognize(ctx, req)
	if err != nil {
		return err
	}
	resp, err := op.Wait(ctx)
	if err != nil {
		return err
	}

	// Print the results.
	for _, result := range resp.Results {
		for _, alt := range result.Alternatives {
			fmt.Fprintf(w, "\"%v\" (confidence=%3f)\n", alt.Transcript, alt.Confidence)
		}
	}
	return nil
}

Java

/**
 * Performs non-blocking speech recognition on remote FLAC file and prints the transcription.
 *
 * @param gcsUri the path to the remote LINEAR16 audio file to transcribe.
 */
public static void asyncRecognizeGcs(String gcsUri) throws Exception {
  // Instantiates a client with GOOGLE_APPLICATION_CREDENTIALS
  try (SpeechClient speech = SpeechClient.create()) {

    // Configure remote file request for FLAC
    RecognitionConfig config =
        RecognitionConfig.newBuilder()
            .setEncoding(AudioEncoding.FLAC)
            .setLanguageCode("en-US")
            .setSampleRateHertz(16000)
            .build();
    RecognitionAudio audio = RecognitionAudio.newBuilder().setUri(gcsUri).build();

    // Use non-blocking call for getting file transcription
    OperationFuture<LongRunningRecognizeResponse, LongRunningRecognizeMetadata> response =
        speech.longRunningRecognizeAsync(config, audio);
    while (!response.isDone()) {
      System.out.println("Waiting for response...");
      Thread.sleep(10000);
    }

    List<SpeechRecognitionResult> results = response.get().getResultsList();

    for (SpeechRecognitionResult result : results) {
      // There can be several alternative transcripts for a given chunk of speech. Just use the
      // first (most likely) one here.
      SpeechRecognitionAlternative alternative = result.getAlternativesList().get(0);
      System.out.printf("Transcription: %s\n", alternative.getTranscript());
    }
  }
}

Node.js

// Imports the Google Cloud client library
const speech = require('@google-cloud/speech');

// Creates a client
const client = new speech.SpeechClient();

/**
 * TODO(developer): Uncomment the following lines before running the sample.
 */
// const gcsUri = 'gs://my-bucket/audio.raw';
// const encoding = 'Encoding of the audio file, e.g. LINEAR16';
// const sampleRateHertz = 16000;
// const languageCode = 'BCP-47 language code, e.g. en-US';

const config = {
  encoding: encoding,
  sampleRateHertz: sampleRateHertz,
  languageCode: languageCode,
};

const audio = {
  uri: gcsUri,
};

const request = {
  config: config,
  audio: audio,
};

// Detects speech in the audio file. This creates a recognition job that you
// can wait for now, or get its result later.
const [operation] = await client.longRunningRecognize(request);
// Get a Promise representation of the final result of the job
const [response] = await operation.promise();
const transcription = response.results
  .map(result => result.alternatives[0].transcript)
  .join('\n');
console.log(`Transcription: ${transcription}`);

Python

def transcribe_gcs(gcs_uri):
    """Asynchronously transcribes the audio file specified by the gcs_uri."""
    from google.cloud import speech

    client = speech.SpeechClient()

    audio = speech.RecognitionAudio(uri=gcs_uri)
    config = speech.RecognitionConfig(
        encoding=speech.RecognitionConfig.AudioEncoding.FLAC,
        sample_rate_hertz=16000,
        language_code="en-US",
    )

    operation = client.long_running_recognize(config=config, audio=audio)

    print("Waiting for operation to complete...")
    response = operation.result(timeout=90)

    # Each result is for a consecutive portion of the audio. Iterate through
    # them to get the transcripts for the entire audio file.
    for result in response.results:
        # The first alternative is the most likely one for this portion.
        print(u"Transcript: {}".format(result.alternatives[0].transcript))
        print("Confidence: {}".format(result.alternatives[0].confidence))

その他の言語

C#: クライアント ライブラリ ページの C# の設定手順を実行してから、.NET の Speech-to-Text のリファレンス ドキュメントをご覧ください。

PHP: クライアント ライブラリ ページの PHP の設定手順を実行してから、PHP の Speech-to-Text のリファレンス ドキュメントをご覧ください。

Ruby: クライアント ライブラリ ページの Ruby の設定手順を実行してから、Ruby の Speech-to-Text のリファレンス ドキュメントをご覧ください。

音声文字変換の結果を Cloud Storage バケットにアップロードする

Speech-to-Text では、長時間にわたる認識結果を Cloud Storage バケットに直接アップロードできます。この機能を Cloud Storage トリガーで実装すると、Cloud Storage アップロードで Cloud Functions を呼び出す通知がトリガーされ、Speech-to-Text にポーリングして認識結果を返す必要がなくなります。

結果を Cloud Storage バケットにアップロードするには、長時間実行の認識リクエストでオプションの TranscriptOutputConfig 出力構成を指定します。

  message TranscriptOutputConfig {

    oneof output_type {
      // Specifies a Cloud Storage URI for the recognition results. Must be
      // specified in the format: `gs://bucket_name/object_name`
      string gcs_uri = 1;
    }
  }

プロトコル

詳細については、longrunningrecognize API エンドポイントをご覧ください。

次の例は、curl を使用して POST リクエストを送信する方法を示しています。ここでは、リクエストの本文で Cloud Storage バケットへのパスを指定しています。結果は、SpeechRecognitionResult を格納する JSON ファイルとしてアップロードされます。

curl -X POST \
     -H "Authorization: Bearer $(gcloud auth application-default print-access-token)" \
     -H "Content-Type: application/json; charset=utf-8" \
     --data "{
  'config': {...},
  'output_config': {
     'gcs_uri':'gs://bucket/result-output-path.json'
  },
  'audio': {
    'uri': 'gs://bucket/audio-path'
  }
}" "https://speech.googleapis.com/v1p1beta1/speech:longrunningrecognize"

LongRunningRecognizeResponse には、アップロードを試みた Cloud Storage バケットへのパスが含まれます。アップロードが失敗した場合、出力エラーが返されます。同じ名前のファイルがすでに存在する場合、アップロードは、タイムスタンプを接尾辞として付加した新しいファイルに結果を書き込みます。

{
  ...
  "metadata": {
    ...
    "outputConfig": {...}
  },
  ...
  "response": {
    ...
    "results": [...],
    "outputConfig": {
      "gcs_uri":"gs://bucket/result-output-path"
    },
    "outputError": {...}
  }
}

使ってみる

Google Cloud を初めて使用する場合は、アカウントを作成して、実際のシナリオでの Speech-to-Text のパフォーマンスを評価します。新規のお客様には、ワークロードの実行、テスト、デプロイに使用できる無料クレジット $300 分を差し上げます。

Speech-to-Text の無料トライアル