From 129cce49b17f0a481227aafa170a495fea9e4f50 Mon Sep 17 00:00:00 2001 From: ymir Date: Mon, 26 Jan 2026 21:14:27 +0000 Subject: [PATCH] Misc changes --- .env/share/bash-completion/completions/yt-dlp | 2 +- .env/share/doc/yt_dlp/README.txt | 123 +++++++++++++----- .../fish/vendor_completions.d/yt-dlp.fish | 6 +- .env/share/man/man1/yt-dlp.1 | 118 +++++++++++++---- .env/share/zsh/site-functions/_yt-dlp | 6 +- .gitignore | 1 + download_youtube.py | 1 + make_folders.py | 36 +++-- 8 files changed, 215 insertions(+), 78 deletions(-) diff --git a/.env/share/bash-completion/completions/yt-dlp b/.env/share/bash-completion/completions/yt-dlp index f7963ef..2fb4447 100644 --- a/.env/share/bash-completion/completions/yt-dlp +++ b/.env/share/bash-completion/completions/yt-dlp @@ -4,7 +4,7 @@ __yt_dlp() COMPREPLY=() cur="${COMP_WORDS[COMP_CWORD]}" prev="${COMP_WORDS[COMP_CWORD-1]}" - opts="--help --version --update --no-update --update-to --ignore-errors --no-abort-on-error --abort-on-error --list-extractors --extractor-descriptions --use-extractors --force-generic-extractor --default-search --ignore-config --no-config-locations --config-locations --plugin-dirs --no-plugin-dirs --flat-playlist --no-flat-playlist --live-from-start --no-live-from-start --wait-for-video --no-wait-for-video --mark-watched --no-mark-watched --no-colors --color --compat-options --alias --preset-alias --proxy --socket-timeout --source-address --impersonate --list-impersonate-targets --force-ipv4 --force-ipv6 --enable-file-urls --geo-verification-proxy --xff --geo-bypass --no-geo-bypass --geo-bypass-country --geo-bypass-ip-block --playlist-start --playlist-end --playlist-items --match-title --reject-title --min-filesize --max-filesize --date --datebefore --dateafter --min-views --max-views --match-filters --no-match-filters --break-match-filters --no-break-match-filters --no-playlist --yes-playlist --age-limit --download-archive --no-download-archive --max-downloads --break-on-existing --no-break-on-existing --break-on-reject --break-per-input --no-break-per-input --skip-playlist-after-errors --concurrent-fragments --limit-rate --throttled-rate --retries --file-access-retries --fragment-retries --retry-sleep --skip-unavailable-fragments --abort-on-unavailable-fragments --keep-fragments --no-keep-fragments --buffer-size --resize-buffer --no-resize-buffer --http-chunk-size --test --playlist-reverse --no-playlist-reverse --playlist-random --lazy-playlist --no-lazy-playlist --hls-prefer-native --hls-prefer-ffmpeg --hls-use-mpegts --no-hls-use-mpegts --download-sections --downloader --downloader-args --batch-file --no-batch-file --id --paths --output --output-na-placeholder --autonumber-size --autonumber-start --restrict-filenames --no-restrict-filenames --windows-filenames --no-windows-filenames --trim-filenames --no-overwrites --force-overwrites --no-force-overwrites --continue --no-continue --part --no-part --mtime --no-mtime --write-description --no-write-description --write-info-json --no-write-info-json --write-playlist-metafiles --no-write-playlist-metafiles --clean-info-json --no-clean-info-json --write-comments --no-write-comments --load-info-json --cookies --no-cookies --cookies-from-browser --no-cookies-from-browser --cache-dir --no-cache-dir --rm-cache-dir --write-thumbnail --no-write-thumbnail --write-all-thumbnails --list-thumbnails --write-link --write-url-link --write-webloc-link --write-desktop-link --quiet --no-quiet --no-warnings --simulate --no-simulate --ignore-no-formats-error --no-ignore-no-formats-error --skip-download --print --print-to-file --get-url --get-title --get-id --get-thumbnail --get-description --get-duration --get-filename --get-format --dump-json --dump-single-json --print-json --force-write-archive --newline --no-progress --progress --console-title --progress-template --progress-delta --verbose --dump-pages --write-pages --load-pages --print-traffic --encoding --legacy-server-connect --no-check-certificates --prefer-insecure --user-agent --referer --add-headers --bidi-workaround --sleep-requests --sleep-interval --max-sleep-interval --sleep-subtitles --format --format-sort --format-sort-force --no-format-sort-force --video-multistreams --no-video-multistreams --audio-multistreams --no-audio-multistreams --all-formats --prefer-free-formats --no-prefer-free-formats --check-formats --check-all-formats --no-check-formats --list-formats --list-formats-as-table --list-formats-old --merge-output-format --allow-unplayable-formats --no-allow-unplayable-formats --write-subs --no-write-subs --write-auto-subs --no-write-auto-subs --all-subs --list-subs --sub-format --sub-langs --username --password --twofactor --netrc --netrc-location --netrc-cmd --video-password --ap-mso --ap-username --ap-password --ap-list-mso --client-certificate --client-certificate-key --client-certificate-password --extract-audio --audio-format --audio-quality --remux-video --recode-video --postprocessor-args --keep-video --no-keep-video --post-overwrites --no-post-overwrites --embed-subs --no-embed-subs --embed-thumbnail --no-embed-thumbnail --embed-metadata --no-embed-metadata --embed-chapters --no-embed-chapters --embed-info-json --no-embed-info-json --metadata-from-title --parse-metadata --replace-in-metadata --xattrs --concat-playlist --fixup --ffmpeg-location --exec --no-exec --exec-before-download --no-exec-before-download --convert-subs --convert-thumbnails --split-chapters --no-split-chapters --remove-chapters --no-remove-chapters --force-keyframes-at-cuts --no-force-keyframes-at-cuts --use-postprocessor --sponsorblock-mark --sponsorblock-remove --sponsorblock-chapter-title --no-sponsorblock --sponsorblock-api --extractor-retries --allow-dynamic-mpd --ignore-dynamic-mpd --hls-split-discontinuity --no-hls-split-discontinuity --extractor-args" + opts="--help --version --update --no-update --update-to --ignore-errors --no-abort-on-error --abort-on-error --list-extractors --extractor-descriptions --use-extractors --force-generic-extractor --default-search --ignore-config --no-config-locations --config-locations --plugin-dirs --no-plugin-dirs --js-runtimes --no-js-runtimes --remote-components --no-remote-components --flat-playlist --no-flat-playlist --live-from-start --no-live-from-start --wait-for-video --no-wait-for-video --mark-watched --no-mark-watched --no-colors --color --compat-options --alias --preset-alias --proxy --socket-timeout --source-address --impersonate --list-impersonate-targets --force-ipv4 --force-ipv6 --enable-file-urls --geo-verification-proxy --xff --geo-bypass --no-geo-bypass --geo-bypass-country --geo-bypass-ip-block --playlist-start --playlist-end --playlist-items --match-title --reject-title --min-filesize --max-filesize --date --datebefore --dateafter --min-views --max-views --match-filters --no-match-filters --break-match-filters --no-break-match-filters --no-playlist --yes-playlist --age-limit --download-archive --no-download-archive --max-downloads --break-on-existing --no-break-on-existing --break-on-reject --break-per-input --no-break-per-input --skip-playlist-after-errors --concurrent-fragments --limit-rate --throttled-rate --retries --file-access-retries --fragment-retries --retry-sleep --skip-unavailable-fragments --abort-on-unavailable-fragments --keep-fragments --no-keep-fragments --buffer-size --resize-buffer --no-resize-buffer --http-chunk-size --test --playlist-reverse --no-playlist-reverse --playlist-random --lazy-playlist --no-lazy-playlist --hls-prefer-native --hls-prefer-ffmpeg --hls-use-mpegts --no-hls-use-mpegts --download-sections --downloader --downloader-args --batch-file --no-batch-file --id --paths --output --output-na-placeholder --autonumber-size --autonumber-start --restrict-filenames --no-restrict-filenames --windows-filenames --no-windows-filenames --trim-filenames --no-overwrites --force-overwrites --no-force-overwrites --continue --no-continue --part --no-part --mtime --no-mtime --write-description --no-write-description --write-info-json --no-write-info-json --write-playlist-metafiles --no-write-playlist-metafiles --clean-info-json --no-clean-info-json --write-comments --no-write-comments --load-info-json --cookies --no-cookies --cookies-from-browser --no-cookies-from-browser --cache-dir --no-cache-dir --rm-cache-dir --write-thumbnail --no-write-thumbnail --write-all-thumbnails --list-thumbnails --write-link --write-url-link --write-webloc-link --write-desktop-link --quiet --no-quiet --no-warnings --simulate --no-simulate --ignore-no-formats-error --no-ignore-no-formats-error --skip-download --print --print-to-file --get-url --get-title --get-id --get-thumbnail --get-description --get-duration --get-filename --get-format --dump-json --dump-single-json --print-json --force-write-archive --newline --no-progress --progress --console-title --progress-template --progress-delta --verbose --dump-pages --write-pages --load-pages --print-traffic --encoding --legacy-server-connect --no-check-certificates --prefer-insecure --user-agent --referer --add-headers --bidi-workaround --sleep-requests --sleep-interval --max-sleep-interval --sleep-subtitles --format --format-sort --format-sort-force --no-format-sort-force --video-multistreams --no-video-multistreams --audio-multistreams --no-audio-multistreams --all-formats --prefer-free-formats --no-prefer-free-formats --check-formats --check-all-formats --no-check-formats --list-formats --list-formats-as-table --list-formats-old --merge-output-format --allow-unplayable-formats --no-allow-unplayable-formats --write-subs --no-write-subs --write-auto-subs --no-write-auto-subs --all-subs --list-subs --sub-format --sub-langs --username --password --twofactor --netrc --netrc-location --netrc-cmd --video-password --ap-mso --ap-username --ap-password --ap-list-mso --client-certificate --client-certificate-key --client-certificate-password --extract-audio --audio-format --audio-quality --remux-video --recode-video --postprocessor-args --keep-video --no-keep-video --post-overwrites --no-post-overwrites --embed-subs --no-embed-subs --embed-thumbnail --no-embed-thumbnail --embed-metadata --no-embed-metadata --embed-chapters --no-embed-chapters --embed-info-json --no-embed-info-json --metadata-from-title --parse-metadata --replace-in-metadata --xattrs --concat-playlist --fixup --ffmpeg-location --exec --no-exec --exec-before-download --no-exec-before-download --convert-subs --convert-thumbnails --split-chapters --no-split-chapters --remove-chapters --no-remove-chapters --force-keyframes-at-cuts --no-force-keyframes-at-cuts --use-postprocessor --sponsorblock-mark --sponsorblock-remove --sponsorblock-chapter-title --no-sponsorblock --sponsorblock-api --extractor-retries --allow-dynamic-mpd --ignore-dynamic-mpd --hls-split-discontinuity --no-hls-split-discontinuity --extractor-args" keywords=":ytfavorites :ytrecommended :ytsubscriptions :ytwatchlater :ythistory" fileopts="-a|--batch-file|--download-archive|--cookies|--load-info-json" diropts="--cache-dir" diff --git a/.env/share/doc/yt_dlp/README.txt b/.env/share/doc/yt_dlp/README.txt index 09c59aa..c4274e8 100644 --- a/.env/share/doc/yt_dlp/README.txt +++ b/.env/share/doc/yt_dlp/README.txt @@ -168,11 +168,14 @@ contain code from other projects with different licenses. Most notably, the PyInstaller-bundled executables include GPLv3+ licensed code, and as such the combined work is licensed under GPLv3+. -See THIRD_PARTY_LICENSES.txt for details. +The zipimport Unix executable (yt-dlp) contains ISC licensed code from +meriyah and MIT licensed code from astring. -The zipimport binary (yt-dlp), the source tarball (yt-dlp.tar.gz), and -the PyPI source distribution & wheel only contain code licensed under -the Unlicense. +See THIRD_PARTY_LICENSES.txt for more details. + +The git repository, the source tarball (yt-dlp.tar.gz), the PyPI source +distribution and the PyPI built distribution (wheel) only contain code +licensed under the Unlicense. Note: The manpages, shell completion (autocomplete) files etc. are available inside the source tarball @@ -231,7 +234,7 @@ install or update to the nightly release before submitting a bug report: yt-dlp --update-to nightly # To install nightly with pip: - python3 -m pip install -U --pre "yt-dlp[default]" + python -m pip install -U --pre "yt-dlp[default]" When running a yt-dlp version that is older than 90 days, you will see a warning message suggesting to update to the latest version. You can @@ -240,11 +243,11 @@ configuration file. DEPENDENCIES -Python versions 3.9+ (CPython) and 3.11+ (PyPy) are supported. Other +Python versions 3.10+ (CPython) and 3.11+ (PyPy) are supported. Other versions and implementations may or may not work correctly. -While all the other dependencies are optional, ffmpeg and ffprobe are -highly recommended +While all the other dependencies are optional, ffmpeg, ffprobe, +yt-dlp-ejs and a JavaScript runtime are highly recommended Strongly recommended @@ -261,6 +264,12 @@ Strongly recommended Important: What you need is ffmpeg binary, NOT the Python package of the same name +- yt-dlp-ejs - Required for deciphering YouTube n/sig values. Licensed + under Unlicense, bundles MIT and ISC components. + + A JavaScript runtime like deno (recommended), node.js, bun, or + QuickJS is also required to run yt-dlp-ejs. See the wiki. + Networking - certifi* - Provides Mozilla's root certificate bundle. Licensed @@ -299,8 +308,9 @@ Misc - pycryptodomex* - For decrypting AES-128 HLS streams and various other data. Licensed under BSD-2-Clause -- phantomjs - Used in extractors where javascript needs to be run. - Licensed under BSD-3-Clause +- phantomjs - Used in some extractors where JavaScript needs to be + run. No longer used for YouTube. To be deprecated in the near + future. Licensed under BSD-3-Clause - secretstorage* - For --cookies-from-browser to access the Gnome keyring while decrypting cookies of Chromium-based browsers on Linux. Licensed under BSD-3-Clause @@ -333,11 +343,11 @@ will be built for the same CPU architecture as the Python used. You can run the following commands: - python3 devscripts/install_deps.py --include pyinstaller - python3 devscripts/make_lazy_extractors.py - python3 -m bundle.pyinstaller + python devscripts/install_deps.py --include-group pyinstaller + python devscripts/make_lazy_extractors.py + python -m bundle.pyinstaller -On some systems, you may need to use py or python instead of python3. +On some systems, you may need to use py or python3 instead of python. python -m bundle.pyinstaller accepts any arguments that can be passed to pyinstaller, such as --onefile/-F or --onedir/-D, which is further @@ -352,7 +362,7 @@ may not work correctly. Platform-independent Binary (UNIX) -You will need the build tools python (3.9+), zip, make (GNU), pandoc* +You will need the build tools python (3.10+), zip, make (GNU), pandoc* and pytest*. After installing these, simply run make. @@ -444,7 +454,7 @@ General Options: containing directory ("-" for stdin). Can be used multiple times and inside other configuration files - --plugin-dirs PATH Path to an additional directory to search + --plugin-dirs DIR Path to an additional directory to search for plugins. This option can be used multiple times to add multiple directories. Use "default" to search the default plugin @@ -452,6 +462,37 @@ General Options: --no-plugin-dirs Clear plugin directories to search, including defaults and those provided by previous --plugin-dirs + --js-runtimes RUNTIME[:PATH] Additional JavaScript runtime to enable, + with an optional location for the runtime + (either the path to the binary or its + containing directory). This option can be + used multiple times to enable multiple + runtimes. Supported runtimes are (in order + of priority, from highest to lowest): deno, + node, quickjs, bun. Only "deno" is enabled + by default. The highest priority runtime + that is both enabled and available will be + used. In order to use a lower priority + runtime when "deno" is available, --no-js- + runtimes needs to be passed before enabling + other runtimes + --no-js-runtimes Clear JavaScript runtimes to enable, + including defaults and those provided by + previous --js-runtimes + --remote-components COMPONENT Remote components to allow yt-dlp to fetch + when required. This option is currently not + needed if you are using an official + executable or have the requisite version of + the yt-dlp-ejs package installed. You can + use this option multiple times to allow + multiple components. Supported values: + ejs:npm (external JavaScript components from + npm), ejs:github (external JavaScript + components from yt-dlp-ejs GitHub). By + default, no remote components are allowed + --no-remote-components Disallow fetching of all remote components, + including any previously allowed by + --remote-components or defaults. --flat-playlist Do not extract a playlist's URL result entries; some entry metadata may be missing and downloading may be bypassed @@ -1183,11 +1224,12 @@ SponsorBlock API for, separated by commas. Available categories are sponsor, intro, outro, selfpromo, preview, filler, interaction, - music_offtopic, poi_highlight, chapter, all - and default (=all). You can prefix the - category with a "-" to exclude it. See [1] - for descriptions of the categories. E.g. - --sponsorblock-mark all,-preview + music_offtopic, hook, poi_highlight, + chapter, all and default (=all). You can + prefix the category with a "-" to exclude + it. See [1] for descriptions of the + categories. E.g. --sponsorblock-mark + all,-preview [1] https://wiki.sponsor.ajay.app/w/Segment_Categories --sponsorblock-remove CATS SponsorBlock categories to be removed from the video file, separated by commas. If a @@ -1256,7 +1298,7 @@ a configuration file. The configuration is loaded from the following locations: 1. Main Configuration: - - The file given to --config-location + - The file given to --config-locations 2. Portable Configuration: (Recommended for portable installations) - If using a binary, yt-dlp.conf in the same directory as the binary @@ -1371,7 +1413,7 @@ Notes about environment variables ${VARIABLE}/$VARIABLE on UNIX and %VARIABLE% on Windows; but is always shown as ${VARIABLE} in this documentation - yt-dlp also allows using UNIX-style variables on Windows for - path-like options; e.g. --output, --config-location + path-like options; e.g. --output, --config-locations - If unset, ${XDG_CONFIG_HOME} defaults to ~/.config and ${XDG_CACHE_HOME} to ~/.cache - On Windows, ~ points to ${HOME} if present; or, ${USERPROFILE} or @@ -2253,13 +2295,17 @@ youtube respectively - player_client: Clients to extract video data from. The currently available clients are web, web_safari, web_embedded, web_music, - web_creator, mweb, ios, android, android_vr, tv, tv_simply and - tv_embedded. By default, tv,web_safari,web is used, and - tv,web_creator,web is used with premium accounts. The web_music - client is added for music.youtube.com URLs when logged-in cookies - are used. The web_embedded client is added for age-restricted videos - but only works if the video is embeddable. The tv_embedded and - web_creator clients are added for age-restricted videos if account + web_creator, mweb, ios, android, android_sdkless, android_vr, tv, + tv_simply, tv_downgraded, and tv_embedded. By default, + tv,android_sdkless,web is used. If no JavaScript runtime is + available, then android_sdkless,web_safari,web is used. If logged-in + cookies are passed to yt-dlp, then tv_downgraded,web_safari,web is + used for free accounts and tv_downgraded,web_creator,web is used for + premium accounts. The web_music client is added for + music.youtube.com URLs when logged-in cookies are used. The + web_embedded client is added for age-restricted videos but only + works if the video is embeddable. The tv_embedded and web_creator + clients are added for age-restricted videos if account age-verification is required. Some clients, such as web and web_music, require a po_token for their formats to be downloadable. Some clients, such as web_creator, will only work with @@ -2285,9 +2331,9 @@ youtube debugging purposes. You can use actual to go with what is prescribed by the site - player_js_version: The player javascript version to use for n/sig - deciphering, in the format of signature_timestamp@hash. Currently, - the default is to force 20348@0004de42. You can use actual to go - with what is prescribed by the site + deciphering, in the format of signature_timestamp@hash (e.g. + 20348@0004de42). The default is to use what is prescribed by the + site, and can be selected with actual - comment_sort: top or new (default) - choose comment sorting mode (on YouTube's side) - max_comments: Limit the amount of comments to gather. @@ -2332,6 +2378,15 @@ youtube - playback_wait: Duration (in seconds) to wait inbetween the extraction and download stages in order to ensure the formats are available. The default is 6 seconds +- jsc_trace: Enable debug logging for JS Challenge fetching. Either + true or false (default) + +youtube-ejs + +- jitless: Run suported Javascript engines in JIT-less mode. Supported + runtimes are deno, node and bun. Provides better security at the + cost of performance/speed. Do note that node and bun are still + considered unsecure. Either true or false (default) youtubepot-webpo @@ -2919,7 +2974,7 @@ Differences in default behavior Some of yt-dlp's default options are different from that of youtube-dl and youtube-dlc: -- yt-dlp supports only Python 3.9+, and will remove support for more +- yt-dlp supports only Python 3.10+, and will remove support for more versions as they become EOL; while youtube-dl still supports Python 2.6+ and 3.2+ - The options --auto-number (-A), --title (-t) and --literal (-l), no diff --git a/.env/share/fish/vendor_completions.d/yt-dlp.fish b/.env/share/fish/vendor_completions.d/yt-dlp.fish index 78734d6..8750971 100644 --- a/.env/share/fish/vendor_completions.d/yt-dlp.fish +++ b/.env/share/fish/vendor_completions.d/yt-dlp.fish @@ -17,6 +17,10 @@ complete --command yt-dlp --long-option no-config-locations --description 'Do no complete --command yt-dlp --long-option config-locations --description 'Location of the main configuration file; either the path to the config or its containing directory ("-" for stdin). Can be used multiple times and inside other configuration files' complete --command yt-dlp --long-option plugin-dirs --description 'Path to an additional directory to search for plugins. This option can be used multiple times to add multiple directories. Use "default" to search the default plugin directories (default)' complete --command yt-dlp --long-option no-plugin-dirs --description 'Clear plugin directories to search, including defaults and those provided by previous --plugin-dirs' +complete --command yt-dlp --long-option js-runtimes --description 'Additional JavaScript runtime to enable, with an optional location for the runtime (either the path to the binary or its containing directory). This option can be used multiple times to enable multiple runtimes. Supported runtimes are (in order of priority, from highest to lowest): deno, node, quickjs, bun. Only "deno" is enabled by default. The highest priority runtime that is both enabled and available will be used. In order to use a lower priority runtime when "deno" is available, --no-js-runtimes needs to be passed before enabling other runtimes' +complete --command yt-dlp --long-option no-js-runtimes --description 'Clear JavaScript runtimes to enable, including defaults and those provided by previous --js-runtimes' +complete --command yt-dlp --long-option remote-components --description 'Remote components to allow yt-dlp to fetch when required. This option is currently not needed if you are using an official executable or have the requisite version of the yt-dlp-ejs package installed. You can use this option multiple times to allow multiple components. Supported values: ejs:npm (external JavaScript components from npm), ejs:github (external JavaScript components from yt-dlp-ejs GitHub). By default, no remote components are allowed' +complete --command yt-dlp --long-option no-remote-components --description 'Disallow fetching of all remote components, including any previously allowed by --remote-components or defaults.' complete --command yt-dlp --long-option flat-playlist --description 'Do not extract a playlist'"'"'s URL result entries; some entry metadata may be missing and downloading may be bypassed' complete --command yt-dlp --long-option no-flat-playlist --description 'Fully extract the videos of a playlist (default)' complete --command yt-dlp --long-option live-from-start --description 'Download livestreams from the start. Currently experimental and only supported for YouTube and Twitch' @@ -275,7 +279,7 @@ complete --command yt-dlp --long-option no-remove-chapters --description 'Do not complete --command yt-dlp --long-option force-keyframes-at-cuts --description 'Force keyframes at cuts when downloading/splitting/removing sections. This is slow due to needing a re-encode, but the resulting video may have fewer artifacts around the cuts' complete --command yt-dlp --long-option no-force-keyframes-at-cuts --description 'Do not force keyframes around the chapters when cutting/splitting (default)' complete --command yt-dlp --long-option use-postprocessor --description 'The (case-sensitive) name of plugin postprocessors to be enabled, and (optionally) arguments to be passed to it, separated by a colon ":". ARGS are a semicolon ";" delimited list of NAME=VALUE. The "when" argument determines when the postprocessor is invoked. It can be one of "pre_process" (after video extraction), "after_filter" (after video passes filter), "video" (after --format; before --print/--output), "before_dl" (before each video download), "post_process" (after each video download; default), "after_move" (after moving the video file to its final location), "after_video" (after downloading and processing all formats of a video), or "playlist" (at end of playlist). This option can be used multiple times to add different postprocessors' -complete --command yt-dlp --long-option sponsorblock-mark --description 'SponsorBlock categories to create chapters for, separated by commas. Available categories are sponsor, intro, outro, selfpromo, preview, filler, interaction, music_offtopic, poi_highlight, chapter, all and default (=all). You can prefix the category with a "-" to exclude it. See [1] for descriptions of the categories. E.g. --sponsorblock-mark all,-preview [1] https://wiki.sponsor.ajay.app/w/Segment_Categories' +complete --command yt-dlp --long-option sponsorblock-mark --description 'SponsorBlock categories to create chapters for, separated by commas. Available categories are sponsor, intro, outro, selfpromo, preview, filler, interaction, music_offtopic, hook, poi_highlight, chapter, all and default (=all). You can prefix the category with a "-" to exclude it. See [1] for descriptions of the categories. E.g. --sponsorblock-mark all,-preview [1] https://wiki.sponsor.ajay.app/w/Segment_Categories' complete --command yt-dlp --long-option sponsorblock-remove --description 'SponsorBlock categories to be removed from the video file, separated by commas. If a category is present in both mark and remove, remove takes precedence. The syntax and available categories are the same as for --sponsorblock-mark except that "default" refers to "all,-filler" and poi_highlight, chapter are not available' complete --command yt-dlp --long-option sponsorblock-chapter-title --description 'An output template for the title of the SponsorBlock chapters created by --sponsorblock-mark. The only available fields are start_time, end_time, category, categories, name, category_names. Defaults to "%default"' complete --command yt-dlp --long-option no-sponsorblock --description 'Disable both --sponsorblock-mark and --sponsorblock-remove' diff --git a/.env/share/man/man1/yt-dlp.1 b/.env/share/man/man1/yt-dlp.1 index 723cc0b..3592aa7 100644 --- a/.env/share/man/man1/yt-dlp.1 +++ b/.env/share/man/man1/yt-dlp.1 @@ -109,7 +109,7 @@ Location of the main configuration file; either the path to the config or its containing directory (\[dq]-\[dq] for stdin). Can be used multiple times and inside other configuration files .TP ---plugin-dirs \f[I]PATH\f[R] +--plugin-dirs \f[I]DIR\f[R] Path to an additional directory to search for plugins. This option can be used multiple times to add multiple directories. Use \[dq]default\[dq] to search the default plugin directories (default) @@ -118,6 +118,37 @@ Use \[dq]default\[dq] to search the default plugin directories (default) Clear plugin directories to search, including defaults and those provided by previous --plugin-dirs .TP +--js-runtimes \f[I]RUNTIME[:PATH]\f[R] +Additional JavaScript runtime to enable, with an optional location for +the runtime (either the path to the binary or its containing directory). +This option can be used multiple times to enable multiple runtimes. +Supported runtimes are (in order of priority, from highest to lowest): +deno, node, quickjs, bun. +Only \[dq]deno\[dq] is enabled by default. +The highest priority runtime that is both enabled and available will be +used. +In order to use a lower priority runtime when \[dq]deno\[dq] is +available, --no-js- runtimes needs to be passed before enabling other +runtimes +.TP +--no-js-runtimes +Clear JavaScript runtimes to enable, including defaults and those +provided by previous --js-runtimes +.TP +--remote-components \f[I]COMPONENT\f[R] +Remote components to allow yt-dlp to fetch when required. +This option is currently not needed if you are using an official +executable or have the requisite version of the yt-dlp-ejs package +installed. +You can use this option multiple times to allow multiple components. +Supported values: ejs:npm (external JavaScript components from npm), +ejs:github (external JavaScript components from yt-dlp-ejs GitHub). +By default, no remote components are allowed +.TP +--no-remote-components +Disallow fetching of all remote components, including any previously +allowed by --remote-components or defaults. +.TP --flat-playlist Do not extract a playlist\[aq]s URL result entries; some entry metadata may be missing and downloading may be bypassed @@ -1123,8 +1154,8 @@ API (https://sponsor.ajay.app) --sponsorblock-mark \f[I]CATS\f[R] SponsorBlock categories to create chapters for, separated by commas. Available categories are sponsor, intro, outro, selfpromo, preview, -filler, interaction, music_offtopic, poi_highlight, chapter, all and -default (=all). +filler, interaction, music_offtopic, hook, poi_highlight, chapter, all +and default (=all). You can prefix the category with a \[dq]-\[dq] to exclude it. See [1] for descriptions of the categories. E.g. @@ -1210,7 +1241,7 @@ The configuration is loaded from the following locations: \f[B]Main Configuration\f[R]: .RS 4 .IP \[bu] 2 -The file given to \f[V]--config-location\f[R] +The file given to \f[V]--config-locations\f[R] .RE .IP "2." 3 \f[B]Portable Configuration\f[R]: (Recommended for portable @@ -1389,7 +1420,7 @@ Environment variables are normally specified as .IP \[bu] 2 yt-dlp also allows using UNIX-style variables on Windows for path-like options; e.g. -\f[V]--output\f[R], \f[V]--config-location\f[R] +\f[V]--output\f[R], \f[V]--config-locations\f[R] .IP \[bu] 2 If unset, \f[V]${XDG_CONFIG_HOME}\f[R] defaults to \f[V]\[ti]/.config\f[R] and \f[V]${XDG_CACHE_HOME}\f[R] to @@ -2660,10 +2691,15 @@ respectively \f[V]player_client\f[R]: Clients to extract video data from. The currently available clients are \f[V]web\f[R], \f[V]web_safari\f[R], \f[V]web_embedded\f[R], \f[V]web_music\f[R], \f[V]web_creator\f[R], -\f[V]mweb\f[R], \f[V]ios\f[R], \f[V]android\f[R], \f[V]android_vr\f[R], -\f[V]tv\f[R], \f[V]tv_simply\f[R] and \f[V]tv_embedded\f[R]. -By default, \f[V]tv,web_safari,web\f[R] is used, and -\f[V]tv,web_creator,web\f[R] is used with premium accounts. +\f[V]mweb\f[R], \f[V]ios\f[R], \f[V]android\f[R], +\f[V]android_sdkless\f[R], \f[V]android_vr\f[R], \f[V]tv\f[R], +\f[V]tv_simply\f[R], \f[V]tv_downgraded\f[R], and \f[V]tv_embedded\f[R]. +By default, \f[V]tv,android_sdkless,web\f[R] is used. +If no JavaScript runtime is available, then +\f[V]android_sdkless,web_safari,web\f[R] is used. +If logged-in cookies are passed to yt-dlp, then +\f[V]tv_downgraded,web_safari,web\f[R] is used for free accounts and +\f[V]tv_downgraded,web_creator,web\f[R] is used for premium accounts. The \f[V]web_music\f[R] client is added for \f[V]music.youtube.com\f[R] URLs when logged-in cookies are used. The \f[V]web_embedded\f[R] client is added for age-restricted videos but @@ -2711,9 +2747,10 @@ You can use \f[V]actual\f[R] to go with what is prescribed by the site .IP \[bu] 2 \f[V]player_js_version\f[R]: The player javascript version to use for n/sig deciphering, in the format of -\f[V]signature_timestamp\[at]hash\f[R]. -Currently, the default is to force \f[V]20348\[at]0004de42\f[R]. -You can use \f[V]actual\f[R] to go with what is prescribed by the site +\f[V]signature_timestamp\[at]hash\f[R] (e.g. +\f[V]20348\[at]0004de42\f[R]). +The default is to use what is prescribed by the site, and can be +selected with \f[V]actual\f[R] .IP \[bu] 2 \f[V]comment_sort\f[R]: \f[V]top\f[R] or \f[V]new\f[R] (default) - choose comment sorting mode (on YouTube\[aq]s side) @@ -2785,6 +2822,17 @@ client requires one for the given context) extraction and download stages in order to ensure the formats are available. The default is \f[V]6\f[R] seconds +.IP \[bu] 2 +\f[V]jsc_trace\f[R]: Enable debug logging for JS Challenge fetching. +Either \f[V]true\f[R] or \f[V]false\f[R] (default) +.SS youtube-ejs +.IP \[bu] 2 +\f[V]jitless\f[R]: Run suported Javascript engines in JIT-less mode. +Supported runtimes are \f[V]deno\f[R], \f[V]node\f[R] and \f[V]bun\f[R]. +Provides better security at the cost of performance/speed. +Do note that \f[V]node\f[R] and \f[V]bun\f[R] are still considered +unsecure. +Either \f[V]true\f[R] or \f[V]false\f[R] (default) .SS youtubepot-webpo .IP \[bu] 2 \f[V]bind_to_visitor_id\f[R]: Whether to use the Visitor ID instead of @@ -3099,7 +3147,7 @@ repository, tag \f[V]2023.09.24\f[R] yt-dlp --update-to nightly # To install nightly with pip: -python3 -m pip install -U --pre \[dq]yt-dlp[default]\[dq] +python -m pip install -U --pre \[dq]yt-dlp[default]\[dq] \f[R] .fi .PP @@ -3109,11 +3157,12 @@ You can suppress this warning by adding \f[V]--no-update\f[R] to your command or configuration file. .SS DEPENDENCIES .PP -Python versions 3.9+ (CPython) and 3.11+ (PyPy) are supported. +Python versions 3.10+ (CPython) and 3.11+ (PyPy) are supported. Other versions and implementations may or may not work correctly. .PP -While all the other dependencies are optional, \f[V]ffmpeg\f[R] and -\f[V]ffprobe\f[R] are highly recommended +While all the other dependencies are optional, \f[V]ffmpeg\f[R], +\f[V]ffprobe\f[R], \f[V]yt-dlp-ejs\f[R] and a JavaScript runtime are +highly recommended .SS Strongly recommended .IP \[bu] 2 \f[B]ffmpeg\f[R] and \f[B]ffprobe\f[R] (https://www.ffmpeg.org) - @@ -3135,6 +3184,23 @@ for details on the specific issues solved by these builds \f[B]NOT\f[R] the Python package of the same name (https://pypi.org/project/ffmpeg) .RE +.IP \[bu] 2 +\f[B]yt-dlp-ejs\f[R] (https://github.com/yt-dlp/ejs) - Required for +deciphering YouTube n/sig values. +Licensed under +Unlicense (https://github.com/yt-dlp/ejs/blob/main/LICENSE), bundles +MIT (https://github.com/davidbonnet/astring/blob/main/LICENSE) and +ISC (https://github.com/meriyah/meriyah/blob/main/LICENSE.md) +components. +.RS 2 +.PP +A JavaScript runtime like \f[B]deno\f[R] (https://deno.land) +(recommended), \f[B]node.js\f[R] (https://nodejs.org), +\f[B]bun\f[R] (https://bun.sh), or +\f[B]QuickJS\f[R] (https://bellard.org/quickjs/) is also required to run +yt-dlp-ejs. +See the wiki (https://github.com/yt-dlp/yt-dlp/wiki/EJS). +.RE .SS Networking .IP \[bu] 2 \f[B]certifi\f[R] (https://github.com/certifi/python-certifi)* - @@ -3208,8 +3274,10 @@ For decrypting AES-128 HLS streams and various other data. Licensed under BSD-2-Clause (https://github.com/Legrandin/pycryptodome/blob/master/LICENSE.rst) .IP \[bu] 2 -\f[B]phantomjs\f[R] (https://github.com/ariya/phantomjs) - Used in -extractors where javascript needs to be run. +\f[B]phantomjs\f[R] (https://github.com/ariya/phantomjs) - Used in some +extractors where JavaScript needs to be run. +No longer used for YouTube. +To be deprecated in the near future. Licensed under BSD-3-Clause (https://github.com/ariya/phantomjs/blob/master/LICENSE.BSD) .IP \[bu] 2 @@ -3258,14 +3326,14 @@ You can run the following commands: .IP .nf \f[C] -python3 devscripts/install_deps.py --include pyinstaller -python3 devscripts/make_lazy_extractors.py -python3 -m bundle.pyinstaller +python devscripts/install_deps.py --include-group pyinstaller +python devscripts/make_lazy_extractors.py +python -m bundle.pyinstaller \f[R] .fi .PP -On some systems, you may need to use \f[V]py\f[R] or \f[V]python\f[R] -instead of \f[V]python3\f[R]. +On some systems, you may need to use \f[V]py\f[R] or \f[V]python3\f[R] +instead of \f[V]python\f[R]. .PP \f[V]python -m bundle.pyinstaller\f[R] accepts any arguments that can be passed to \f[V]pyinstaller\f[R], such as \f[V]--onefile/-F\f[R] or @@ -3283,7 +3351,7 @@ officially supported. This may or may not work correctly. .SS Platform-independent Binary (UNIX) .PP -You will need the build tools \f[V]python\f[R] (3.9+), \f[V]zip\f[R], +You will need the build tools \f[V]python\f[R] (3.10+), \f[V]zip\f[R], \f[V]make\f[R] (GNU), \f[V]pandoc\f[R]* and \f[V]pytest\f[R]*. .PP After installing these, simply run \f[V]make\f[R]. @@ -3819,7 +3887,7 @@ Features marked with a \f[B]*\f[R] have been back-ported to youtube-dl Some of yt-dlp\[aq]s default options are different from that of youtube-dl and youtube-dlc: .IP \[bu] 2 -yt-dlp supports only Python 3.9+, and will remove support for more +yt-dlp supports only Python 3.10+, and will remove support for more versions as they become EOL (https://devguide.python.org/versions/#python-release-cycle); while youtube-dl still supports Python 2.6+ and diff --git a/.env/share/zsh/site-functions/_yt-dlp b/.env/share/zsh/site-functions/_yt-dlp index 462f35d..ca2468e 100644 --- a/.env/share/zsh/site-functions/_yt-dlp +++ b/.env/share/zsh/site-functions/_yt-dlp @@ -3,8 +3,8 @@ __yt_dlp() { local curcontext="$curcontext" fileopts diropts cur prev typeset -A opt_args - fileopts="--download-archive|-a|--batch-file|--load-info-json|--cookies|--no-cookies" - diropts="--cache-dir" + fileopts="--download-archive|-a|--batch-file|--load-info-json|--cookies|--no-cookies|--config-locations|--netrc-location|--ffmpeg-location" + diropts="--plugin-dirs|--cache-dir" cur=$words[CURRENT] case $cur in :) @@ -21,7 +21,7 @@ __yt_dlp() { elif [[ ${prev} == "--recode-video" ]]; then _arguments '*: :(mp4 flv ogg webm mkv)' else - _arguments '*: :(--help --version --update --no-update --update-to --ignore-errors --no-abort-on-error --abort-on-error --list-extractors --extractor-descriptions --use-extractors --force-generic-extractor --default-search --ignore-config --no-config-locations --config-locations --plugin-dirs --no-plugin-dirs --flat-playlist --no-flat-playlist --live-from-start --no-live-from-start --wait-for-video --no-wait-for-video --mark-watched --no-mark-watched --no-colors --color --compat-options --alias --preset-alias --proxy --socket-timeout --source-address --impersonate --list-impersonate-targets --force-ipv4 --force-ipv6 --enable-file-urls --geo-verification-proxy --xff --geo-bypass --no-geo-bypass --geo-bypass-country --geo-bypass-ip-block --playlist-start --playlist-end --playlist-items --match-title --reject-title --min-filesize --max-filesize --date --datebefore --dateafter --min-views --max-views --match-filters --no-match-filters --break-match-filters --no-break-match-filters --no-playlist --yes-playlist --age-limit --download-archive --no-download-archive --max-downloads --break-on-existing --no-break-on-existing --break-on-reject --break-per-input --no-break-per-input --skip-playlist-after-errors --concurrent-fragments --limit-rate --throttled-rate --retries --file-access-retries --fragment-retries --retry-sleep --skip-unavailable-fragments --abort-on-unavailable-fragments --keep-fragments --no-keep-fragments --buffer-size --resize-buffer --no-resize-buffer --http-chunk-size --test --playlist-reverse --no-playlist-reverse --playlist-random --lazy-playlist --no-lazy-playlist --hls-prefer-native --hls-prefer-ffmpeg --hls-use-mpegts --no-hls-use-mpegts --download-sections --downloader --downloader-args --batch-file --no-batch-file --id --paths --output --output-na-placeholder --autonumber-size --autonumber-start --restrict-filenames --no-restrict-filenames --windows-filenames --no-windows-filenames --trim-filenames --no-overwrites --force-overwrites --no-force-overwrites --continue --no-continue --part --no-part --mtime --no-mtime --write-description --no-write-description --write-info-json --no-write-info-json --write-playlist-metafiles --no-write-playlist-metafiles --clean-info-json --no-clean-info-json --write-comments --no-write-comments --load-info-json --cookies --no-cookies --cookies-from-browser --no-cookies-from-browser --cache-dir --no-cache-dir --rm-cache-dir --write-thumbnail --no-write-thumbnail --write-all-thumbnails --list-thumbnails --write-link --write-url-link --write-webloc-link --write-desktop-link --quiet --no-quiet --no-warnings --simulate --no-simulate --ignore-no-formats-error --no-ignore-no-formats-error --skip-download --print --print-to-file --get-url --get-title --get-id --get-thumbnail --get-description --get-duration --get-filename --get-format --dump-json --dump-single-json --print-json --force-write-archive --newline --no-progress --progress --console-title --progress-template --progress-delta --verbose --dump-pages --write-pages --load-pages --print-traffic --encoding --legacy-server-connect --no-check-certificates --prefer-insecure --user-agent --referer --add-headers --bidi-workaround --sleep-requests --sleep-interval --max-sleep-interval --sleep-subtitles --format --format-sort --format-sort-force --no-format-sort-force --video-multistreams --no-video-multistreams --audio-multistreams --no-audio-multistreams --all-formats --prefer-free-formats --no-prefer-free-formats --check-formats --check-all-formats --no-check-formats --list-formats --list-formats-as-table --list-formats-old --merge-output-format --allow-unplayable-formats --no-allow-unplayable-formats --write-subs --no-write-subs --write-auto-subs --no-write-auto-subs --all-subs --list-subs --sub-format --sub-langs --username --password --twofactor --netrc --netrc-location --netrc-cmd --video-password --ap-mso --ap-username --ap-password --ap-list-mso --client-certificate --client-certificate-key --client-certificate-password --extract-audio --audio-format --audio-quality --remux-video --recode-video --postprocessor-args --keep-video --no-keep-video --post-overwrites --no-post-overwrites --embed-subs --no-embed-subs --embed-thumbnail --no-embed-thumbnail --embed-metadata --no-embed-metadata --embed-chapters --no-embed-chapters --embed-info-json --no-embed-info-json --metadata-from-title --parse-metadata --replace-in-metadata --xattrs --concat-playlist --fixup --ffmpeg-location --exec --no-exec --exec-before-download --no-exec-before-download --convert-subs --convert-thumbnails --split-chapters --no-split-chapters --remove-chapters --no-remove-chapters --force-keyframes-at-cuts --no-force-keyframes-at-cuts --use-postprocessor --sponsorblock-mark --sponsorblock-remove --sponsorblock-chapter-title --no-sponsorblock --sponsorblock-api --extractor-retries --allow-dynamic-mpd --ignore-dynamic-mpd --hls-split-discontinuity --no-hls-split-discontinuity --extractor-args)' + _arguments '*: :(--help --version --update --no-update --update-to --ignore-errors --no-abort-on-error --abort-on-error --list-extractors --extractor-descriptions --use-extractors --force-generic-extractor --default-search --ignore-config --no-config-locations --config-locations --plugin-dirs --no-plugin-dirs --js-runtimes --no-js-runtimes --remote-components --no-remote-components --flat-playlist --no-flat-playlist --live-from-start --no-live-from-start --wait-for-video --no-wait-for-video --mark-watched --no-mark-watched --no-colors --color --compat-options --alias --preset-alias --proxy --socket-timeout --source-address --impersonate --list-impersonate-targets --force-ipv4 --force-ipv6 --enable-file-urls --geo-verification-proxy --xff --geo-bypass --no-geo-bypass --geo-bypass-country --geo-bypass-ip-block --playlist-start --playlist-end --playlist-items --match-title --reject-title --min-filesize --max-filesize --date --datebefore --dateafter --min-views --max-views --match-filters --no-match-filters --break-match-filters --no-break-match-filters --no-playlist --yes-playlist --age-limit --download-archive --no-download-archive --max-downloads --break-on-existing --no-break-on-existing --break-on-reject --break-per-input --no-break-per-input --skip-playlist-after-errors --concurrent-fragments --limit-rate --throttled-rate --retries --file-access-retries --fragment-retries --retry-sleep --skip-unavailable-fragments --abort-on-unavailable-fragments --keep-fragments --no-keep-fragments --buffer-size --resize-buffer --no-resize-buffer --http-chunk-size --test --playlist-reverse --no-playlist-reverse --playlist-random --lazy-playlist --no-lazy-playlist --hls-prefer-native --hls-prefer-ffmpeg --hls-use-mpegts --no-hls-use-mpegts --download-sections --downloader --downloader-args --batch-file --no-batch-file --id --paths --output --output-na-placeholder --autonumber-size --autonumber-start --restrict-filenames --no-restrict-filenames --windows-filenames --no-windows-filenames --trim-filenames --no-overwrites --force-overwrites --no-force-overwrites --continue --no-continue --part --no-part --mtime --no-mtime --write-description --no-write-description --write-info-json --no-write-info-json --write-playlist-metafiles --no-write-playlist-metafiles --clean-info-json --no-clean-info-json --write-comments --no-write-comments --load-info-json --cookies --no-cookies --cookies-from-browser --no-cookies-from-browser --cache-dir --no-cache-dir --rm-cache-dir --write-thumbnail --no-write-thumbnail --write-all-thumbnails --list-thumbnails --write-link --write-url-link --write-webloc-link --write-desktop-link --quiet --no-quiet --no-warnings --simulate --no-simulate --ignore-no-formats-error --no-ignore-no-formats-error --skip-download --print --print-to-file --get-url --get-title --get-id --get-thumbnail --get-description --get-duration --get-filename --get-format --dump-json --dump-single-json --print-json --force-write-archive --newline --no-progress --progress --console-title --progress-template --progress-delta --verbose --dump-pages --write-pages --load-pages --print-traffic --encoding --legacy-server-connect --no-check-certificates --prefer-insecure --user-agent --referer --add-headers --bidi-workaround --sleep-requests --sleep-interval --max-sleep-interval --sleep-subtitles --format --format-sort --format-sort-force --no-format-sort-force --video-multistreams --no-video-multistreams --audio-multistreams --no-audio-multistreams --all-formats --prefer-free-formats --no-prefer-free-formats --check-formats --check-all-formats --no-check-formats --list-formats --list-formats-as-table --list-formats-old --merge-output-format --allow-unplayable-formats --no-allow-unplayable-formats --write-subs --no-write-subs --write-auto-subs --no-write-auto-subs --all-subs --list-subs --sub-format --sub-langs --username --password --twofactor --netrc --netrc-location --netrc-cmd --video-password --ap-mso --ap-username --ap-password --ap-list-mso --client-certificate --client-certificate-key --client-certificate-password --extract-audio --audio-format --audio-quality --remux-video --recode-video --postprocessor-args --keep-video --no-keep-video --post-overwrites --no-post-overwrites --embed-subs --no-embed-subs --embed-thumbnail --no-embed-thumbnail --embed-metadata --no-embed-metadata --embed-chapters --no-embed-chapters --embed-info-json --no-embed-info-json --metadata-from-title --parse-metadata --replace-in-metadata --xattrs --concat-playlist --fixup --ffmpeg-location --exec --no-exec --exec-before-download --no-exec-before-download --convert-subs --convert-thumbnails --split-chapters --no-split-chapters --remove-chapters --no-remove-chapters --force-keyframes-at-cuts --no-force-keyframes-at-cuts --use-postprocessor --sponsorblock-mark --sponsorblock-remove --sponsorblock-chapter-title --no-sponsorblock --sponsorblock-api --extractor-retries --allow-dynamic-mpd --ignore-dynamic-mpd --hls-split-discontinuity --no-hls-split-discontinuity --extractor-args)' fi ;; esac diff --git a/.gitignore b/.gitignore index c647c9c..a8a1667 100644 --- a/.gitignore +++ b/.gitignore @@ -131,6 +131,7 @@ celerybeat.pid # Environments .venv .env +.env/ env/ venv/ ENV/ diff --git a/download_youtube.py b/download_youtube.py index 94546fd..5108d37 100644 --- a/download_youtube.py +++ b/download_youtube.py @@ -9,6 +9,7 @@ ydl_opts = { 'preferredcodec': 'mp3', 'preferredquality': '0', # 0 = best quality }], + 'outtmpl': '%(uploader)s - %(title)s.%(ext)s' } url = sys.argv[1] diff --git a/make_folders.py b/make_folders.py index 2f1e94a..8b72697 100755 --- a/make_folders.py +++ b/make_folders.py @@ -226,23 +226,31 @@ def check_title_songname(x: str, audio): x = x.rsplit(".",1)[0] # remove the file extension logging.info("file has extension " + extension + ". removing it from title. New title: " + x) - items = x.split(" - ") - if (len(items) > 2): - logging.info("song title has more than 1 part after the -: " + str(items)) - if (items[1].count(".mp3") >= 1): - logging.info("setting TIT2 tag to: " + str(items[1].strip().rstrip().rsplit(".")[0])) # get second part of title and remove the file extension - audio["TIT2"] = TIT2(encoding=3,text=str(items[1].strip().rstrip().rsplit(".")[0])) - elif (items[1].count(".flac") >= 1): - logging.info("setting title tag to " + str(items[1].strip().rstrip().rsplit(".")[0])) # get second part of title and remove the file extension - audio["title"] = str(items[1].strip().rstrip().rsplit(".")[0]) + if (" - " in x): + items = x.split(" - ") + if (len(items) > 2): + logging.info("song title has more than 1 part after the -: " + str(items)) + if (items[1].count(".mp3") >= 1): + logging.info("setting TIT2 tag to: " + str(items[1].strip().rstrip().rsplit(".")[0])) # get second part of title and remove the file extension + audio["TIT2"] = TIT2(encoding=3,text=str(items[1].strip().rstrip().rsplit(".")[0])) + elif (items[1].count(".flac") >= 1): + logging.info("setting title tag to " + str(items[1].strip().rstrip().rsplit(".")[0])) # get second part of title and remove the file extension + audio["title"] = str(items[1].strip().rstrip().rsplit(".")[0]) + else: + logging.info("title: " + str(items[1].strip().rstrip())) # get second part of title and remove the file extension + audio["TIT2"] = TIT2(encoding=3,text=str(items[1].strip().rstrip())) + audio["title"] = TIT2(encoding=3,text=str(items[1].strip().rstrip())) else: - logging.info("title: " + str(items[1].strip().rstrip())) # get second part of title and remove the file extension - audio["TIT2"] = TIT2(encoding=3,text=str(items[1].strip().rstrip())) - audio["title"] = TIT2(encoding=3,text=str(items[1].strip().rstrip())) + logging.info("song title has only 1 part after the -: " + items[1]) + if ("TIT2" not in audio.keys()): + song_title = items[1].strip().rstrip() + logging.info("TIT2 tag not found, creating it. Using song title: " + song_title) + audio["TIT2"] = TIT2(encoding=3,text=song_title) + audio["title"] = TIT2(encoding=3,text=song_title) else: - logging.info("song title has only 1 part after the -: " + items[0]) + logging.info("no - found in title, setting full name as title: " + x) if ("TIT2" not in audio.keys()): - song_title = items[0].strip().rstrip() + song_title = x.strip().rstrip() logging.info("TIT2 tag not found, creating it. Using song title: " + song_title) audio["TIT2"] = TIT2(encoding=3,text=song_title) audio["title"] = TIT2(encoding=3,text=song_title)