diff --git a/README.md b/README.md index 219a5d8..010a740 100644 --- a/README.md +++ b/README.md @@ -37,6 +37,7 @@ Certain values can be set via environment variables, using the `-e` parameter on * __AUDIO_DOWNLOAD_DIR__: path to where audio-only downloads will be saved, if you wish to separate them from the video downloads. Defaults to the value of `DOWNLOAD_DIR`. * __URL_PREFIX__: base path for the web server (for use when hosting behind a reverse proxy). Defaults to `/`. * __OUTPUT_TEMPLATE__: the template for the filenames of the downloaded videos, formatted according to [this spec](https://github.com/ytdl-org/youtube-dl/blob/master/README.md#output-template). Defaults to `%(title)s.%(ext)s`. +* __YTDL_OPTIONS__: Additional options to pass to youtube-dl, in JSON format. [See available options here](https://github.com/yt-dlp/yt-dlp/blob/master/yt_dlp/YoutubeDL.py#L176). They roughly correspond to command-line options, though some do not have exact equivalents here, for example `--recode-video` has to be specified via `postprocessors`. Also note that dashes are replaced with underscores. Example value: `{"sleep_interval":10}`. ## Chrome extension diff --git a/app/main.py b/app/main.py index d94967b..000cb28 100644 --- a/app/main.py +++ b/app/main.py @@ -2,6 +2,7 @@ # pylint: disable=no-member,method-hidden import os +import sys from aiohttp import web import socketio import logging @@ -17,6 +18,7 @@ class Config: 'AUDIO_DOWNLOAD_DIR': '%%DOWNLOAD_DIR', 'URL_PREFIX': '', 'OUTPUT_TEMPLATE': '%(title)s.%(ext)s', + 'YTDL_OPTIONS': '{}', } def __init__(self): @@ -27,6 +29,12 @@ class Config: setattr(self, k, getattr(self, v[2:])) if not self.URL_PREFIX.endswith('/'): self.URL_PREFIX += '/' + try: + self.YTDL_OPTIONS = json.loads(self.YTDL_OPTIONS) + assert isinstance(self.YTDL_OPTIONS, dict) + except (json.decoder.JSONDecodeError, AssertionError): + log.error('YTDL_OPTIONS is invalid') + sys.exit(1) config = Config() diff --git a/app/ytdl.py b/app/ytdl.py index ef4ada0..052637d 100644 --- a/app/ytdl.py +++ b/app/ytdl.py @@ -32,7 +32,7 @@ class DownloadInfo: class Download: manager = None - def __init__(self, download_dir, output_template, quality, info): + def __init__(self, download_dir, output_template, quality, ytdl_opts, info): self.download_dir = download_dir self.output_template = output_template if quality == 'best': @@ -46,6 +46,7 @@ class Download: self.format = quality[7:] else: raise Exception(f'unknown quality {quality}') + self.ytdl_opts = ytdl_opts self.info = info self.canceled = False self.tmpfilename = None @@ -77,6 +78,7 @@ class Download: 'cachedir': False, 'socket_timeout': 30, 'progress_hooks': [put_status], + **self.ytdl_opts, }).download([self.info.url]) self.status_queue.put({'status': 'finished' if ret == 0 else 'error'}) except yt_dlp.utils.YoutubeDLError as exc: @@ -161,7 +163,7 @@ class DownloadQueue: if entry['id'] not in self.queue: dl = DownloadInfo(entry['id'], entry['title'], entry.get('webpage_url') or entry['url'], quality) dldirectory = self.config.DOWNLOAD_DIR if quality != 'audio' else self.config.AUDIO_DOWNLOAD_DIR - self.queue[entry['id']] = Download(dldirectory, self.config.OUTPUT_TEMPLATE, quality, dl) + self.queue[entry['id']] = Download(dldirectory, self.config.OUTPUT_TEMPLATE, quality, self.config.YTDL_OPTIONS, dl) self.event.set() await self.notifier.added(dl) return {'status': 'ok'}