媒体响应

通过媒体响应,您的 Action 可以播放播放时长超过 SSML 的 240 秒限制的音频内容。媒体响应适用于纯音频设备和可以显示视觉内容的设备。在屏幕上,媒体响应随附一个具有媒体控件的可视组件和(可选)静态图片。

在定义媒体响应时,请使用同时具有 RICH_RESPONSELONG_FORM_AUDIO surface 功能的“候选”,以便 Google 助理仅在支持的设备上返回富响应。在提示中,您只能对每个 content 对象使用一个富响应。

要播放的音频必须是格式正确的 MP3 文件。MP3 文件必须托管在网络服务器上,并通过 HTTPS 网址公开提供。只有 MP3 格式支持直播。

智能显示屏上的媒体响应示例
图 1. 智能显示屏上的媒体响应示例

行为

智能手机上的媒体响应示例
图 2. 智能手机上的媒体响应示例

媒体响应的主要组件是单轨卡片。用户可以通过该卡片执行以下操作:

  • 重放最后 10 秒
  • 快进 30 秒
  • 查看媒体内容的总长度
  • 查看媒体播放的进度指示器
  • 查看已播放时长

媒体响应支持以下语音交互音频控件,所有这些控件都由 Google 助理处理:

  • “Ok Google,播放。”
  • “Ok Google,暂停。”
  • “Ok Google,停止。”
  • “Ok Google,重新开始。”

用户还可以通过说出“Hey Google,调高音量。”或“Hey Google,把音量设为 50%”这类指令来控制音量。您的 Action 中的 intent 处理类似的训练短语时,会优先执行。除非您的 Action 有特定原因,否则让 Google 助理处理这些用户请求。

Android 手机上的行为

在 Android 手机上,当手机处于锁定状态时,您也可以使用媒体控件。 媒体控件也会显示在通知区域中,只要满足以下任一条件,用户就能看到媒体回复:

  • Google 助理位于前台,手机屏幕处于开启状态。
  • 用户在音频播放期间离开 Google 助理,并在播放完成后 10 分钟内返回到 Google 助理。返回 Google 助理后,用户会看到媒体卡片和建议内容信息卡。

属性

媒体响应具有以下属性:

媒体资源 类型 要求 说明
media_type MediaType 必需 所提供响应的媒体类型。确认媒体状态时返回 MEDIA_STATUS_ACK
start_offset string 可选 跳转至第一个媒体轨道。请以秒为单位提供值,秒数的小数位不应超过九个小数位,并以后缀“s”结尾。例如,3 秒加 1 纳秒表示为“3.000000001s”。
optional_media_controls OptionalMediaControls 的数组 可选 选择启用属性,以便在用户更改其媒体播放状态(例如通过暂停或停止媒体播放)时接收回调。
media_objects MediaObject 的数组 必需 表示要在提示中包含的媒体对象。使用 MEDIA_STATUS_ACK 确认媒体状态时,请勿提供媒体对象。
first_media_object_index integer 可选 要播放的 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 助理可以生成媒体状态事件,将您的播放进度告知 Action。您可以在网络钩子代码中处理这些状态事件,以便在用户暂停、停止或结束媒体播放时正确地引导用户进行跳转。

Google 助理会根据媒体播放进度和用户查询从以下列表中返回状态事件:

  • FINISHED:用户完成了媒体播放(或跳至下一条媒体),并且过渡不是到对话退出。此状态还会映射到 MEDIA_STATUS_FINISHED 系统 intent。
  • PAUSED:用户暂停了媒体播放。您可以通过 optional_media_controls 属性选择接收此状态事件。此状态还会映射到 MEDIA_STATUS_PAUSED 系统 intent。
  • STOPPED:用户停止或退出媒体播放。您可以通过 optional_media_controls 属性选择接收此状态事件。此状态还会映射到 MEDIA_STATUS_STOPPED 系统 intent。
  • FAILED:媒体播放失败。此状态还会映射到 MEDIA_STATUS_FAILED 系统 intent。

在媒体播放期间,用户可能会提供一个可同时解读为媒体暂停和停止事件(如“停止”“取消”或“退出”)的查询。在这种情况下,Google 助理会向您的 Action 提供 actions.intent.CANCEL 系统 intent,生成状态值为“STOPPED”的媒体状态事件,并完全退出您的 Action。

当 Google 助理生成包含 PAUSEDSTOPPED 状态值的媒体状态事件时,使用仅包含确认信息(类型为 MEDIA_STATUS_ACK)的媒体响应进行响应。

媒体播放进度

对于网络钩子请求的 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”或类似内容来跳到下一首曲目。

播放列表的最后一首曲目无法使用 Next 按钮。不过,如果启用循环模式,播放列表会从第一首曲目再次开始播放。如需详细了解循环模式,请参阅实现循环模式

如需创建播放列表,请在 media_objects 数组中包含多个 MediaObject。以下代码段展示了一条提示,该提示会返回包含三首曲目的播放列表:

{
  "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
                }
              }
            }
          ],
        }
      }
    }
  ]
}

实现循环模式

循环模式允许您提供自动重复的音频响应。您可以使用此模式重复单个曲目或循环播放播放列表如果用户说出单个循环曲目的“Next”或类似语音指令,歌曲会再次开始播放。对于循环播放列表,用户说出“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"
        }
      }
    }
  ]
}