Gracias por tu visita. Esta página solo está disponible en inglés.

Step 8: Test Your Skill and Observe Logs in CloudWatch (VSK Fire TV)

It's time to test your skill and observe the directives Alexa sends to your Lambda function. You'll view the interactions through CloudWatch, which will list the directives Alexa sends to your Lambda. To see the responses your Lambda sends to your app, you'll open Logcat in Android Studio.

Connect to Fire TV Through adb

Now that you've configured the security profile, you're ready to run your app on Fire TV to make sure everything works and is authorized. See Connect to Fire TV Through adb for full details on running your app on Fire TV. The abbreviated version is as follows:

  1. On your Fire TV, go My Fire TV > Developer Options. Enable ADB Debugging and Apps from Unknown Sources.
  2. On Fire TV, go to Settings, and then browse to My Fire TV > About > Network. (Some Fire TV models might say "Device" instead of "My Fire TV.") Make a note of the IP address listed on this screen.
  3. Make sure you're computer is on the same wifi network as your Fire TV.
  4. Open up a terminal window and run the following:

    adb connect <ipaddress>:<port>
    

    The <port> can be any number within the 5555 to 5585 range.

    For example:

    adb connect 10.49.172.51:5555
    

    If adb fails to connect to your Fire TV, check to make sure you're on the same wifi network. If you are, try restarting your Fire TV (Settings > My Fire TV > Restart), as there might be conflicts on the ports.

  5. After successfully connecting to Fire TV, open Android Studio and run your app by clicking the Run App button Run 'app' .
  6. Choose the connected Fire TV device and click OK.

    Selecting the target Fire TV device
    Selecting the target Fire TV device
  7. Verify that your app runs. Open Logcat in Android Studio to monitor the log messages. If your app runs, then you know that you have configured the security profile correctly. The sample app's homescreen looks as follows:

    Three open-source videos are integrated into the catalog used in the sample app.
    Three open-source videos are integrated into the catalog used in the sample app.

    If the app loads a blank screen or has other issues, open Logcat and filter on "Error." If you see an error that says "Invalid API key," check to make sure you're signing your app with the custom debug signing key you configured earlier.

The Interaction Model Between Alexa, Lambda, and Your Fire TV App

Now that you have all the pieces in place, it's a good time to describe how all of these components work together in more detail. When you say phrases to your Alexa-enabled device, these phrases get parsed for their meaning (through Alexa natural language services) and converted into directives. Directives are information blocks (formatted in JSON) sent by Alexa via the Video Skill API to your Lambda for processing. There are about a half a dozen directives used with Fire TV, listed in the API Reference section.

You can view the directives that Alexa sends to your Lambda function through CloudWatch. CloudWatch is an AWS service that collects monitoring and operational data for Lambda (and other services) in the form of logs, metrics, and events. Each time your Lambda receives directives from Alexa, your Lambda can log the directives and other events, and you can view those logs in CloudWatch.

The core task in configuring a video skill is in understanding the directives Alexa sends to your Lambda function and then implementing the expected responses in your app. (Your Lambda function should also send a simple confirmation response back to Alexa to indicate that your processing of the directive was successful.)

(Note that although your Lambda function sends a response back to Alexa, your Lambda cannot provide any custom voice feedback that would be directed to the user. Alexa handles this communication exclusively. The only action you can perform is to carry out the actions specified in the API reference.)

Your Lambda communicates information to your Fire TV app through ADM. In the Lambda for the sample app, the Lambda simply pushes the same directive it receives from Alexa to your app. (You can customize your Lambda to send information as desired to your app.) The sample app contains logic that looks through the message from ADM and locates any media identifiers that match its catalog and plays them. You can see the incoming message through the Logcat pane — filter for the title you searched for.

Check your ADM message handler in your app to see if you have received the directive.
Check your ADM message handler in the app to see if you have received the directive. Filter on the media title you searched for.

Contexts for Utterance, and Implicit versus Explicit Targeting

Before getting into the various test cases, note the different contexts in which you can specify utterances. There are two primary contexts in which you can say utterances:

  • Implicit targeting: A voice command that does not specify the content provider or app name, e.g., "Watch Big Buck Bunny."
  • Explicit targeting: A voice command that specifies the content provider or app name, e.g. "Watch Big Buck Bunny on Streamz."

