我知道这个问题已经很老了,但是在过去的几天里我尝试了类似的东西,实际上我很沮丧,因为我花了很长时间才找到解决方案。所以也许我可以省去一些麻烦。
与 TO 类似,我尝试创建一个 Alexa Skill 来播放 Youtube 音频。这可以用 pafy 来完成,正如问题中所指出的那样,使用bestaudio = video.getbestaudio()
. 由于我们不打算下载音频,因此无需指定格式。生成的链接将是 .webm 格式,但只有音频部分,可以通过在浏览器中打开链接进行测试。
这是此部分的代码示例:
import pafy
def get_audio(url):
video = pafy.new(url)
best = video.getbestaudio()
return best.url
yt_url = "https://www.youtube.com/watch?v=iu7289s7l64"
audio_url = get_audio(yt_url)
print(audio_url)
这实际上对我来说在本地运行良好。但是,在将代码部署到 AWS Lambda 时,它不起作用。Alexa 会报告请求的技能响应存在问题,而 CloudWatch 没有显示任何错误或日志输出。
这里有两件事需要注意:
- 确保库已打包并上传。但是,这将在 CloudWatch Logs 中引发错误,并且在使用新的 ASK CLI 2.x 并在 require.txt 中添加 pafy 和 youtube-dl 时不会出现问题。当使用旧版本的 ASK CLI (1.x) 时,我遇到了问题,因为 requirements.txt 被忽略了。
- 在 AWS 控制台中增加 Lambda 函数的超时。默认情况下,它设置为 3s,这在这种情况下是短路的。长视频的调用似乎最多需要 10 秒,为了安全起见,我将其设置为 30 秒。由于某种原因,这比本地呼叫所需的时间长得多(如果有人对此有见解,我会很好奇)。然而,这就是让我陷入困境的原因。
由于 TO 还询问如何调用音频流,这是我的解决方案:
class StoryIntent(AbstractRequestHandler):
def can_handle(self, handler_input):
# type: (HandlerInput) -> bool
return ask_utils.is_intent_name("StartPlayingIntent")(handler_input)
def handle(self, handler_input):
# type: (HandlerInput) -> Response
yt_url = "https://www.youtube.com/watch?v=iu7289s7l64"
url = get_audio(yt_url)
return handler_input.response_builder.speak('I am starting to play the story').add_directive(
PlayDirective(
play_behavior=PlayBehavior.REPLACE_ALL,
audio_item=AudioItem(
stream=Stream(
token=url,
url=url,
expected_previous_token=None),
metadata=None
)
)
).set_should_end_session(True)
我不确定在回答这个问题时上面的代码是否有效。到今天,基于类的意图很常见,所以我们开始吧。
tl:dr增加 Lambda 函数的 Timeout,默认为 short。