メディア レスポンス

メディア レスポンスを使用すると、アクションは、SSML の 240 秒の制限を超える再生時間で音声コンテンツを再生できます。メディア レスポンスは、音声のみのデバイスと、ビジュアル コンテンツを表示できるデバイスの両方で機能します。ディスプレイでは、メディア レスポンスは、メディア コントロールおよび(必要に応じて)静止画像を含む視覚コンポーネントとともに表示されます。

メディア レスポンスを定義する場合は、Google アシスタントがサポートされているデバイスでのみリッチ レスポンスを返すように、RICH_RESPONSELONG_FORM_AUDIO の両方のサーフェス機能を持つ候補を使用します。リッチ レスポンスは、プロンプト内の content オブジェクトごとに 1 つだけ使用できます。

再生する音声は、正しい形式の MP3 ファイルである必要があります。MP3 ファイルは、ウェブサーバーでホストし、HTTPS URL で一般公開する必要があります。ライブ ストリーミングは MP3 形式でのみサポートされています。

スマートディスプレイのメディア レスポンスの例
図 1. スマートディスプレイのメディア レスポンスの例

動作

スマートフォンに表示されたメディア レスポンスの例
図 2. スマートフォンのメディア レスポンスの例

メディア レスポンスの主なコンポーネントは単一トラックカードです。このカードを使用すると、ユーザーは次のことができます。

  • 最後の 10 秒を再生
  • 30 秒早送り
  • メディア コンテンツの全長を表示する
  • メディア再生の進行状況インジケーターを確認する
  • 経過時間を確認する

メディア レスポンスは、音声操作で次の音声コントロールをサポートしています。これらはすべて Google アシスタントによって処理されます。

  • 「OK Google, 再生して」
  • 「OK Google, 一時停止して」
  • 「OK Google, 止めて」
  • 「OK Google, 最初からやり直して」

「OK Google, 音量を上げて」や「OK Google, 音量を 50% に設定して」などと話しかけて音量を調整することもできます。アクション内のインテントは、類似のトレーニング フレーズを処理する場合、優先されます。アクションに特別な理由がない限り、アシスタントはこのようなユーザー リクエストを処理できるようにします。

Android スマートフォンでの動作

Android スマートフォンでは、スマートフォンがロックされているときもメディア コントロールを使用できます。 メディア コントロールも通知領域に表示され、次のいずれかの条件が満たされると、ユーザーはメディア レスポンスを確認できます。

  • Google アシスタントがフォアグラウンドで動作していて、スマートフォンの画面がオンになっている。
  • ユーザーが音声の再生中に Google アシスタントから離れ、再生が完了してから 10 分以内に Google アシスタントに戻った。Google アシスタントに戻ると、メディアカードと候補ワードが表示されます。

プロパティ

メディア レスポンスには次の特性があります。

プロパティ 種類 必須 / 任意 説明
media_type MediaType 必須 提供されたレスポンスのメディアタイプ。メディア ステータスを確認応答する場合は、MEDIA_STATUS_ACK を返します。
start_offset string 任意 最初のメディア トラックを開始する位置を移動します。値は秒単位で指定します。小数点以下の秒数は小数第 9 位以下で表し、末尾は接尾辞「s」にします。たとえば、3 秒と 1 ナノ秒は「3.000000001s」と表されます。
optional_media_controls OptionalMediaControls の配列 任意 ユーザーがメディア再生ステータスを変更(メディア再生の一時停止や停止など)したときにコールバックを受け取るオプトイン プロパティ。
media_objects MediaObject の配列 必須 プロンプトに含めるメディア オブジェクトを表します。MEDIA_STATUS_ACK でメディア ステータスを確認する場合は、メディア オブジェクトを指定しないでください。
first_media_object_index 整数 任意 media_objects 内で再生する最初の MediaObject の 0 ベースのインデックス。指定されていない場合、ゼロまたは境界外の場合、最初の MediaObject から再生が開始されます。
repeat_mode RepeatMode 任意 メディア オブジェクトのリストを繰り返し表示するためのモードです。

サンプルコード

YAML

candidates:
  - first_simple:
      variants:
        - speech: This is a media response.
    content:
      media:
        start_offset: 2.12345s
        optional_media_controls:
          - PAUSED
          - STOPPED
        media_objects:
          - name: Media name
            description: Media description
            url: 'https://storage.googleapis.com/automotive-media/Jazz_In_Paris.mp3'
            image:
              large:
                url: 'https://storage.googleapis.com/automotive-media/album_art.jpg'
                alt: Jazz in Paris album art
        media_type: AUDIO

