미디어 응답

미디어 응답을 사용하면 작업에서 재생 시간이 240초 한도인 SSML보다 긴 오디오 콘텐츠를 재생할 수 있습니다. 미디어 응답은 오디오 전용 기기 및 시각적 콘텐츠를 표시할 수 있는 기기 모두에서 작동합니다. 디스플레이에서 미디어 응답은 미디어 컨트롤이 있는 시각적 구성요소 및 스틸 이미지(선택사항)와 함께 제공됩니다.

미디어 응답을 정의할 때 Google 어시스턴트가 지원되는 기기에서만 리치 응답을 반환하도록 RICH_RESPONSELONG_FORM_AUDIO 노출 영역 기능을 모두 포함하는 후보를 사용합니다. 프롬프트의 content 객체당 하나의 리치 응답만 사용할 수 있습니다.

재생할 오디오는 올바른 형식의 MP3 파일이어야 합니다. MP3 파일은 웹 서버에서 호스팅되어야 하며 HTTPS URL을 통해 공개적으로 사용 가능해야 합니다. 실시간 스트리밍은 MP3 형식에서만 지원됩니다.

스마트 디스플레이의 미디어 응답 예
그림 1. 스마트 디스플레이의 미디어 응답 예

동작

스마트폰에 표시된 미디어 응답의 예
그림 2. 스마트폰의 미디어 응답 예

미디어 응답의 기본 구성요소는 단일 트랙 카드입니다. 이 카드를 통해 사용자는 다음 작업을 할 수 있습니다.

  • 지난 10초 다시 재생
  • 30초 앞으로 이동
  • 미디어 콘텐츠의 총 길이 보기
  • 미디어 재생 진행률 표시기 보기
  • 경과된 재생 시간 보기

미디어 응답은 음성 상호작용에 다음과 같은 오디오 컨트롤을 지원하며, 이러한 모든 작업은 Google 어시스턴트에서 처리됩니다.

  • "Hey Google, 재생해 줘."
  • “Hey Google, 일시중지해 줘.”
  • “Hey Google, 중지해 줘.”
  • “Hey Google, 다시 시작해 줘.”

사용자는 "Hey Google, 볼륨 높여 줘" 또는 "Hey 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 기반 색인입니다. 지정하지 않거나, 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 어시스턴트는 미디어 상태 이벤트를 생성하여 작업에 재생 진행률을 알릴 수 있습니다. 웹훅 코드에서 이러한 상태 이벤트를 처리하여 사용자를 미디어 재생을 일시중지, 중지 또는 종료할 때 적절하게 라우팅하세요.

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' 상태 값으로 미디어 상태 이벤트를 생성하고, 작업을 완전히 종료합니다.

어시스턴트가 PAUSED 또는 STOPPED 상태 값으로 미디어 상태 이벤트를 생성하면 확인 (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를 두 개 이상 포함합니다. 다음 코드 스니펫은 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
                }
              }
            }
          ],
        }
      }
    }
  ]
}

연속 재생 모드 구현

연속 모드를 사용하면 자동으로 반복되는 오디오 응답을 제공할 수 있습니다. 이 모드를 사용하여 단일 트랙을 반복하거나 재생목록을 반복할 수 있습니다. 사용자가 "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"
        }
      }
    }
  ]
}