When developing on the Alexa, using:

var audioUrl = Util.getS3PreSignedUrl("Media/001.mp3").replace(/&/g,'&');`

I can play an mp3 audio clip using an SSML tag and yet keep the mp3 private, by storing it in an Alexa-hosted S3 bucket (and locking down the permissions to it):

output1+=audio001[currentTrack]+<audio src="${audioUrl1}"/>+moreInstructions; // AND

return handlerInput.responseBuilder .speak(output1) .reprompt(moreInstructions) .getResponse();

However, I can't seem to follow the same approach for an mp4 / video format. It seems that using Alexa Presentation Language (APL), you have to store your videos publically on the internet. I have tried to use the pre-signed Utility function for the Mp4 video, but it doesn't seem to work ...

I tried the following:

const Alexa = require('ask-sdk-core');
const Util = require('./util.js');
const DOCUMENT_ID = "VideoDocument";

var videoUrl = Util.getS3PreSignedUrl("Media/safari.mp4").replace(/&/g,'&amp;');

const datasource = {
"videoPlayerTemplateData": {
    "type": "object",
    "properties": {
        "backgroundImage": "https://d2o906d8ln7ui1.cloudfront.net/images/response_builder/background-green.png",
        "displayFullscreen": true,
        "headerTitle": "xxx",
        "headerSubtitle": "xxx",
        "logoUrl": "xxx,
        "videoControlType": "skip",
        "videoSources": [

// "https://d2o906d8ln7ui1.cloudfront.net/videos/AdobeStock_277864451.mov", "https://d2o906d8ln7ui1.cloudfront.net/videos/AdobeStock_292807382.mov", videoUrl ], "sliderType": "determinate" } } };

const LaunchRequestHandler = {
canHandle(handlerInput) {
    return Alexa.getRequestType(handlerInput.requestEnvelope) === 'LaunchRequest';
},
handle(handlerInput) {
    const speakOutput = 'Welcome, you can say Hello or Help. Which would you like to try?';

    return handlerInput.responseBuilder
        .speak(speakOutput)
        .reprompt(speakOutput)
        .getResponse();
}

};

const createDirectivePayload = (aplDocumentId, dataSources = {}, tokenId = "documentToken") => {
return {
    type: "Alexa.Presentation.APL.RenderDocument",
    token: tokenId,
    document: {
        type: "Link",
        src: "doc://alexa/apl/documents/" + aplDocumentId
    },
    datasources: dataSources
}

};

const SampleAPLRequestHandler = {
canHandle(handlerInput) {
    // handle named intent
    return Alexa.getRequestType(handlerInput.requestEnvelope) === 'IntentRequest'
        && Alexa.getIntentName(handlerInput.requestEnvelope) === 'HelloWorldIntent';
},
handle(handlerInput) {
    if (Alexa.getSupportedInterfaces(handlerInput.requestEnvelope)['Alexa.Presentation.APL']) {
        // generate the APL RenderDocument directive that will be returned from your skill
        const aplDirective = createDirectivePayload(DOCUMENT_ID, datasource);
        // add the RenderDocument directive to the responseBuilder
        handlerInput.responseBuilder.addDirective(aplDirective);
    }

    // send out skill response
    return handlerInput.responseBuilder.getResponse();
}

};

It works if videoURL is set to a string or a URL of a publically hosted mp4 video, but not if it points to the pre-signed URL for an mp4 video from an S3 bucket.

1

There are 1 best solutions below

0
On

The .replace(/&/g,'&amp;') is only used for URLs which will be included in SSML, since this is an XML syntax within a json, so two parsers apply and will correct this when they are invoked inside each other.

If you get a file URL directly in json (what APL is), then you just can use var videoUrl = Util.getS3PreSignedUrl("Media/safari.mp4"); and it should work.