mirror of
https://github.com/neosubhamoy/pytubepp.git
synced 2026-02-05 02:32:23 +05:30
Compare commits
10 Commits
v1.1.2-sta
...
v1.1.4-sta
53
README.md
53
README.md
@@ -9,18 +9,22 @@
|
|||||||
[](https://github.com/neosubhamoy/pytubepp/)
|
[](https://github.com/neosubhamoy/pytubepp/)
|
||||||
[](https://github.com/neosubhamoy/pytubepp/)
|
[](https://github.com/neosubhamoy/pytubepp/)
|
||||||
|
|
||||||
😀 GOOD NEWS: If you are Windows(10/11) user and don't want to bother remembering PytubePP Commands! (You are not familier with Command Line Tools). We recently released a Browser Extension that can auto detect YouTube Videos and You can download the Video in one click directly from the browser using PytubePP CLI. Install [PytubePP Helper](https://github.com/neosubhamoy/pytubepp-helper) app in your System and add [PytubePP Extension](https://github.com/neosubhamoy/pytubepp-extension) in your Browser to get started.
|
😀 GOOD NEWS: If you are not a power user and don't want to bother remembering PytubePP Commands! (You are not familier with Command Line Tools). We recently released a Browser Extension that can auto detect YouTube Videos and You can download the Video in one click directly from the browser using PytubePP CLI. Install [PytubePP Helper](https://github.com/neosubhamoy/pytubepp-helper) app in your System and add [PytubePP Extension](https://github.com/neosubhamoy/pytubepp-extension) in your Browser to get started.
|
||||||
|
|
||||||
|
> **🥰 Liked this project? Please consider giving it a Star (🌟) on github to show us your appreciation and help the algorythm recommend this project to even more awesome people like you!**
|
||||||
|
|
||||||
### **🏷️ Features**
|
### **🏷️ Features**
|
||||||
* Auto Post-Process & Merge YouTube DASH Streams
|
* Auto Post-Process & Merge YouTube DASH Streams
|
||||||
* Supports upto 8K 60fps HDR Stream Download
|
* Supports upto 8K 60fps HDR Stream Download
|
||||||
* Supports MP3 Download (with Embeded Thumbnail and Tags)
|
* Supports MP3 Download (with Embeded Thumbnail and Tags)
|
||||||
|
* Supports Embeded Captions
|
||||||
* Smart Stream Selection
|
* Smart Stream Selection
|
||||||
* Highly Configurable and Many More 😉
|
* Highly Configurable and Many More 😉
|
||||||
|
|
||||||
### **📎 Pre-Requirements**
|
### **📎 Pre-Requirements**
|
||||||
* [Python](https://www.python.org/downloads/) (>=3.8)
|
* [Python](https://www.python.org/downloads/) (>=3.8)
|
||||||
* [FFmpeg](https://ffmpeg.org/)
|
* [FFmpeg](https://ffmpeg.org/)
|
||||||
|
* [Node.js](https://nodejs.org/en/download/) (required for auto YT poToken genration which is currently not possible in Python environment)
|
||||||
|
|
||||||
### **🧩 Python Dependencies**
|
### **🧩 Python Dependencies**
|
||||||
* [pytubefix](https://pypi.org/project/pytubefix/)
|
* [pytubefix](https://pypi.org/project/pytubefix/)
|
||||||
@@ -47,7 +51,16 @@
|
|||||||
- Windows (10/11): `winget install ffmpeg`<br>
|
- Windows (10/11): `winget install ffmpeg`<br>
|
||||||
- MacOS (using Homebrew): `brew install ffmpeg`<br>
|
- MacOS (using Homebrew): `brew install ffmpeg`<br>
|
||||||
- Android (using Termux): `pkg install ffmpeg`
|
- Android (using Termux): `pkg install ffmpeg`
|
||||||
3. Install PytubePP (using PIP)
|
3. Install Node.js
|
||||||
|
- Linux (Debian): `curl -o- https://fnm.vercel.app/install | bash && fnm install --lts && fnm use lts`<br>
|
||||||
|
- Linux (Fedora): `curl -o- https://fnm.vercel.app/install | bash && fnm install --lts && fnm use lts`<br>
|
||||||
|
- Linux (Arch): `curl -o- https://fnm.vercel.app/install | bash && fnm install --lts && fnm use lts`<br>
|
||||||
|
- Windows (10/11): `winget install Schniz.fnm;fnm install --lts;fnm use lts`<br>
|
||||||
|
- MacOS (using Homebrew): `brew install node`<br>
|
||||||
|
- Android (using Termux): `pkg install nodejs`
|
||||||
|
4. Install PytubePP (using PIP)
|
||||||
|
|
||||||
|
> Use `pip3` command instead of `pip` if you are on Linux or MacOS.
|
||||||
|
|
||||||
```terminal
|
```terminal
|
||||||
pip install pytubepp
|
pip install pytubepp
|
||||||
@@ -62,7 +75,7 @@ pip install pytubefix pytubepp --upgrade
|
|||||||
### **📌 Commands and Flags**
|
### **📌 Commands and Flags**
|
||||||
Using PytubePP is as simple as just supplying it only the YouTube video url as argument!
|
Using PytubePP is as simple as just supplying it only the YouTube video url as argument!
|
||||||
** Before Starting Please NOTE: PytubePP follows a simple rule - "Use the Default Download Configuration if No Flags are Passed"
|
** Before Starting Please NOTE: PytubePP follows a simple rule - "Use the Default Download Configuration if No Flags are Passed"
|
||||||
* To download a video in maximum available resolution the command will look like:
|
* To download a video in default configuration (maximum resolution and without any caption by default) the command will look like:
|
||||||
```terminal
|
```terminal
|
||||||
pytubepp "https://youtube.com/watch?v=2lAe1cqCOXo"
|
pytubepp "https://youtube.com/watch?v=2lAe1cqCOXo"
|
||||||
```
|
```
|
||||||
@@ -70,6 +83,10 @@ pytubepp "https://youtube.com/watch?v=2lAe1cqCOXo"
|
|||||||
```terminal
|
```terminal
|
||||||
pytubepp "https://youtube.com/watch?v=2lAe1cqCOXo" -s 480p
|
pytubepp "https://youtube.com/watch?v=2lAe1cqCOXo" -s 480p
|
||||||
```
|
```
|
||||||
|
* To download the video with embeded caption (suppose en - English) the command will be:
|
||||||
|
```terminal
|
||||||
|
pytubepp "https://youtube.com/watch?v=2lAe1cqCOXo" -c en
|
||||||
|
```
|
||||||
* To download the video in audio-only MP3 format the command will be:
|
* To download the video in audio-only MP3 format the command will be:
|
||||||
```terminal
|
```terminal
|
||||||
pytubepp "https://youtube.com/watch?v=2lAe1cqCOXo" -s mp3
|
pytubepp "https://youtube.com/watch?v=2lAe1cqCOXo" -s mp3
|
||||||
@@ -84,15 +101,42 @@ pytubepp "https://youtube.com/watch?v=2lAe1cqCOXo" -i
|
|||||||
| Flag | Usage | Requires Parameter | Requires URL | Parameters | Default |
|
| Flag | Usage | Requires Parameter | Requires URL | Parameters | Default |
|
||||||
| :--- | :--- | :--- | :--- | :--- | :--- |
|
| :--- | :--- | :--- | :--- | :--- | :--- |
|
||||||
| -s | Choose preferred download stream | YES | YES | `144` `144p` `240` `240p` `360` `360p` `480` `480p` `720` `720p` `hd` `1080` `1080p` `fhd` `1440` `1440p` `2k` `2160` `2160p` `4k` `4320` `4320p` `8k` `mp3` (Pass any one of them) | Your chosen Default Stream via `-ds` flag |
|
| -s | Choose preferred download stream | YES | YES | `144` `144p` `240` `240p` `360` `360p` `480` `480p` `720` `720p` `hd` `1080` `1080p` `fhd` `1440` `1440p` `2k` `2160` `2160p` `4k` `4320` `4320p` `8k` `mp3` (Pass any one of them) | Your chosen Default Stream via `-ds` flag |
|
||||||
|
| -c | Choose preferred caption | YES | YES | All [ISO 639-1 Language Codes](https://www.w3schools.com/tags/ref_language_codes.asp) + some others (Pass any one of them) eg: `en` for English | Your chosen Default Caption via `-dc` flag |
|
||||||
| -i | Shows the video information like: Title, Author, Views, Publication Date, Duration, Available Download Streams | NO | YES | No parameters | No default |
|
| -i | Shows the video information like: Title, Author, Views, Publication Date, Duration, Available Download Streams | NO | YES | No parameters | No default |
|
||||||
|
| -ls | Lists all available streams (video, audio, caption) (only for debuging purposes) | NO | YES | No parameters | No default |
|
||||||
| -ri | Shows the video information in raw json format | NO | YES | No parameters | No default |
|
| -ri | Shows the video information in raw json format | NO | YES | No parameters | No default |
|
||||||
| -jp | Shows raw json output in prettified view (with indentation: 4) (primarily used with -ri flag)| NO | YES | No parameters | No default |
|
| -jp | Shows raw json output in prettified view (with indentation: 4) (primarily used with -ri flag)| NO | YES | No parameters | No default |
|
||||||
| -ds | Set default download stream | YES | NO | `144p` `240p` `360p` `480p` `720p` `1080p` `1440p` `2160p` `4320p` `mp3` `max` (Pass any one of them) | `max` |
|
| -ds | Set default download stream | YES | NO | `144p` `240p` `360p` `480p` `720p` `1080p` `1440p` `2160p` `4320p` `mp3` `max` (Pass any one of them) | `max` |
|
||||||
|
| -dc | Set default caption | YES | NO | All [ISO 639-1 Language Codes](https://www.w3schools.com/tags/ref_language_codes.asp) + some others + `none` for No Caption (Pass any one of them) eg: `en` for English | `none` |
|
||||||
| -df | Set custom download folder path | YES | NO | Use the full path excluding the last trailing slash within double quotes eg(in Linux): `"/path/to/folder"` (Make sure the folder path you enterted is already created and accessable) | Within `PytubePP Downloads` folder in your System's `Downloads` folder |
|
| -df | Set custom download folder path | YES | NO | Use the full path excluding the last trailing slash within double quotes eg(in Linux): `"/path/to/folder"` (Make sure the folder path you enterted is already created and accessable) | Within `PytubePP Downloads` folder in your System's `Downloads` folder |
|
||||||
| -r | Reset to default configuration (Download Folder, Default Stream) | NO | NO | No parameters | No default |
|
| -r | Reset to default configuration (Download Folder, Default Stream) | NO | NO | No parameters | No default |
|
||||||
| -sc | Show all current user configurations | NO | NO | No parameters | No default |
|
| -sc | Show all current user configurations | NO | NO | No parameters | No default |
|
||||||
| -ct | Clear temporary files (audio, video, thumbnail) of the failed, incomplete downloads | NO | NO | No parameters | No default |
|
| -ct | Clear temporary files (audio, video, thumbnail) of the failed, incomplete downloads | NO | NO | No parameters | No default |
|
||||||
|
|
||||||
|
### 🛠️ Contributing / Building from Source
|
||||||
|
|
||||||
|
Want to be part of this? Feel free to contribute...!! Pull Requests are always welcome...!! (^_^) Follow these simple steps to start building:
|
||||||
|
|
||||||
|
* Make sure to install Python, FFmpeg, Node.js and Git before proceeding.
|
||||||
|
|
||||||
|
1. Fork this repo in your github account.
|
||||||
|
2. Git clone the forked repo in your local machine.
|
||||||
|
|
||||||
|
> Use `python3` and `pip3` commands instead of `python` and `pip` if you are on Linux or MacOS.
|
||||||
|
|
||||||
|
3. Install python dependencies
|
||||||
|
|
||||||
|
```terminal
|
||||||
|
pip install -r requirements.txt
|
||||||
|
```
|
||||||
|
4. build, install and test the module
|
||||||
|
|
||||||
|
```terminal
|
||||||
|
python -m build // build the module
|
||||||
|
|
||||||
|
pip install .\dist\pytubepp-<version>-py3-none-any.whl // install the module (give the path to the newly genrated whl file based on your OS path style and don't forget to replace the <version> with the actual version number)
|
||||||
|
```
|
||||||
|
5. Do the changes, Send a Pull Request with proper Description (NOTE: Pull Requests Without Proper Description will be Rejected)
|
||||||
|
|
||||||
⭕ Noticed any Bugs? or Want to give me some suggetions? always feel free to open an issue...!!
|
⭕ Noticed any Bugs? or Want to give me some suggetions? always feel free to open an issue...!!
|
||||||
|
|
||||||
@@ -100,8 +144,7 @@ pytubepp "https://youtube.com/watch?v=2lAe1cqCOXo" -i
|
|||||||
|
|
||||||
PytubePP - (Pytube Post Processor) is a Fully Open Sourced Project licensed under MIT License. Anyone can view, modify, use (personal and commercial) or distribute it's sources without any attribution and extra permissions.
|
PytubePP - (Pytube Post Processor) is a Fully Open Sourced Project licensed under MIT License. Anyone can view, modify, use (personal and commercial) or distribute it's sources without any attribution and extra permissions.
|
||||||
|
|
||||||
**🌟 Liked this project? Please consider giving it a star to show me your appreciation**
|
⚖️ NOTE: YouTube is a trademark of Google LLC. Use of this trademark is subject to Google Permissions. Downloading and using Copyrighted YouTube Content for Commercial pourposes are not allowed by YouTube Terms without proper Permissions from the Creator. We don't promote this kinds of activity, You should use the downloaded contents wisely and at your own responsibility.
|
||||||
<br></br>
|
|
||||||
|
|
||||||
****
|
****
|
||||||
|
|
||||||
|
|||||||
@@ -4,7 +4,7 @@ build-backend = "setuptools.build_meta"
|
|||||||
|
|
||||||
[project]
|
[project]
|
||||||
name = "pytubepp"
|
name = "pytubepp"
|
||||||
version = "1.1.2"
|
version = "1.1.4"
|
||||||
authors = [
|
authors = [
|
||||||
{ name="Subhamoy Biswas", email="hey@neosubhamoy.com" },
|
{ name="Subhamoy Biswas", email="hey@neosubhamoy.com" },
|
||||||
]
|
]
|
||||||
|
|||||||
@@ -14,6 +14,7 @@ def get_download_folder():
|
|||||||
DEFAULT_CONFIG = {
|
DEFAULT_CONFIG = {
|
||||||
'downloadDIR': get_download_folder(),
|
'downloadDIR': get_download_folder(),
|
||||||
'defaultStream': 'max',
|
'defaultStream': 'max',
|
||||||
|
'defaultCaption': 'none',
|
||||||
}
|
}
|
||||||
|
|
||||||
def get_temporary_directory():
|
def get_temporary_directory():
|
||||||
|
|||||||
@@ -1,13 +1,13 @@
|
|||||||
from tqdm import tqdm
|
from tqdm import tqdm
|
||||||
from .config import get_temporary_directory, load_config
|
from .config import get_temporary_directory, load_config
|
||||||
from .utils import get_unique_filename
|
from .utils import get_unique_filename, postprocess_cleanup
|
||||||
import os, re, requests, shutil, sys, random
|
import os, re, requests, shutil, sys, random, ffmpy
|
||||||
|
|
||||||
userConfig = load_config()
|
userConfig = load_config()
|
||||||
downloadDIR = userConfig['downloadDIR']
|
downloadDIR = userConfig['downloadDIR']
|
||||||
tempDIR = get_temporary_directory()
|
tempDIR = get_temporary_directory()
|
||||||
|
|
||||||
def download_progressive(stream, itag, title, resolution, file_extention, tempDIR=tempDIR, downloadDIR=downloadDIR):
|
def download_progressive(stream, itag, title, resolution, file_extention, captions, caption_code=None, tempDIR=tempDIR, downloadDIR=downloadDIR):
|
||||||
global total_filesize, progress_bar
|
global total_filesize, progress_bar
|
||||||
selected_vdo = stream.get_by_itag(itag)
|
selected_vdo = stream.get_by_itag(itag)
|
||||||
total_filesize = selected_vdo.filesize
|
total_filesize = selected_vdo.filesize
|
||||||
@@ -15,11 +15,31 @@ def download_progressive(stream, itag, title, resolution, file_extention, tempDI
|
|||||||
random_filename = str(random.randint(1000000000, 9999999999))
|
random_filename = str(random.randint(1000000000, 9999999999))
|
||||||
filename = random_filename + '_vdo.' + file_extention
|
filename = random_filename + '_vdo.' + file_extention
|
||||||
output_temp_file = os.path.join(tempDIR, filename)
|
output_temp_file = os.path.join(tempDIR, filename)
|
||||||
output_file = os.path.join(downloadDIR, get_unique_filename(title + '_' + resolution + '.' + file_extention))
|
output_file = os.path.join(downloadDIR, get_unique_filename(title + '_' + resolution + '.' + file_extention)) if not caption_code else os.path.join(downloadDIR, get_unique_filename(title + '_' + resolution + '_' + caption_code + '.' + file_extention))
|
||||||
selected_vdo.download(output_path=tempDIR, filename=filename)
|
selected_vdo.download(output_path=tempDIR, filename=filename)
|
||||||
print('Processing...')
|
|
||||||
shutil.move(output_temp_file, output_file)
|
if caption_code:
|
||||||
print('Done! 🎉')
|
print(f'Downloading Caption ({caption_code})...')
|
||||||
|
caption = captions[caption_code]
|
||||||
|
caption_file = os.path.join(tempDIR, random_filename + '_cap.srt')
|
||||||
|
caption.save_captions(caption_file)
|
||||||
|
print('Processing...')
|
||||||
|
devnull = open(os.devnull, 'w')
|
||||||
|
output_temp_file_with_subs = os.path.join(tempDIR, random_filename + '_merged.' + file_extention)
|
||||||
|
ff = ffmpy.FFmpeg(
|
||||||
|
inputs={output_temp_file: None},
|
||||||
|
outputs={output_temp_file_with_subs: ['-i', caption_file, '-c', 'copy', '-c:s', 'mov_text', '-metadata:s:s:0', f'language={caption_code}', '-metadata:s:s:0', f'title={caption_code}', '-metadata:s:s:0', f'handler_name={caption_code}']}
|
||||||
|
)
|
||||||
|
ff.run(stdout=devnull, stderr=devnull)
|
||||||
|
devnull.close()
|
||||||
|
|
||||||
|
shutil.move(output_temp_file_with_subs, output_file)
|
||||||
|
postprocess_cleanup(tempDIR, ['_vdo.' + file_extention, '_cap.srt', '_merged.' + file_extention], random_filename)
|
||||||
|
print('Done! 🎉')
|
||||||
|
else:
|
||||||
|
print('Processing...')
|
||||||
|
shutil.move(output_temp_file, output_file)
|
||||||
|
print('Done! 🎉')
|
||||||
|
|
||||||
def download_nonprogressive(stream, itag_vdo, itag_ado, file_extention, output_path):
|
def download_nonprogressive(stream, itag_vdo, itag_ado, file_extention, output_path):
|
||||||
global total_filesize, progress_bar
|
global total_filesize, progress_bar
|
||||||
|
|||||||
1013
pytubepp/main.py
1013
pytubepp/main.py
File diff suppressed because it is too large
Load Diff
@@ -8,24 +8,62 @@ userConfig = load_config()
|
|||||||
downloadDIR = userConfig['downloadDIR']
|
downloadDIR = userConfig['downloadDIR']
|
||||||
tempDIR = get_temporary_directory()
|
tempDIR = get_temporary_directory()
|
||||||
|
|
||||||
def merge_audio_video(title, resolution, file_extention, random_filename, tempDIR=tempDIR, downloadDIR=downloadDIR):
|
def merge_audio_video(title, resolution, file_extention, random_filename, captions, caption_code=None, tempDIR=tempDIR, downloadDIR=downloadDIR):
|
||||||
video_file = os.path.join(tempDIR, random_filename + '_vdo.' + file_extention)
|
video_file = os.path.join(tempDIR, random_filename + '_vdo.' + file_extention)
|
||||||
audio_file = os.path.join(tempDIR, random_filename + '_ado.' + file_extention)
|
audio_file = os.path.join(tempDIR, random_filename + '_ado.' + file_extention)
|
||||||
output_temp_file = os.path.join(tempDIR, random_filename + '_merged.' + file_extention)
|
output_temp_file = os.path.join(tempDIR, random_filename + '_merged.' + file_extention)
|
||||||
output_file = os.path.join(downloadDIR, get_unique_filename(title + '_' + resolution + '.' + file_extention))
|
output_file = os.path.join(downloadDIR, get_unique_filename(title + '_' + resolution + '.' + file_extention)) if not caption_code else os.path.join(downloadDIR, get_unique_filename(title + '_' + resolution + '_' + caption_code + '.' + file_extention))
|
||||||
|
|
||||||
input_params = {video_file: None, audio_file: None}
|
if caption_code:
|
||||||
output_params = {output_temp_file: ['-c:v', 'copy', '-c:a', 'copy']}
|
print(f'Downloading Caption ({caption_code})...')
|
||||||
|
caption = captions[caption_code]
|
||||||
|
srt_file = os.path.join(tempDIR, random_filename + '_cap.srt')
|
||||||
|
caption.save_captions(srt_file)
|
||||||
|
vtt_file = os.path.join(tempDIR, random_filename + '_cap.vtt')
|
||||||
|
|
||||||
print('Processing...')
|
print('Processing...')
|
||||||
devnull = open(os.devnull, 'w')
|
if file_extention == 'webm':
|
||||||
ff = ffmpy.FFmpeg(inputs=input_params, outputs=output_params)
|
devnull = open(os.devnull, 'w')
|
||||||
ff.run(stdout=devnull, stderr=devnull)
|
ff_convert = ffmpy.FFmpeg(
|
||||||
devnull.close()
|
inputs={srt_file: None},
|
||||||
|
outputs={vtt_file: None}
|
||||||
|
)
|
||||||
|
ff_convert.run(stdout=devnull, stderr=devnull)
|
||||||
|
subtitle_file = vtt_file
|
||||||
|
subtitle_codec = 'webvtt'
|
||||||
|
else:
|
||||||
|
subtitle_file = srt_file
|
||||||
|
subtitle_codec = 'mov_text'
|
||||||
|
|
||||||
shutil.move(output_temp_file, output_file)
|
input_params = {video_file: None, audio_file: None}
|
||||||
postprocess_cleanup(tempDIR, ['_vdo.' + file_extention, '_ado.' + file_extention, '_merged.' + file_extention], random_filename)
|
output_params = {output_temp_file: ['-i', subtitle_file, '-c:v', 'copy', '-c:a', 'copy',
|
||||||
print('Done! 🎉')
|
'-c:s', subtitle_codec, '-metadata:s:s:0', f'language={caption_code}',
|
||||||
|
'-metadata:s:s:0', f'title={caption_code}', '-metadata:s:s:0', f'handler_name={caption_code}']}
|
||||||
|
|
||||||
|
devnull = open(os.devnull, 'w')
|
||||||
|
ff = ffmpy.FFmpeg(inputs=input_params, outputs=output_params)
|
||||||
|
ff.run(stdout=devnull, stderr=devnull)
|
||||||
|
devnull.close()
|
||||||
|
|
||||||
|
shutil.move(output_temp_file, output_file)
|
||||||
|
cleanup_files = ['_vdo.' + file_extention, '_ado.' + file_extention, '_cap.srt', '_merged.' + file_extention]
|
||||||
|
if file_extention == 'webm':
|
||||||
|
cleanup_files.append('_cap.vtt')
|
||||||
|
postprocess_cleanup(tempDIR, cleanup_files, random_filename)
|
||||||
|
print('Done! 🎉')
|
||||||
|
else:
|
||||||
|
input_params = {video_file: None, audio_file: None}
|
||||||
|
output_params = {output_temp_file: ['-c:v', 'copy', '-c:a', 'copy']}
|
||||||
|
|
||||||
|
print('Processing...')
|
||||||
|
devnull = open(os.devnull, 'w')
|
||||||
|
ff = ffmpy.FFmpeg(inputs=input_params, outputs=output_params)
|
||||||
|
ff.run(stdout=devnull, stderr=devnull)
|
||||||
|
devnull.close()
|
||||||
|
|
||||||
|
shutil.move(output_temp_file, output_file)
|
||||||
|
postprocess_cleanup(tempDIR, ['_vdo.' + file_extention, '_ado.' + file_extention, '_merged.' + file_extention], random_filename)
|
||||||
|
print('Done! 🎉')
|
||||||
|
|
||||||
def convert_to_mp3(title, thumbnail_url, random_filename, mp3_artist='Unknown', mp3_title='Unknown', mp3_album='Unknown', tempDIR=tempDIR, downloadDIR=downloadDIR):
|
def convert_to_mp3(title, thumbnail_url, random_filename, mp3_artist='Unknown', mp3_title='Unknown', mp3_album='Unknown', tempDIR=tempDIR, downloadDIR=downloadDIR):
|
||||||
image_file = os.path.join(tempDIR, random_filename + '_thumbnail.jpg')
|
image_file = os.path.join(tempDIR, random_filename + '_thumbnail.jpg')
|
||||||
|
|||||||
Reference in New Issue
Block a user