Spidey
Spidey

Reputation: 974

Downloading data directly into a temporary file with python youtube_dl

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.

Upvotes: 5

Views: 5452

Answers (1)

Chris
Chris

Reputation: 96

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.

Upvotes: 6

Related Questions