Downloading data directly into a temporary file with python youtube_dl
Asked Answered
G

1

5

I'm using python embedded youtube_dl and I'd like to download video content directly into a temporary file. I attempted to create a NamedTemporaryFile and have youtube_dl write into it, but I always get a prompt that the file was already downloaded (the temporary file has that name and it thinks the download already happened).

I also attempted to have youtube_dl stream downloaded data to stdout and redirect stdout to the temporary file but I can't get the python embedded version to do that. It doesn't output to stdout it simply creates a file named -.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=h3h035Eyz5A&ab_channel=Loku"])

To summarize, the code above won't override -.mp4 files if they already exist and it won't stream the download into stdout so I can redirect it into a temp file.

The temp file is needed because it's an intermediary step for further processing. At this point it feels like I'll need to copy the file to temp file and delete the original or I'll need to use youtube_dl with a subprocess which feels silly.

Garbage answered 13/11, 2020 at 17:24 Comment(0)
L
6

I have run into a similar issue before. A good work around I found was to use tempfile.TemporaryDirectory() to temporarily store the file and then open() to retrieve the file.

Looking at the youtube_dl code base, it looks like you want to use extract_info instead of the download method directly.

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=h3h035Eyz5A&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.

Note that you should use snake_case for the arguments (the keys in ydl_opts) since you are not using the cli. I also think recode-video is not a supported option, but check here to be sure.

Also note that I'm assuming that you want to download one video. The code above doesn't account for retrieving playlist from the temp directory, and I intentionally added the noplaylist option to ydl_opts.

Laurenelaurens answered 7/1, 2021 at 10:24 Comment(2)
Ended up copying into temp file and deleting the original because it better fit my use-case. I was also hoping to nudge youtube_dl devs to take this issue into consideration (posted an issue some time ago) but they didn't respond yet. Anyway I'll accept your answer, welcome to stackoverflow.Garbage
Cool, glad you found a solution. Thanks for the welcome.Laurenelaurens

© 2022 - 2024 — McMap. All rights reserved.