As you test various utterances, note that explicit targeting is only available after pushing your skill to Live App Testing. When you are sideloading your application through Android Studio, Alexa cannot handle explicit targeting of your skill. As a result, you'll need to open up your app so that it's the foreground.

However, if your app is in the foreground (rather than the background), when you say "Watch Big Buck Bunny," Alexa looks for matches within the foregrounded catalog's app (rather than in all catalogs). Saying a command while your app is in the foreground is the equivalent of explicit targeting but is supported even when you're sideloading from Android locally.

Say a Test Utterance

With the app running on your Fire TV, say to your Echo, "Alexa, watch Big Buck Bunny." Pause a little as you say Big … Buck … Bunny (otherwise Alexa will think you're saying Bugs Bunny).

Alexa responds, "<Video Skill> is now Alexa-enabled…. Getting Big Buck Bunny from <Video Skill>." This means Alexa has automatically paired your Fire TV app with the video skill. The Big Buck Bunny video starts to play.

Viewing Logs in CloudWatch

You will need to use CloudWatch to observe the events received from the video skill and the logs written by your Lambda. To view logs in CloudWatch:

  1. In AWS, go to CloudWatch and then choose Logs > Log groups in the left sidebar.

  2. Click your Lambda function.

    If you don't see your Lambda function, make sure you're in the right region, since only Lambda functions related to the region you're in appear.

  3. A list of logs for the function appears, with the most recent log group on top. (Logs won't appear here until you start saying commands to your Echo.)

If In the Lambda logs, to make the logs more scannable, you can select the Text radio button.

Note that you can also access your CloudWatch logs by going to your Lambda function. Click the Monitoring tab, and then click the View logs in CloudWatch button, as shown on the following screenshot.

CloudWatch Logs link from Lambda function screen
CloudWatch Logs link from Lambda function screen

Full Interaction in CloudWatch

Before jumping into the test utterances below, let's step through a sample CloudWatch log in detail. For a SearchAndPlay directive, your CloudWatch logs should resemble the following (at least for the sample Lambda). See the inline comments for explanations of what each log message means. Note that the Request ID (5351d...7376c) is shortened here for readability.

2019-11-22T02:38:56.315Z 5351d…7376c INFO Lambda was invoked by Alexa

The log starts with the Alexa request event.

When a Lambda function is invoked (in this case, by the video skill, which acts as a "trigger"), AWS Lambda starts executing your code by calling the handler function. The runtime passes three arguments to the handler method:

exports.handler = (event, context, callback) =>

Each argument is as follows:

  • event: The first argument, event, contains information from the invoker. In this case, the invoker is the Alexa directive. Alexa passes this directive as a JSON-formatted string when it calls Invoke.
  • context: The second argument is the context object, which contains information about the invocation, function, and execution environment.
  • callback: The third argument, callback, is a function that you can call in non-async functions to send a response.

You can learn more about Lambda in AWS Lambda Function Handler in Node.js.

2019-11-22T02:38:56.345Z 5351d…7376c INFO Context:

{
    "callbackWaitsForEmptyEventLoop": true,
    "functionVersion": "$LATEST",
    "functionName": "football_streamz_lambda",
    "memoryLimitInMB": "128",
    "logGroupName": "/aws/lambda/football_streamz_lambda",
    "logStreamName": "2019/11/22/[$LATEST]80890c82ad974631b9586cb4072e3558",
    "invokedFunctionArn": "arn:aws:lambda:us-east-1:793895964098:function:football_streamz_lambda",
    "awsRequestId": "5351d...7376c"
}

To see the context, the sample Lambda logs this information:

console.log("Context: " + JSON.stringify(context, null, 2));

The context contains information about the event that invoked your Lambda. The context information isn't that useful except that it shows the Lambda ARN that was invoked and the function (your video skill) that invoked it. You will likely want to just comment this out. Context is uncommented in the sample app so you can see what information gets passed to it. The video skill is a smart home trigger that you connected to this Lambda function.

2019-11-22T02:38:56.345Z 5351d…7376c INFO Alexa Request: SearchAndPlay

{
    "directive": {
        "payload": {
            "entities": [
                {
                    "type": "Video",
                    "uri": "entity://provider/program/amzn1.p11cat.merged-video.8a42b984-28c2-5c09-bd24-8d924e004d3f",
                    "value": "Big Buck Bunny",
                    "externalIds": {
                        "hawaii_us": "tt1254207",
                        "ENTITY_ID": "amzn1.p11cat.merged-video.8a42b984-28c2-5c09-bd24-8d924e004d3f",
                        "imdb": "tt1254207",
                        "tms": "MV006850300000"
                    }
                },
                {
                    "type": "Video",
                    "uri": "entity://provider/program/amzn1.p11cat.merged-video.5ad5ba65-843b-5ac0-bf1d-668e5f7ff894",
                    "value": "The Big Money",
                    "externalIds": {
                        "ENTITY_ID": "amzn1.p11cat.merged-video.5ad5ba65-843b-5ac0-bf1d-668e5f7ff894",
                        "tms": "MV010152170000"
                    }
                },
                {
                    "type": "Video",
                    "uri": "entity://provider/program/amzn1.p11cat.merged-video.de82b43b-3fbb-5550-872a-e85752ae5901",
                    "value": "Big Buck Pole",
                    "externalIds": {
                        "ENTITY_ID": "amzn1.p11cat.merged-video.de82b43b-3fbb-5550-872a-e85752ae5901",
                        "tms": "8826242"
                    }
                },
                {
                    "type": "Video",
                    "uri": "entity://provider/program/amzn1.p11cat.merged-video.4176eed9-eb18-546a-b934-314f50abe8db",
                    "value": "Big Buck Bunny",
                    "externalIds": {
                        "ENTITY_ID": "amzn1.p11cat.merged-video.4176eed9-eb18-546a-b934-314f50abe8db"
                    }
                },
                {
                    "type": "Video",
                    "uri": "entity://provider/program/amzn1.p11cat.merged-video.3cabe805-968e-5001-813c-f46b5b1069d7",
                    "value": "Big Buck Bunny",
                    "externalIds": {
                        "ENTITY_ID": "amzn1.p11cat.merged-video.3cabe805-968e-5001-813c-f46b5b1069d7",
                        "tms": "SH023726740000"
                    }
                }
            ]
        },
        "header": {
            "payloadVersion": "3",
            "messageId": "c2ca519b-9582-4cbf-87ae-5aa9bbb0abb5",
            "namespace": "Alexa.RemoteVideoPlayer",
            "name": "SearchAndPlay",
            "correlationToken": "b762c130-fb10-4337-ae08-3659cb5d1b87"
        },
        "endpoint": {
            "endpointId": "1b8b8f648adcd730##amzn1-ask-skill-c90a4a61-0cda-4a6e-a797-8766abec6fcb##development##com-fireappbuilder-android-nature-streamz",
            "cookie": {
                "VSKClientVersion": "1.4.5",
                "deviceType": "AFF5OAL5E3DIU",
                "appPackageName": "com.fireappbuilder.android.nature.streamz",
                "deviceId": "G3J0TV00838703PE",
                "appName": "Sample Alexa VSK Fire TV App",
                "applicationInstanceId": "amzn1.adm-registration.v3.Y29t...LmFtYX0"
            },
            "scope": {
                "token": null,
                "type": "BearerToken"
            }
        }
    }
}

The customer said a command to an Alexa-enabled Fire TV device (e.g., "Watch Big Buck Bunny"). The utterance was parsed by Alexa in the cloud and a directive was generated. Through the Video Skill API, Alexa reaches out to your Lambda function with the directive. The directive contains all matching items from your catalog as well as from Amazon Prime (the amzn1.p11cat... references).

This is a SearchAndPlay directive generated by Alexa specifying the content that your app should play. The content specified is "Big Buck Bunny." Alexa looks in your catalog for titles matching the user's request and lists the matching entries in the externalIds array. Alexa sends all matches to your Lambda and expects you to determine which one you should play in your app.

2019-11-22T02:38:56.345Z 5351d…7376c INFO ADM Registration ID: amzn1.adm-registration.v3.Y29tLmFtYXp…

In this case, the sample Lambda logs the ADM Registration ID to the console. You can choose to log whatever you want in your Lambda so you can see it in CloudWatch.

2019-11-22T02:38:56.788Z 5351d…7376c INFO Got Access Token Type:bearer Expires In:3600

ADM gets an accessToken using your credentials. If it succeeds, the Lambda function calls the sendMessageToDevice() function. If this is unsuccessful, no access token is granted.

2019-11-22T02:38:56.825Z 5351d…7376c INFO Calling device…

ADM calls the sendMessageToDevice() function to send the directive to your app, identifying it by way of the API key. ADM uses the request module for sending the directive. You can read more about ADM documentation headers in Request an access token.

2019-11-22T02:38:56.967Z 5351d…7376c INFO Response from the app:

{
    "registrationID": "amzn1.adm-registration.v3.Y29tLmFtYXpvbi5EZXZpY2VNZXN...hM1VCUFVnPT0"
}

The Lambda function responds with the registration ID to confirm the communication. (The long string is truncated here for readability.)

2019-11-22T02:38:56.967Z 5351d…7376c INFO Sending SearchAndPlay response back to Alexa: :

{
    "event": {
        "header": {
            "messageId": "not-required",
            "correlationToken": "not-required",
            "name": "Response",
            "namespace": "Alexa",
            "payloadVersion": "3"
        },
        "endpoint": {
            "scope": {
                "type": "DirectedUserId",
                "directedUserId": "not-required"
            },
            "endpointId": "not-required"
        },
        "payload": {}
    }
}

Your Lambda function sends a "success" response back to Alexa, indicating the directive was received by the Lambda.

END RequestId: 5351d…7376c

The directive has a request ID as shown. The interaction is finished.

REPORT RequestId: 5351d…7376c Duration: 673.60 ms Billed Duration: 700 ms Memory Size: 128 MB Max Memory Used: 102 MB Init Duration: 689.67 ms

The directive took this much time and memory to process. This is the duration you were billed for for running this process. Most Fire TV apps with video skills rarely use more memory than what free tier already provides: "1 million requests per month, with 400,000 GB-seconds of compute time per month." See AWS Lambda Pricing for more details.

Commands for the Sample App

Now that you have a sense of how to read the CloudWatch logs (for the information logged by the sample Lambda), it's time to run some tests. In this section, you will save four different utterances to Alexa and observe how the app behaves and what gets logged in CloudWatch. Because explicit targeting of your app isn't available yet, you'll need to start the sample app to bring it to the foreground before saying each utterance.

The sample app is capable of processing four directives. In the sample app, if you look at com.amazon.android.tv.tenfoot.receiver.TenFootADMessageHandler#onMessage (starting at line 80), you can see the logic of how the sample app handles the messages received from ADM. Remember that in this sample Lambda code, the Lambda merely passes along the same directive it receives from Alexa. The app then queries the payload and looks for media in its catalog.

You can code your Lambda with whatever process makes sense for your app. For example, as an alternative workflow, your Lambda could perform some processing on its own to locate the correct media identifier, and then send that down to your app, if you want.

SearchAndDisplayResults Directives

Sample utterance: Start the sample app. Then say, "Alexa, find Big Buck Bunny"

Response: "Getting Big Buck Bunny from [video skill name]". The app goes to the search screen and searches for the text "big buck bunny."

Directive that Alexa sends to your Lambda: SearchAndDisplayResults.

SearchAndPlay Directives

Sample utterance: Start the sample app. Then say, "Alexa, watch Big Buck Bunny"

Response: "Getting Big Buck Bunny from [video skill name]." Then the Big Buck Bunny video plays.

Directive that Alexa sends to your Lambda: SearchAndPlay

PlaybackController - Pause Directives

Sample utterance: Start the sample app (if necessary) and play Big Buck Bunny. Then say, "Alexa, pause."

Response: Alexa doesn't say anything, but the video pauses.

Directive that Alexa sends to your Lambda: PlaybackController: Pause

PlaybackController - Play Directives

Sample utterance: With the Big Buck Bunny video paused in the previous scenario, say, "Alexa, play."

Response: Alexa doesn't say anything, but the video resumes playback.

Directive Alexa sends to your Lambda: PlaybackController: Play

Next Steps

Now that you've got a sense of how the Alexa directives and Lambda function work, it's time to customize the Lambda for your own content and service. Continue on to Step 9: Interpret and React to Directives.

(If you run into any issues that prevent you from continuing, see Troubleshooting.)