youtube-dl 同时下载多个
youtbe-dl multiple downloads at the same time
我有一个 python 应用程序,其中有一个包含多个网址的变量。
此时我使用这样的东西:
for v in arr:
cmd = 'youtube-dl -u ' + email + ' -p ' + password + ' -o "' + v['path'] + '" ' + v['url']
os.system(cmd)
但这样我就一个接一个地下载视频。如何同时下载 3 个视频? (不是来自 youtube,所以没有播放列表或频道)
我不需要在 python 中使用多线程,而是多次调用 youtube-dl,拆分数组。所以从python的角度来看可以上线程
使用 Pool
:
import multiprocessing.dummy
import subprocess
arr = [
{'vpath': 'example/%(title)s.%(ext)s', 'url': 'https://www.youtube.com/watch?v=BaW_jenozKc'},
{'vpath': 'example/%(title)s.%(ext)s', 'url': 'http://vimeo.com/56015672'},
{'vpath': '%(playlist_title)s/%(title)s-%(id)s.%(ext)s',
'url': 'https://www.youtube.com/playlist?list=PLLe-WjSmNEm-UnVV8e4qI9xQyI0906hNp'},
]
email = 'my-email@example.com'
password = '123456'
def download(v):
subprocess.check_call([
'echo', 'youtube-dl',
'-u', email, '-p', password,
'-o', v['vpath'], '--', v['url']])
p = multiprocessing.dummy.Pool(concurrent)
p.map(download, arr)
multiprocessing.dummy.Pool
是一个Pool
的基于线程的轻量级版本,它更适合这里,因为工作任务只是启动子进程。
请注意,您之前的代码中的 os.system
不是 subprocess.check_call
, which prevents the command injection vulnerability。
还要注意 youtube-dl output templates 真的很强大。在大多数情况下,您实际上不需要自己定义和管理文件名。
我使用 threading
库实现了同样的事情,这被认为是生成新进程的一种更轻松的方法。
假设:
- 每个任务都会将视频下载到不同的目录。
import os
import threading
import youtube_dl
COOKIE_JAR = "path_to_my_cookie_jar"
def download_task(videos, output_dir):
if not os.path.isdir(output_dir):
os.makedirs(output_dir)
if not os.path.isfile(COOKIE_JAR):
raise FileNotFoundError("Cookie Jar not found\n")
ydl_opts = {
'cookiefile': COOKIE_JAR,
'outtmpl': f'{output_dir}/%(title)s.%(ext)s'
}
with youtube_dl.YoutubeDL(ydl_opts) as ydl:
ydl.download(videos)
if __name__ == "__main__":
output_dir = "./root_dir"
threads = []
for playlist in many_playlists:
output_dir = f"{output_dir}/playlist.name"
thread = threading.Thread(target=download_task, args=(playlist, output_dir))
threads.append(thread)
# Actually start downloading
for thread in threads:
thread.start()
# Wait for all the downloads to complete
for thread in threads:
thread.join()
我有一个 python 应用程序,其中有一个包含多个网址的变量。
此时我使用这样的东西:
for v in arr:
cmd = 'youtube-dl -u ' + email + ' -p ' + password + ' -o "' + v['path'] + '" ' + v['url']
os.system(cmd)
但这样我就一个接一个地下载视频。如何同时下载 3 个视频? (不是来自 youtube,所以没有播放列表或频道)
我不需要在 python 中使用多线程,而是多次调用 youtube-dl,拆分数组。所以从python的角度来看可以上线程
使用 Pool
:
import multiprocessing.dummy
import subprocess
arr = [
{'vpath': 'example/%(title)s.%(ext)s', 'url': 'https://www.youtube.com/watch?v=BaW_jenozKc'},
{'vpath': 'example/%(title)s.%(ext)s', 'url': 'http://vimeo.com/56015672'},
{'vpath': '%(playlist_title)s/%(title)s-%(id)s.%(ext)s',
'url': 'https://www.youtube.com/playlist?list=PLLe-WjSmNEm-UnVV8e4qI9xQyI0906hNp'},
]
email = 'my-email@example.com'
password = '123456'
def download(v):
subprocess.check_call([
'echo', 'youtube-dl',
'-u', email, '-p', password,
'-o', v['vpath'], '--', v['url']])
p = multiprocessing.dummy.Pool(concurrent)
p.map(download, arr)
multiprocessing.dummy.Pool
是一个Pool
的基于线程的轻量级版本,它更适合这里,因为工作任务只是启动子进程。
请注意,您之前的代码中的 os.system
不是 subprocess.check_call
, which prevents the command injection vulnerability。
还要注意 youtube-dl output templates 真的很强大。在大多数情况下,您实际上不需要自己定义和管理文件名。
我使用 threading
库实现了同样的事情,这被认为是生成新进程的一种更轻松的方法。
假设:
- 每个任务都会将视频下载到不同的目录。
import os
import threading
import youtube_dl
COOKIE_JAR = "path_to_my_cookie_jar"
def download_task(videos, output_dir):
if not os.path.isdir(output_dir):
os.makedirs(output_dir)
if not os.path.isfile(COOKIE_JAR):
raise FileNotFoundError("Cookie Jar not found\n")
ydl_opts = {
'cookiefile': COOKIE_JAR,
'outtmpl': f'{output_dir}/%(title)s.%(ext)s'
}
with youtube_dl.YoutubeDL(ydl_opts) as ydl:
ydl.download(videos)
if __name__ == "__main__":
output_dir = "./root_dir"
threads = []
for playlist in many_playlists:
output_dir = f"{output_dir}/playlist.name"
thread = threading.Thread(target=download_task, args=(playlist, output_dir))
threads.append(thread)
# Actually start downloading
for thread in threads:
thread.start()
# Wait for all the downloads to complete
for thread in threads:
thread.join()