minor changes
This commit is contained in:
parent
e7b0fd9fff
commit
761786ae4d
40
README.md
40
README.md
|
@ -4,12 +4,12 @@ _Automated YouTube Archival._
|
||||||
|
|
||||||
A wrapper for youtube-dl used for keeping very large amounts of data from YouTube in sync. It's designed to be simple and easy to use.
|
A wrapper for youtube-dl used for keeping very large amounts of data from YouTube in sync. It's designed to be simple and easy to use.
|
||||||
|
|
||||||
I have a single, very large playlist that I add any videos I like to. On my NAS is a service uses this program to download new videos (see [Example systemd Service.md]).
|
I have a single, very large playlist that I add any videos I like to. This runs as a service on my NAS (see [Example systemd Service.md]).
|
||||||
|
|
||||||
### Features
|
### Features
|
||||||
|
|
||||||
- Uses yt-dlp instead of youtube-dl.
|
- Uses yt-dlp instead of youtube-dl.
|
||||||
- Skip videos that are already downloaded which makes checking a playlist for new videos quick because youtube-dl doesn't have to fetch the entire playlist.
|
- Skips videos that are already downloaded.
|
||||||
- Automatically update yt-dlp on launch.
|
- Automatically update yt-dlp on launch.
|
||||||
- Download the videos in a format suitable for archiving:
|
- Download the videos in a format suitable for archiving:
|
||||||
- Complex `format` that balances video quality and file size.
|
- Complex `format` that balances video quality and file size.
|
||||||
|
@ -29,14 +29,44 @@ pip install -r requirements.txt
|
||||||
|
|
||||||
### Usage
|
### Usage
|
||||||
|
|
||||||
`./downloader.py <URL to download or path of a file containing the URLs of the videos to download> <output directory>`
|
This program has 3 modes:
|
||||||
|
|
||||||
|
<br>
|
||||||
|
|
||||||
|
**Direct-Download Mode:**
|
||||||
|
|
||||||
|
In this mode, you give the downloader a URL to the media you want to download.
|
||||||
|
|
||||||
|
`./downloader.py <video URL to download> --output <output directory>`
|
||||||
|
|
||||||
|
<br>
|
||||||
|
|
||||||
|
**Config-File Mode:**
|
||||||
|
|
||||||
|
In this mode, you give the downloader the path to a config file that contains the URLs of the media and where to download them to.
|
||||||
|
|
||||||
|
The config file can be a YAML file or a TXT file with the URL to download on each line.
|
||||||
|
|
||||||
|
When using the YAML file (see [targets.sample.yml]): `./downloader.py <path to the config file>`
|
||||||
|
|
||||||
|
When using a TXT file: `./downloader.py <path to the config file> --output <output directory>`
|
||||||
|
|
||||||
|
<br>
|
||||||
|
|
||||||
|
**Daemon Mode:**
|
||||||
|
|
||||||
|
In this mode, the downloader will loop over the media you give it and sleep for a certain number of minutes. It takes
|
||||||
|
|
||||||
To run as a daemon, do:
|
To run as a daemon, do:
|
||||||
|
|
||||||
`/usr/bin/python3 /home/user/automated-youtube-dl/downloader.py --daemon --sleep 60 <url> <ouput folder>`
|
`/usr/bin/python3 /home/user/automated-youtube-dl/downloader.py --daemon --sleep 60 <video URL or config file path>`
|
||||||
|
|
||||||
`--sleep` is how many minutes to sleep after completing all downloads.
|
`--sleep` is how many minutes to sleep after completing all downloads.
|
||||||
|
|
||||||
|
Daemon mode can take a URL (like direct-download mode) or a path to a config file (like config-file mode).
|
||||||
|
|
||||||
|
<br>
|
||||||
|
|
||||||
#### Folder Structure
|
#### Folder Structure
|
||||||
|
|
||||||
```
|
```
|
||||||
|
@ -56,6 +86,8 @@ Videos will be saved using this name format:
|
||||||
[%(id)s] [%(title)s] [%(uploader)s] [%(uploader_id)s]
|
[%(id)s] [%(title)s] [%(uploader)s] [%(uploader_id)s]
|
||||||
```
|
```
|
||||||
|
|
||||||
|
<br>
|
||||||
|
|
||||||
#### Arguments
|
#### Arguments
|
||||||
|
|
||||||
| Argument | Flag | Help |
|
| Argument | Flag | Help |
|
||||||
|
|
|
@ -18,7 +18,7 @@ from appdirs import user_data_dir
|
||||||
from tqdm.auto import tqdm
|
from tqdm.auto import tqdm
|
||||||
|
|
||||||
from process.funcs import get_silent_logger, remove_duplicates_from_playlist, restart_program, setup_file_logger
|
from process.funcs import get_silent_logger, remove_duplicates_from_playlist, restart_program, setup_file_logger
|
||||||
from process.threads import download_video, bar_eraser
|
from process.threads import bar_eraser, download_video
|
||||||
from ydl.files import create_directories, resolve_path
|
from ydl.files import create_directories, resolve_path
|
||||||
from ydl.yt_dlp import YDL, update_ytdlp
|
from ydl.yt_dlp import YDL, update_ytdlp
|
||||||
|
|
||||||
|
@ -47,7 +47,7 @@ parser.add_argument('--no-update', '-n', action='store_true', help='Don\'t updat
|
||||||
parser.add_argument('--max-size', type=int, default=1100, help='Max allowed size of a video in MB.')
|
parser.add_argument('--max-size', type=int, default=1100, help='Max allowed size of a video in MB.')
|
||||||
parser.add_argument('--rm-cache', '-r', action='store_true', help='Delete the yt-dlp cache on start.')
|
parser.add_argument('--rm-cache', '-r', action='store_true', help='Delete the yt-dlp cache on start.')
|
||||||
parser.add_argument('--threads', type=int, default=(cpu_count() - 1),
|
parser.add_argument('--threads', type=int, default=(cpu_count() - 1),
|
||||||
help=f'How many download processes to use. Default: number of CPU cores (for your machine, {cpu_count()}) - 1 = {cpu_count() - 1}')
|
help=f'How many download processes to use. Default: number of CPU cores (for your machine: {cpu_count()}) - 1 = {cpu_count() - 1}')
|
||||||
parser.add_argument('--daemon', '-d', action='store_true',
|
parser.add_argument('--daemon', '-d', action='store_true',
|
||||||
help="Run in daemon mode. Disables progress bars sleeps for the amount of time specified in --sleep.")
|
help="Run in daemon mode. Disables progress bars sleeps for the amount of time specified in --sleep.")
|
||||||
parser.add_argument('--sleep', type=float, default=60, help='How many minutes to sleep when in daemon mode.')
|
parser.add_argument('--sleep', type=float, default=60, help='How many minutes to sleep when in daemon mode.')
|
||||||
|
@ -93,7 +93,9 @@ log_time = time.time()
|
||||||
|
|
||||||
|
|
||||||
def load_input_file():
|
def load_input_file():
|
||||||
# Get the URLs of the videos to download. Is the input a URL or file?
|
"""
|
||||||
|
Get the URLs of the videos to download. Is the input a URL or file?
|
||||||
|
"""
|
||||||
url_list = {}
|
url_list = {}
|
||||||
if not re.match(url_regex, str(args.file)) or args.input_datatype in ('txt', 'yaml'):
|
if not re.match(url_regex, str(args.file)) or args.input_datatype in ('txt', 'yaml'):
|
||||||
args.file = resolve_path(args.file)
|
args.file = resolve_path(args.file)
|
||||||
|
@ -130,7 +132,9 @@ def load_input_file():
|
||||||
resolved_paths[resolve_path(directory)] = urls
|
resolved_paths[resolve_path(directory)] = urls
|
||||||
url_list = resolved_paths
|
url_list = resolved_paths
|
||||||
else:
|
else:
|
||||||
|
# They gave us just a URL
|
||||||
if not args.output:
|
if not args.output:
|
||||||
|
# Set a default path
|
||||||
args.output = resolve_path(Path(os.getcwd(), 'automated-youtube-dl_output'))
|
args.output = resolve_path(Path(os.getcwd(), 'automated-youtube-dl_output'))
|
||||||
# print('You must specify an output path with --output when the input is a URL.')
|
# print('You must specify an output path with --output when the input is a URL.')
|
||||||
# sys.exit(1)
|
# sys.exit(1)
|
||||||
|
@ -452,7 +456,7 @@ while True:
|
||||||
|
|
||||||
playlist_bar.update()
|
playlist_bar.update()
|
||||||
else:
|
else:
|
||||||
msg = f"All videos already downloaded for '{playlist['title']}'."
|
msg = f"All videos already downloaded for \"{playlist['title']}\"."
|
||||||
if args.daemon:
|
if args.daemon:
|
||||||
logger.info(msg)
|
logger.info(msg)
|
||||||
else:
|
else:
|
||||||
|
|
Reference in New Issue