JSON

{
  "candidates": [
    {
      "first_simple": {
        "variants": [
          {
            "speech": "This is a media response."
          }
        ]
      },
      "content": {
        "media": {
          "start_offset": "2.12345s",
          "optional_media_controls": [
            "PAUSED",
            "STOPPED"
          ],
          "media_objects": [
            {
              "name": "Media name",
              "description": "Media description",
              "url": "https://storage.googleapis.com/automotive-media/Jazz_In_Paris.mp3",
              "image": {
                "large": {
                  "url": "https://storage.googleapis.com/automotive-media/album_art.jpg",
                  "alt": "Jazz in Paris album art"
                }
              }
            }
          ],
          "media_type": "AUDIO"
        }
      }
    }
  ]
}

Node.js

// Media response
app.handle('media', (conv) => {
  conv.add('This is a media response');
  conv.add(new Media({
    mediaObjects: [
      {
        name: 'Media name',
        description: 'Media description',
        url: 'https://storage.googleapis.com/automotive-media/Jazz_In_Paris.mp3',
        image: {
          large: JAZZ_IN_PARIS_IMAGE,
        }
      }
    ],
    mediaType: 'AUDIO',
    optionalMediaControls: ['PAUSED', 'STOPPED'],
    startOffset: '2.12345s'
  }));
});

JSON

{
  "session": {
    "id": "session_id",
    "params": {},
    "languageCode": ""
  },
  "prompt": {
    "override": false,
    "content": {
      "media": {
        "mediaObjects": [
        {
          "name": "Media name",
          "description": "Media description",
          "url": "https://storage.googleapis.com/automotive-media/Jazz_In_Paris.mp3",
          "image": {
            "large": {
              "alt": "Jazz in Paris album art",
              "height": 0,
              "url": "https://storage.googleapis.com/automotive-media/album_art.jpg",
              "width": 0
            }
          }
        }
        ],
        "mediaType": "AUDIO",
        "optionalMediaControls": [
          "PAUSED",
          "STOPPED"
        ]
      }
    },
    "firstSimple": {
      "speech": "This is a media response",
      "text": "This is a media response"
    }
  }
}

メディアのステータスの受信

ユーザーのメディア再生中または再生後に、Google アシスタントはメディア ステータス イベントを生成して、アクションに再生の進行状況を通知します。これらのステータス イベントを Webhook コードで処理して、ユーザーがメディアの再生を一時停止、停止、終了したときに、適切にルーティングされるようにします。

Google アシスタントは、メディアの再生の進行状況とユーザークエリに基づいて、次のリストからステータス イベントを返します。

  • FINISHED: ユーザーがメディアの再生を完了し(または次のメディアにスキップした)、遷移が会話の終了ではない場合。このステータスは MEDIA_STATUS_FINISHED システム インテントにもマッピングされます。
  • PAUSED: ユーザーがメディアの再生を一時停止しました。optional_media_controls プロパティで、このステータス イベントの受信をオプトインします。このステータスは MEDIA_STATUS_PAUSED システム インテントにもマッピングされます。
  • STOPPED: ユーザーがメディアの再生を停止または終了しました。optional_media_controls プロパティで、このステータス イベントの受信をオプトインします。このステータスは MEDIA_STATUS_STOPPED システム インテントにもマッピングされます。
  • FAILED: メディアの再生に失敗しました。このステータスは MEDIA_STATUS_FAILED システム インテントにもマッピングされます。

メディアの再生中に、ユーザーがメディアの一時停止イベントと停止イベントの両方として解釈可能なクエリを提供する場合があります(「停止」、「キャンセル」、「終了」など)。その場合、アシスタントはアクションに actions.intent.CANCEL システム インテントを提供し、「STOPPED」ステータス値を含むメディア ステータス イベントを生成して、アクションを完全に終了します。

Google アシスタントがステータス値 PAUSED または STOPPED を含むメディア ステータス イベントを生成すると、確認応答(タイプ MEDIA_STATUS_ACK)のみを含むメディア レスポンスで応答します。

メディアの進行状況

