2016-12-31 86 views
2

我正在嘗試爲亞馬遜Alexa寫一個獨特的Alexa技巧。我想編寫一個自定義的Lambda函數來播放下面的api(https://api.ense.nyc/latest)中包含的音頻內容。Alexa技能套件 - 從我們的iOS應用程序的API播放音頻的自定義技巧

我已經通過所有亞馬遜的關於這一主題的文檔閱讀:

我感到困惑究竟如何寫一個獨特的lambda函數進行。

+0

你看了鏈接頁面:創造一個技能的AWS lambda函數(https://developer.amazon.com/public/solutions/alexa/alexa-skills-kit/docs/developing-從你提到的「建立自定義技能」頁面的「步驟2」中獲得一個「alexa-skill-as-a-lambda-function」從字面上看,它具有創建「Lambda函數」的分步指南。另外,你應該用'aws-lambda'標籤標記你的問題。 – gmiley

回答

0

在alexa中播放音頻比常規技能有點棘手。

看起來你需要做的:

-Parse您的JSON和創建某種對象的保存音頻URL和音頻卡。

- 然後您需要將技能狀態設置爲PLAY_MODE,然後使用詢問audioPlayerPlay()命令開始播放音頻。 (https://developer.amazon.com/public/solutions/alexa/alexa-skills-kit/docs/custom-audioplayer-interface-reference#audioplayer-directives

- 然後您需要設置音頻事件處理程序以跟蹤音頻事件。

- 您需要設置意圖讓用戶播放下一個或以前的音頻。

不勝枚舉......

下面是一個簡單的播客技巧解析XML飼料和播放音頻

https://github.com/bespoken/streamer

0

下面的代碼工作的lambda函數用於播放第一音頻項目。請享用!

/** 
* App ID for the skill 
*/ 
//var APP_ID = undefined; //OPTIONAL: replace with "amzn1.echo-sdk-ams.app.[your-unique-value-here]"; 

/** 
* The AlexaSkill prototype and helper functions 
*/ 

var APP_ID = undefined; 

//var AlexaSkill = require('./AlexaSkill'); 

////// 
/** 
    Copyright 2014-2015 Amazon.com, Inc. or its affiliates. All Rights Reserved. 

    Licensed under the Apache License, Version 2.0 (the "License"). You may not use this file except in compliance with the License. A copy of the License is located at 

     http://aws.amazon.com/apache2.0/ 

    or in the "license" file accompanying this file. This file is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. 
*/ 



////////////////////////////////////////////// 
//////////// /AlexaSkill.js File Starts ///// 
////////////////////////////////////////////// 




'use strict'; 

function AlexaSkill(appId) { 
    this._appId = appId; 
} 

AlexaSkill.speechOutputType = { 
    PLAIN_TEXT: 'PlainText', 
    SSML: 'SSML' 
} 

AlexaSkill.prototype.requestHandlers = { 
    LaunchRequest: function (event, context, response) { 
     this.eventHandlers.onLaunch.call(this, event.request, event.session, response); 
    }, 

    IntentRequest: function (event, context, response) { 
     this.eventHandlers.onIntent.call(this, event.request, event.session, response); 
    }, 

    SessionEndedRequest: function (event, context) { 
     this.eventHandlers.onSessionEnded(event.request, event.session); 
     context.succeed(); 
    } 
}; 

/** 
* Override any of the eventHandlers as needed 
*/ 
AlexaSkill.prototype.eventHandlers = { 
    /** 
    * Called when the session starts. 
    * Subclasses could have overriden this function to open any necessary resources. 
    */ 
    onSessionStarted: function (sessionStartedRequest, session) { 
    }, 

    /** 
    * Called when the user invokes the skill without specifying what they want. 
    * The subclass must override this function and provide feedback to the user. 
    */ 
    onLaunch: function (launchRequest, session, response) { 
     throw "onLaunch should be overriden by subclass"; 
    }, 

    /** 
    * Called when the user specifies an intent. 
    */ 
    onIntent: function (intentRequest, session, response) { 
     var intent = intentRequest.intent, 
      intentName = intentRequest.intent.name, 
      intentHandler = this.intentHandlers[intentName]; 
     if (intentHandler) { 
      console.log('dispatch intent = ' + intentName); 
      intentHandler.call(this, intent, session, response); 
     } else { 
      throw 'Unsupported intent = ' + intentName; 
     } 
    }, 

    /** 
    * Called when the user ends the session. 
    * Subclasses could have overriden this function to close any open resources. 
    */ 
    onSessionEnded: function (sessionEndedRequest, session) { 
    } 
}; 

/** 
* Subclasses should override the intentHandlers with the functions to handle specific intents. 
*/ 
AlexaSkill.prototype.intentHandlers = {}; 

AlexaSkill.prototype.execute = function (event, context) { 
    try { 
     console.log("session applicationId: " + event.session.application.applicationId); 

     // Validate that this request originated from authorized source. 
     if (this._appId && event.session.application.applicationId !== this._appId) { 
      console.log("The applicationIds don't match : " + event.session.application.applicationId + " and " 
       + this._appId); 
      throw "Invalid applicationId"; 
     } 

     if (!event.session.attributes) { 
      event.session.attributes = {}; 
     } 

     if (event.session.new) { 
      this.eventHandlers.onSessionStarted(event.request, event.session); 
     } 

     // Route the request to the proper handler which may have been overriden. 
     var requestHandler = this.requestHandlers[event.request.type]; 
     requestHandler.call(this, event, context, new Response(context, event.session)); 
    } catch (e) { 
     console.log("Unexpected exception " + e); 
     context.fail(e); 
    } 
}; 

var Response = function (context, session) { 
    this._context = context; 
    this._session = session; 
}; 

function createSpeechObject(optionsParam) { 
    if (optionsParam && optionsParam.type === 'SSML') { 
     return { 
      type: optionsParam.type, 
      ssml: optionsParam.speech 
     }; 
    } else { 
     return { 
      type: optionsParam.type || 'PlainText', 
      text: optionsParam.speech || optionsParam 
     } 
    } 
} 

Response.prototype = (function() { 
    var buildSpeechletResponse = function (options) { 
     var alexaResponse = { 
      outputSpeech: createSpeechObject(options.output), 
      shouldEndSession: options.shouldEndSession 
     }; 
     if (options.reprompt) { 
      alexaResponse.reprompt = { 
       outputSpeech: createSpeechObject(options.reprompt) 
      }; 
     } 
     if (options.cardTitle && options.cardContent) { 
      alexaResponse.card = { 
       type: "Simple", 
       title: options.cardTitle, 
       content: options.cardContent 
      }; 
     } 
     var returnResult = { 
       version: '1.0', 
       response: alexaResponse 
     }; 
     if (options.session && options.session.attributes) { 
      returnResult.sessionAttributes = options.session.attributes; 
     } 
     return returnResult; 
    }; 

    return { 
     tell: function (speechOutput) { 
      this._context.succeed(buildSpeechletResponse({ 
       session: this._session, 
       output: speechOutput, 
       shouldEndSession: true 
      })); 
     }, 
     tellWithCard: function (speechOutput, cardTitle, cardContent) { 
      this._context.succeed(buildSpeechletResponse({ 
       session: this._session, 
       output: speechOutput, 
       cardTitle: cardTitle, 
       cardContent: cardContent, 
       shouldEndSession: true 
      })); 
     }, 
     ask: function (speechOutput, repromptSpeech) { 
      this._context.succeed(buildSpeechletResponse({ 
       session: this._session, 
       output: speechOutput, 
       reprompt: repromptSpeech, 
       shouldEndSession: false 
      })); 
     }, 
     askWithCard: function (speechOutput, repromptSpeech, cardTitle, cardContent) { 
      this._context.succeed(buildSpeechletResponse({ 
       session: this._session, 
       output: speechOutput, 
       reprompt: repromptSpeech, 
       cardTitle: cardTitle, 
       cardContent: cardContent, 
       shouldEndSession: false 
      })); 
     } 
    }; 
})(); 




////////////////////////////////////////////// 
///////////// AlexaSkill.js File Ends ////// 
////////////////////////////////////////////// 










'use strict'; 

function AlexaSkill(appId) { 
    this._appId = appId; 
} 

AlexaSkill.speechOutputType = { 
    PLAIN_TEXT: 'PlainText', 
    SSML: 'SSML' 
} 

AlexaSkill.prototype.requestHandlers = { 
    LaunchRequest: function (event, context, response) { 
     this.eventHandlers.onLaunch.call(this, event.request, event.session, response); 
    }, 

    IntentRequest: function (event, context, response) { 
     this.eventHandlers.onIntent.call(this, event.request, event.session, response); 
    }, 

    SessionEndedRequest: function (event, context) { 
     this.eventHandlers.onSessionEnded(event.request, event.session); 
     context.succeed(); 
    } 
}; 

/** 
* Override any of the eventHandlers as needed 
*/ 
AlexaSkill.prototype.eventHandlers = { 
    /** 
    * Called when the session starts. 
    * Subclasses could have overriden this function to open any necessary resources. 
    */ 
    onSessionStarted: function (sessionStartedRequest, session) { 
    }, 

    /** 
    * Called when the user invokes the skill without specifying what they want. 
    * The subclass must override this function and provide feedback to the user. 
    */ 
    onLaunch: function (launchRequest, session, response) { 
     throw "onLaunch should be overriden by subclass"; 
    }, 

    /** 
    * Called when the user specifies an intent. 
    */ 
    onIntent: function (intentRequest, session, response) { 
     var intent = intentRequest.intent, 
      intentName = intentRequest.intent.name, 
      intentHandler = this.intentHandlers[intentName]; 
     if (intentHandler) { 
      console.log('dispatch intent = ' + intentName); 
      intentHandler.call(this, intent, session, response); 
     } else { 
      throw 'Unsupported intent = ' + intentName; 
     } 
    }, 

    /** 
    * Called when the user ends the session. 
    * Subclasses could have overriden this function to close any open resources. 
    */ 
    onSessionEnded: function (sessionEndedRequest, session) { 
    } 
}; 

/** 
* Subclasses should override the intentHandlers with the functions to handle specific intents. 
*/ 
AlexaSkill.prototype.intentHandlers = {}; 

AlexaSkill.prototype.execute = function (event, context) { 
    try { 
     console.log("session applicationId: " + event.session.application.applicationId); 

     // Validate that this request originated from authorized source. 
     if (this._appId && event.session.application.applicationId !== this._appId) { 
      console.log("The applicationIds don't match : " + event.session.application.applicationId + " and " 
       + this._appId); 
      throw "Invalid applicationId"; 
     } 

     if (!event.session.attributes) { 
      event.session.attributes = {}; 
     } 

     if (event.session.new) { 
      this.eventHandlers.onSessionStarted(event.request, event.session); 
     } 

     // Route the request to the proper handler which may have been overriden. 
     var requestHandler = this.requestHandlers[event.request.type]; 
     requestHandler.call(this, event, context, new Response(context, event.session)); 
    } catch (e) { 
     console.log("Unexpected exception " + e); 
     context.fail(e); 
    } 
}; 

var Response = function (context, session) { 
    this._context = context; 
    this._session = session; 
}; 

function createSpeechObject(optionsParam) { 
    if (optionsParam && optionsParam.type === 'SSML') { 
     return { 
      type: optionsParam.type, 
      ssml: optionsParam.speech 
     }; 
    } else { 
     return { 
      type: optionsParam.type || 'PlainText', 
      text: optionsParam.speech || optionsParam 
     } 
    } 
} 

Response.prototype = (function() { 
    var buildSpeechletResponse = function (options) { 
     var alexaResponse = { 
      outputSpeech: createSpeechObject(options.output), 
      shouldEndSession: options.shouldEndSession 
     }; 
     if (options.reprompt) { 
      alexaResponse.reprompt = { 
       outputSpeech: createSpeechObject(options.reprompt) 
      }; 
     } 
     if (options.cardTitle && options.cardContent) { 
      alexaResponse.card = { 
       type: "Simple", 
       title: options.cardTitle, 
       content: options.cardContent 
      }; 
     } 
     var returnResult = { 
       version: '1.0', 
       response: alexaResponse 
     }; 
     if (options.session && options.session.attributes) { 
      returnResult.sessionAttributes = options.session.attributes; 
     } 
     return returnResult; 
    }; 

    return { 
     tell: function (speechOutput) { 
      this._context.succeed(buildSpeechletResponse({ 
       session: this._session, 
       output: speechOutput, 
       shouldEndSession: true 
      })); 
     }, 
     tellWithCard: function (speechOutput, cardTitle, cardContent) { 
      this._context.succeed(buildSpeechletResponse({ 
       session: this._session, 
       output: speechOutput, 
       cardTitle: cardTitle, 
       cardContent: cardContent, 
       shouldEndSession: true 
      })); 
     }, 
     ask: function (speechOutput, repromptSpeech) { 
      this._context.succeed(buildSpeechletResponse({ 
       session: this._session, 
       output: speechOutput, 
       reprompt: repromptSpeech, 
       shouldEndSession: false 
      })); 
     }, 
     askWithCard: function (speechOutput, repromptSpeech, cardTitle, cardContent) { 
      this._context.succeed(buildSpeechletResponse({ 
       session: this._session, 
       output: speechOutput, 
       reprompt: repromptSpeech, 
       cardTitle: cardTitle, 
       cardContent: cardContent, 
       shouldEndSession: false 
      })); 
     }, 
     justUseThisJsonPlease: function(json) { 
      this._context.succeed(json); 
     } 
    }; 
})(); 
////// 
var https = require('https'); 
var Fact = function() { 
    AlexaSkill.call(this, APP_ID); 
}; 

// Extend AlexaSkill 
Fact.prototype = Object.create(AlexaSkill.prototype); 
Fact.prototype.constructor = Fact; 

Fact.prototype.eventHandlers.onSessionStarted = function (sessionStartedRequest, session) { 
    console.log("onSessionStarted requestId: " + sessionStartedRequest.requestId + ", sessionId: " + session.sessionId); 
    // any initialization logic goes here 
}; 

Fact.prototype.eventHandlers.onLaunch = function (launchRequest, session, response) { 
    console.log("onLaunch requestId: " + launchRequest.requestId + ", sessionId: " + session.sessionId); 
    //handleEnseFeed(response) 
}; 

/** 
* Overridden to show that a subclass can override this function to teardown session state. 
*/ 
Fact.prototype.eventHandlers.onSessionEnded = function (sessionEndedRequest, session) { 
    //console.log("onSessionEnded requestId: " + sessionEndedRequest.requestId + ", sessionId: " + session.sessionId); 
    // any cleanup logic goes here 
}; 

Fact.prototype.intentHandlers = { 
    "PlayAudio": function (event, context, response) { 
     //response.tell('ense is lit') 
     //handleEnseFeed(response) 
      fetchEnseParse("/latest", function(body) { 
      if(body == "error") { 
      } 
      else { 
       var directives = body.enses.map(function(ense) { 
        var a = ense[1].fileUrl; 
        return { 
         'playBehavior': 'REPLACE_ALL', 
         'audioItem': 
          { 
           'stream': 
            { 
             'url': 'https://s3.amazonaws.com/media.ense.nyc/enses/2017_01_13T16_57_20.190Z/30312/0', 
             'token': '33529', 
             'offsetInMilliseconds': 0 
            } 
          }, 
          'type': 'AudioPlayer.Play' 
        }; 
       }) 
      } 
      var jsonresponse = { 
       'outputSpeech': { 
        'text': '', 
        'type': 'PlainText' 
        }, 
       'directives': [directives[0]] 
      };  
      response.justUseThisJsonPlease({ response: jsonresponse }); 
      //queueNext(); 
     }); 
    }, 
    "AudioPlayer.PlaybackNearlyFinished" : function(event, context, response) { 
     //console.log(JSON.stringify(intent)); 
     //console.log(JSON.stringify(session)); 
     //console.log(JSON.stringify(response)); 
     // console.log("dog") 
     // var stream = { 
     //  "url": "https://s3.amazonaws.com/media.ense.nyc/enses/violetindigoviolet/30034/0", 
     //  "token": "some_token", 
     //  "expectedPreviousToken": "33529", 
     //  "offsetInMilliseconds": 0 
     // }; 
     // response.audioPlayerPlayStream("ENQUEUE", stream); 
     // response.justUseThisJsonPlease({ response: stream }); 
      var second = 
      { 
       "type": "AudioPlayer.Play", 
       "playBehavior": "REPLACE_ENQUEUED", 
       "audioItem": { 
       "stream": { 
        "url": "https://s3.amazonaws.com/media.ense.nyc/enses/violetindigoviolet/30034/0", 
        "token": "33530", 
       // "expectedPreviousToken": "33529", 
        "offsetInMilliseconds": 0 
       } 
       } 
      } 
      response.justUseThisJsonPlease({ response: second }); 
    }, 
     "AudioPlayer.PlaybackFinished" : function(event, context, response) { 
      var speechOutput = "Goodbye"; 
      response.tell(speechOutput); 
    }, 
    "AMAZON.HelpIntent": function (intent, session, response) { 
     response.ask("You can say play ense feed or, you can say exit... What can I help you with?", "What can I help you with?"); 
    }, 
    "AMAZON.StopIntent": function (intent, session, response) { 
     var speechOutput = "Goodbye"; 
     response.tell(speechOutput); 
    }, 
    "AMAZON.CancelIntent": function (intent, session, response) { 
     var speechOutput = "Goodbye"; 
     response.tell(speechOutput); 
    } 
}; 



function queueNext(event, second) { 
     console.log ('trains') 
     var response = { 

     'outputSpeech': 
     { 
     'text': '', 
     'type': 'PlainText' 
     }, 
      'directives': 
      [ 
       { 
        'playBehavior': 'REPLACE_ALL', 
        'audioItem': 
       { 
        'stream': 
        { 
         'url': 'https://s3.amazonaws.com/media.ense.nyc/enses/violetindigoviolet/30034/0', 
         'token': '33529', 
         'offsetInMilliseconds': 10000 
        } 
       }, 
       'type': 'AudioPlayer.Play'} 

      ] 
     }; 
    // second.succeed({ response: response }); 
} 

function handleEnseFeed(response) { 
    https.get('https://api.ense.nyc/latest', function (res) { 
     var body = ''; 

     if (res.statusCode != 200) 

     res.on('data', function (chunk) { 
      body += chunk; 
     }); 

     res.on('end', function (par1, par2) { 
      body = JSON.parse(body); 
      var enses = body.enses; 

      response._context.succeed(thisResponse); 

     }).on('error', function (e) { 

     }); 

    }); 
} 


function fetchEnseParse(url, handler) { 
    const getEnseOptions = { 
      host : "api.ense.nyc", 
      path : url 
     }; 
    const req = https.request(getEnseOptions, (res) => { 
      var body = ''; 
      res.setEncoding('utf8'); 
      res.on('data', (chunk) => body += chunk); 
      res.on('end',() => { 
       // If we know it's JSON, parse it 
       if (res.headers['content-type'] && res.headers['content-type'].indexOf('application/json') != -1) { 
        body = JSON.parse(body); 
        handler(body); 
       } else { 
        handler("error"); 
       } 

      }); 
     }); 

     req.on('error', function() { 
      handler("error"); 
     }); 
     req.end(); 
}; 


// Create the handler that responds to the Alexa Request. 
exports.handler = function (event, context) { 
    // Create an instance of the SpaceGeek skill. 
    var fact = new Fact(); 
    console.log("tractor") 
    // queueNext(); 
    // var api = testFuntion(); 
    fact.execute(event, context); 
};