Alexa YouTube在Python Flask-Ask中的技巧

时间:2018-07-09 12:42:43

标签: python youtube alexa pafy flask-ask

我正在使用Python中的flask-ask框架来开发Alexa-Skill,该Alexa-Skill仅播放YouTube视频的音频流而无需下载。

因此,我使用了using Uninstantiatable = IncompleteType;

以下功能可从YouTube视频中获取音频网址:

pafy

此功能比应播放音频

def get_audio():
    video = pafy.new("https://www.youtube.com/watch?v=ALdKl2HRSoI")
    bestaudio = video.getbestaudio(preftype="m4a")
    playurl = bestaudio.url
    return playurl

不幸的是,它不适用于我从pafy获得的网址。 Alexa只是玩什么。

我打印了从pafy获得的url,看起来像这样:

Pafy: Youtube-Audio URL

如果我为@ask.intent('StoryIntent') def story(): speech = "I am starting to play the story" stream_url = get_audio("https://www.youtube.com/watch?v=ALdKl2HRSoI") return audio(speech).play(stream_url) 使用以下URL,则一切正常:

Sample Audio-File on S3

我还尝试了以下操作: 我从“ Pafy:Youtube-Audio URL”下载了音频文件,并将其上传到S3,并使用了S3的链接,一切正常。但是我不想下载YouTube视频作为我的方法。

1 个答案:

答案 0 :(得分:2)

我知道这个问题已经很老了,但是最近几天我尝试了类似的尝试,但由于花了我很长时间才找出解决方案,所以实际上感到非常沮丧。所以也许我可以为别人省些麻烦。

类似于TO,我尝试创建Alexa技能来播放Youtube Audio。可以使用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没有显示任何错误或日志输出。

这里要注意两件事:

  1. 确保已打包并上传了库。但是,这将在CloudWatch Logs中引发错误,并且在pafy和youtube-上使用新的ASK CLI 2.x时,这并不困难。 dl已添加到require.txt中。使用较旧版本的ASK CLI(1.x)时,我遇到了问题,因为require.txt被忽略了。
  2. 增加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函数的超时,默认为短路方式。