Загрузка данных непосредственно во временный файл с помощью python youtube_dl

#python-3.6 #youtube-dl

#python-3.6 #youtube-dl

Вопрос:

Я использую python embedded youtube_dl и хотел бы загружать видеоконтент непосредственно во временный файл. Я попытался создать NamedTemporaryFile и youtube_dl записать в него, но я всегда получаю сообщение о том, что файл уже загружен (временный файл имеет это имя, и он считает, что загрузка уже произошла).

Я также попытался youtube_dl передать загруженные данные stdout во временный файл и перенаправить stdout их во временный файл, но я не могу заставить встроенную версию python сделать это. Он не выводит данные stdout , а просто создает файл с именем -.mp4 .

 import youtube_dl

ydl_opts = {
    "format": "bestvideo[ext=mp4] bestaudio[ext=m4a]/best[ext=mp4]/best",
    "merge-output-format": "mp4",
    "recode-video": "mp4",
    "outtmpl": "-",
    "verbose": True,
}
with youtube_dl.YoutubeDL(ydl_opts) as ydl:
    ydl.download(["https://www.youtube.com/watch?v=h3h035Eyz5Aamp;ab_channel=Loku"])

  

Подводя итог, приведенный выше код не будет переопределять -.mp4 файлы, если они уже существуют, и не будет передавать потоковую загрузку, stdout чтобы я мог перенаправить ее во временный файл.

Временный файл необходим, потому что это промежуточный шаг для дальнейшей обработки. На данный момент мне кажется, что мне нужно скопировать файл во временный файл и удалить оригинал, или мне нужно будет использовать youtube_dl с подпроцессом, который кажется глупым.

Ответ №1:

Я уже сталкивался с подобной проблемой раньше. Хорошим решением, которое я нашел, было использование tempfile.TemporaryDirectory() для временного хранения файла, а затем open() для извлечения файла.

Глядя на базу кода youtube_dl, похоже, что вы хотите использовать extract_info вместо download прямого метода.

 import tempfile

from youtube_dl import YoutubeDL
from youtube_dl.utils import DownloadError

with tempfile.TemporaryDirectory() as tempdirname:
  ydl_opts = {
      "format": "bestvideo[ext=mp4] bestaudio[ext=m4a]/best[ext=mp4]/best",
      "merge_output_format": "mp4",
      "outtmpl": f"{tempdirname}/%(id)s.%(ext)s",
      "noplaylist": True,
      "verbose": True,
  }
  ydl = YoutubeDL(ydl_opts)
  try:
    meta = ydl.extract_info(
      "https://www.youtube.com/watch?v=h3h035Eyz5Aamp;ab_channel=Loku",
      download=True,
    )
  except DownloadError as e:
    raise e
  else:
    video_id = meta["id"]
    video_ext = meta["ext"]
    file = open(f"{tempdirname}/{video_id}.{video_ext}", "rb")
    # whatever else you gotta do bruh...
    # when the with statement finishes execution, the temp directory
    # will be cleaned up.
  

Обратите внимание, что вы должны использовать snake_case для аргументов (ключей в ydl_opts ), поскольку вы не используете cli. Я также думаю recode-video , что это не поддерживаемый вариант, но проверьте здесь, чтобы убедиться.

Также обратите внимание, что я предполагаю, что вы хотите загрузить одно видео. Приведенный выше код не учитывает получение списка воспроизведения из каталога temp, и я намеренно добавил эту noplaylist опцию ydl_opts .

Комментарии:

1. В итоге я скопировал во временный файл и удалил оригинал, потому что он лучше подходит для моего варианта использования. Я также надеялся подтолкнуть youtube_dl разработчиков к рассмотрению этой проблемы (опубликовал проблему некоторое время назад), но они еще не ответили. В любом случае я принимаю ваш ответ, добро пожаловать в stackoverflow.

2. Круто, рад, что вы нашли решение. Спасибо за приветствие.