Python - yt_dlp 的进度从 100% 回到钩子响应中的“下沉”

Python - Progress of yt_dlp goes from 100% back to "downloding" in hook response

提问人:Benjamin 提问时间:11/10/2023 最后编辑:Benjamin 更新时间:11/11/2023 访问量:35

问:

我改编了我在这里找到的代码,它展示了如何在yt_dlp库中使用 python 钩子。我稍微打印出代码,只打印出状态和进度。

日志中有两件事我觉得很奇怪:

  1. 在达到 100% 之前,下载率从 91% 上升到 93%,然后又回到 90%。
  2. 完成后,控制台会打印出几行附加行,下载返回到“正在下载”。

知道这是怎么回事吗?

日志结束:

Status: downloading | Downloaded 91% 62552097/68667474 bytes
Status: downloading | Downloaded 93% 63600673/68667474 bytes
Status: downloading | Downloaded 90% 61765665/68667474 bytes
Status: downloading | Downloaded 90% 61634593/68667474 bytes
Status: downloading | Downloaded 96% 65697825/68667474 bytes
Status: downloading | Downloaded 90% 61569057/68667474 bytes
Status: downloading | Downloaded 90% 61536289/68667474 bytes
Status: finished | Downloaded 100% already
Status: downloading | Downloaded 100% 68667474/68667474 bytes
Status: downloading | Downloaded 90% 61519905/68667474 bytes
Status: downloading | Downloaded 90% 61511713/68667474 bytes
Status: downloading | Downloaded 90% 61507617/68667474 bytes
Status: downloading | Downloaded 90% 61505569/68667474 bytes
Status: downloading | Downloaded 75% 51466830/68667474 bytes
Status: downloading | Downloaded 75% 51465806/68667474 bytes
Status: downloading | Downloaded 60% 41180262/68667474 bytes

法典:

import asyncio
from functools import partial
import threading
from yt_dlp import YoutubeDL
from queue import LifoQueue, Empty

import sys
def main():
    # Set the url to download
    url = "xxxxx"

    # Get the current event loop
    loop = asyncio.get_event_loop()

    # Create a Last In First Out Queue to communicate between the threads
    queue = LifoQueue()

    # Create the future which will be marked as done once the file is downloaded
    coros = [youtube_dl(url, queue)]
    future = asyncio.gather(*coros)

    # Start a new thread to run the loop_in_thread function (with the positional arguments passed to it)
    t = threading.Thread(target=loop_in_thread, args=[loop, future])
    t.start()

    # While the future isn't finished yet continue
    while not future.done():
        try:
            # Get the latest status update from the que and print it
            data = queue.get_nowait()
            if data['status'] == 'downloading':
                print('Status: ' + data['status'] + ' | Downloaded ' + "{:.0%}".format(data['downloaded_bytes']/data['total_bytes']) + ' ' +  str(data['downloaded_bytes']) + '/' + str(data['total_bytes']) + ' bytes')
            elif data['status'] == 'finished':
                print('Status: ' + data['status'] + ' | Downloaded 100% already')
        except Empty as e:
            print('Status: Loading')
        finally:
            # Sleep between checking for updates
            asyncio.run(asyncio.sleep(0.1))


def loop_in_thread(loop, future):
    loop.run_until_complete(future)


async def youtube_dl(url, queue):
    """
    Download
    """

    yt_dlp_hook_partial = partial(yt_dlp_hook, queue)

    ydl_opts = {
        'quiet': True,
        'noprogress': True,
        'format': 'm4a/bestaudio/best',
        'postprocessors': [{  # Extract audio using ffmpeg
            'key': 'FFmpegExtractAudio',
            'preferredcodec': 'm4a',
        }],
        'outtmpl': 'tmp_output/%(title)s [%(id)s].%(ext)s',
        'progress_hooks': [yt_dlp_hook_partial]
    }

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


def yt_dlp_hook(queue: LifoQueue, download):
    """
    download Hook

    Args:
        download (_type_): _description_
    """
    # Instead of logging the data just add the latest data to the queue
    queue.put(download)


if __name__ == "__main__":
    main()
python yt-dlp

评论


答: 暂无答案