有没有办法在异步

时间:2017-11-21 17:13:19

标签: python-3.x ffmpeg async-await youtube-dl

我有一个应用程序,我使用zmqasyncio与能够将youtube-dl视频下载到服务器的客户端进行通信。我尝试将await添加到youtube_dl的下载功能,但它给了我一个错误,因为它不是协程。我现在的代码看起来像这样:

import asyncio
import youtube_dl


async def networking_stuff():
    download = True
    while True:
        if download:
            print("Received a request for download")
            await youtube_to_mp3("https://www.youtube.com/watch?v=u9WgtlgGAgs")
            download = False
        print("Working..")
        await asyncio.sleep(2)


async def youtube_to_mp3(url):
    ydl_opts = {
        'format': 'bestaudio/best',
        'postprocessors': [{
            'key': 'FFmpegExtractAudio',
            'preferredcodec': 'mp3',
            'preferredquality': '192',
        }]
    }

    with youtube_dl.YoutubeDL(ydl_opts) as ydl:
        ydl.download([url])


loop = asyncio.get_event_loop()
loop.create_task(networking_stuff())
loop.run_forever()

给出以下输出:

Received a request for download
[youtube] u9WgtlgGAgs: Downloading webpage
[youtube] u9WgtlgGAgs: Downloading video info webpage
[youtube] u9WgtlgGAgs: Extracting video information
[youtube] u9WgtlgGAgs: Downloading MPD manifest
[download] Destination: The Cardigans - My Favourite Game “Stone Version”-u9WgtlgGAgs.webm
[download] 100% of 4.20MiB in 00:03
[ffmpeg] Destination: The Cardigans - My Favourite Game “Stone Version”-u9WgtlgGAgs.mp3
Deleting original file The Cardigans - My Favourite Game “Stone Version”-u9WgtlgGAgs.webm (pass -k to keep)
Working..
Working..
....
Working..
Working..

虽然我希望在Working..的消息之间打印youtube-dl消息。我在这里遗漏了什么,或者async / await这是不可能的? ffmpeg阻止了吗?如果是这样,我可以在async中运行下载而无需转换为mp3或仅使用线程吗?

1 个答案:

答案 0 :(得分:3)

你是对的,你不能简单地使任何函数异步。

您的问题假定youtube-dl需要ffmpeg才能工作。它不完全正确,它可以通过自己的方式下载单个流,AFAIK ffmpeg仅用于将这些流(视频+音频+可能是字幕)复用到一个文件。

如果你使用ffmpeg,从性能的角度来看并不多,因为如果它是通过子进程使用的(最有可能的情况),那么至少有一个完整的 - 为了完成工作而产生了进程。与子进程的交互也可以以非阻塞方式完成 - 请参阅https://docs.python.org/3/library/asyncio-subprocess.html,但无论如何,如果您的代码为每个任务生成一个进程,则无论如何都无法很好地扩展。

否则,可能(并且有意义)分叉youtube-dl并进行更改,以便所有网络操作都基于asyncio。这可能是相当多的重构,但它应该是可行的。

关于您的代码:
首先,函数youtube_to_mp3根本不是异步的,因为没有可以执行await …表达式的代码路径。如果您从函数定义中移除async字,并从await移除await youtube_to_mp3("…,则代码的含义将不会发生

其次,即使它是异步的,你也不会以允许" parallel"的方式使用它。执行。 await关键字实际上意味着:此任务中的控制流 只有在等待的协程完成后才会继续。如果你需要在" parallel"中运行多个协程,你将不需要一个接一个地直接等待它们。有几种方法可以并行运行协同程序,例如,您可以使用https://docs.python.org/3/library/asyncio-task.html#asyncio.gather并等待结果"组合" coroutine,如果所有任务都在同一时刻被知道(但它看起来不像你的情况),或者使用fire-and-forget方法(loop.create_task)。

相关问题