2016-12-31 1 views
2

아마존 알렉사에 대한 고유 한 알렉시 스킬을 쓰려고합니다. 다음 API (https://api.ense.nyc/latest)에 포함 된 오디오 내용을 재생하는 사용자 지정 람다 함수를 작성하고 싶습니다.알렉사 스킬 키트 - iOS 앱의 API에서 오디오를 재생하는 사용자 지정 기술

나는 주제에 아마존의 모든 문서를 읽어했습니다

나는 독특한 람다 함수를 서면으로 진행하는 정확한 방법에 대한 혼란 스러워요을 Flashbriefing.

+0

당신은 링크 된 페이지를 읽나요 알렉사 - 스킬 - 람다 - 기능)을'당신이 언급 한 '커스텀 스킬 만들기'페이지의'2 단계 '에서 삭제 했습니까? 말 그대로 '람다 함수 (Lambda Function)'를 생성하는 단계별 가이드가 있습니다. 또한 질문에'aws-lambda' 태그를 붙여야합니다. – gmiley

답변

0

alexa에서 오디오를 재생하는 것은 일반적인 기술보다 조금 까다 롭습니다. 당신의 JSON -Parse

및 오디오 URL 및 오디오 카드를 보유 개체의 어떤 종류를 만들 : 당신이해야 할 같은

보인다.

- 그런 다음 기술 상태를 PLAY_MODE로 설정해야 audioPlayerPlay() 명령으로 오디오 재생을 시작해야합니다. (https://developer.amazon.com/public/solutions/alexa/alexa-skills-kit/docs/custom-audioplayer-interface-reference#audioplayer-directives)

- 그런 다음 오디오 이벤트를 추적하기 위해 오디오 이벤트 핸들러를 설정해야합니다.

- 사용자가 다음 또는 이전 오디오를 재생할 수 있도록 의도를 설정해야합니다. 목록은 계속

... 여기

처음 재생에 다음 코드는 람다 함수에서 작동하는 오디오

https://github.com/bespoken/streamer

0

를 XML 피드를 구문 분석하고 재생하는 샘플 팟 캐스트 기술이다 오디오 항목. 즐겨! [스킬에 대한 AWS 람다 함수 만들기] (https://developer.amazon.com/public/solutions/alexa/alexa-skills-kit/docs/developing- :

/** 
* 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); 
}; 
관련 문제