現在のメディア再生の進行状況は、Webhook リクエストの context.media.progress フィールドで確認できます。メディアの進行状況を開始時間オフセットとして使用して、メディアの再生が終了した時点から再生を再開できます。開始時間オフセットをメディア レスポンスに適用するには、start_offset プロパティを使用します。

サンプルコード

Node.js

// Media status
app.handle('media_status', (conv) => {
  const mediaStatus = conv.intent.params.MEDIA_STATUS.resolved;
  switch(mediaStatus) {
    case 'FINISHED':
      conv.add('Media has finished playing.');
      break;
    case 'FAILED':
      conv.add('Media has failed.');
      break;
    case 'PAUSED' || 'STOPPED':
      if (conv.request.context) {
        // Persist the media progress value
        const progress = conv.request.context.media.progress;
      }
      // Acknowledge pause/stop
      conv.add(new Media({
        mediaType: 'MEDIA_STATUS_ACK'
        }));
      break;
    default:
      conv.add('Unknown media status received.');
  }
});

再生リストを返す

レスポンスに複数の音声ファイルを追加して、再生リストを作成できます。最初のトラックの再生が完了すると、次のトラックが自動的に再生されます。各トラックの再生が完了するまでは、この処理が継続されます。ユーザーは、画面上の [Next] ボタンを押すか、「Next」などと話しかけて次のトラックにスキップすることもできます。

プレイリストの最後のトラックで [次へ] ボタンが無効になります。ただし、ループモードを有効にすると、プレイリストは最初のトラックから再び再生されます。ループモードの詳細については、ループモードを実装するをご覧ください。

再生リストを作成するには、media_objects 配列に複数の MediaObject を含めます。次のコード スニペットは、3 つのトラックのプレイリストを返すプロンプトを示しています。

{
  "candidates": [
    {
      "content": {
        "media": {
          "media_objects": [
            {
              "name": "1. Jazz in Paris",
              "description": "Song 1 of 3",
              "url": "https://storage.googleapis.com/automotive-media/Jazz_In_Paris.mp3",
              "image": {
                "large": {
                  "url": "https://storage.googleapis.com/automotive-media/album_art.jpg",
                  "alt": "Album cover of an ocean view",
                  "height": 1600,
                  "width": 1056
                }
              }
            },
            {
              "name": "2. Jazz in Paris",
              "description": "Song 2 of 3",
              "url": "https://storage.googleapis.com/automotive-media/Jazz_In_Paris.mp3",
              "image": {
                "large": {
                  "url": "https://storage.googleapis.com/automotive-media/album_art.jpg",
                  "alt": "Album cover of an ocean view",
                  "height": 1600,
                  "width": 1056
                }
              }
            },
            {
              "name": "3. Jazz in Paris",
              "description": "Song 3 of 3",
              "url": "https://storage.googleapis.com/automotive-media/Jazz_In_Paris.mp3",
              "image": {
                "large": {
                  "url": "https://storage.googleapis.com/automotive-media/album_art.jpg",
                  "alt": "Album cover of an ocean view",
                  "height": 1600,
                  "width": 1056
                }
              }
            }
          ],
        }
      }
    }
  ]
}

ループモードを実装する

ループモードでは、自動的に繰り返される音声レスポンスを提供できます。このモードを使用して、単一トラックを繰り返し再生したり、プレイリストをループしたりできます。ループした 1 つのトラックに対してユーザーが「次へ」などのように言えば、曲が再び再生されます。ループ再生された再生リストの場合、ユーザーが「Next」と話しかけると、再生リストの次のトラックが開始されます。

ループモードを実装するには、プロンプトに repeat_mode フィールドを追加し、その値を ALL に設定します。この追加により、最後のメディア オブジェクトの最後に到達したときに、メディア レスポンスを最初のメディア オブジェクトの先頭までループさせることができます。

次のコード スニペットは、ループ トラックを返すプロンプトを示しています。

{
  "candidates": [
    {
      "content": {
        "media": {
          "media_objects": [
            {
              "name": "Jazz in Paris",
              "description": "Single song (repeated)",
              "url": "https://storage.googleapis.com/automotive-media/Jazz_In_Paris.mp3",
              "image": {
                "large": {
                  "url": "https://storage.googleapis.com/automotive-media/album_art.jpg",
                  "alt": "Album cover of an ocean view",
                  "height": 1600,
                  "width": 1056
                }
              }
            }
          ],
          "repeat_mode": "ALL"
        }
      }
    }
  ]
}