mirror of
https://github.com/neosubhamoy/pytubepp.git
synced 2026-02-04 18:22:23 +05:30
Compare commits
8 Commits
v1.1.3-sta
...
v1.1.5-sta
15
README.md
15
README.md
@@ -62,6 +62,8 @@
|
|||||||
|
|
||||||
> Use `pip3` command instead of `pip` if you are on Linux or MacOS.
|
> Use `pip3` command instead of `pip` if you are on Linux or MacOS.
|
||||||
|
|
||||||
|
> Use `--break-system-packages` flag to install 'PytubePP' in global environment if you get `error: externally-managed-environment` while installing in Linux or MacOS (Don't worry it will not break your system packages, it's just a security mesure)
|
||||||
|
|
||||||
```terminal
|
```terminal
|
||||||
pip install pytubepp
|
pip install pytubepp
|
||||||
```
|
```
|
||||||
@@ -72,21 +74,29 @@ pip install pytubepp
|
|||||||
pip install pytubefix pytubepp --upgrade
|
pip install pytubefix pytubepp --upgrade
|
||||||
```
|
```
|
||||||
|
|
||||||
|
**UNINSTALL: If you want to uninstall PytubePP (Use the command below to uninstall) NOTE: it will only remove the 'PytubePP' python package**
|
||||||
|
```
|
||||||
|
pip uninstall pytubepp -y
|
||||||
|
```
|
||||||
|
|
||||||
### **📌 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 principle -> `Use Default Configuration if No Flags are Passed`
|
||||||
* To download a video in default configuration (maximum resolution and without any caption by default) 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"
|
||||||
```
|
```
|
||||||
|
> NOTE: This command will behave differently if you have changed default configurations
|
||||||
* To download the video in a specific resolution (suppose 480p) the command will be:
|
* To download the video in a specific resolution (suppose 480p) the command will be:
|
||||||
```terminal
|
```terminal
|
||||||
pytubepp "https://youtube.com/watch?v=2lAe1cqCOXo" -s 480p
|
pytubepp "https://youtube.com/watch?v=2lAe1cqCOXo" -s 480p
|
||||||
```
|
```
|
||||||
|
> NOTE: PytubePP always uses default configuration of flags if they are not passed for example if you only pass `-s` flag then it will use the default caption along with it, if you only pass `-c` then it will use default stream and vice versa
|
||||||
* To download the video with embeded caption (suppose en - English) the command will be:
|
* To download the video with embeded caption (suppose en - English) the command will be:
|
||||||
```terminal
|
```terminal
|
||||||
pytubepp "https://youtube.com/watch?v=2lAe1cqCOXo" -c en
|
pytubepp "https://youtube.com/watch?v=2lAe1cqCOXo" -c en
|
||||||
```
|
```
|
||||||
|
> NOTE: You can override and disable default caption for the current video if you pass `-c none`
|
||||||
* 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
|
||||||
@@ -101,8 +111,9 @@ 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 |
|
| -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) + `none` for No Caption 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` |
|
||||||
|
|||||||
@@ -4,7 +4,7 @@ build-backend = "setuptools.build_meta"
|
|||||||
|
|
||||||
[project]
|
[project]
|
||||||
name = "pytubepp"
|
name = "pytubepp"
|
||||||
version = "1.1.3"
|
version = "1.1.5"
|
||||||
authors = [
|
authors = [
|
||||||
{ name="Subhamoy Biswas", email="hey@neosubhamoy.com" },
|
{ name="Subhamoy Biswas", email="hey@neosubhamoy.com" },
|
||||||
]
|
]
|
||||||
|
|||||||
115
pytubepp/main.py
115
pytubepp/main.py
@@ -3,7 +3,7 @@ from tabulate import tabulate
|
|||||||
from .config import get_temporary_directory, load_config, update_config, reset_config
|
from .config import get_temporary_directory, load_config, update_config, reset_config
|
||||||
from .download import download_progressive, download_nonprogressive, download_audio, progress
|
from .download import download_progressive, download_nonprogressive, download_audio, progress
|
||||||
from .postprocess import merge_audio_video, convert_to_mp3
|
from .postprocess import merge_audio_video, convert_to_mp3
|
||||||
from .utils import get_version, clear_temp_files, is_valid_url, network_available
|
from .utils import get_version, clear_temp_files, is_valid_url, network_available, ffmpeg_installed, nodejs_installed
|
||||||
import appdirs, os, re, sys, argparse, json
|
import appdirs, os, re, sys, argparse, json
|
||||||
|
|
||||||
class YouTubeDownloader:
|
class YouTubeDownloader:
|
||||||
@@ -42,10 +42,15 @@ class YouTubeDownloader:
|
|||||||
if not network_available():
|
if not network_available():
|
||||||
print('\nRequest timeout! Please check your network and try again...!!')
|
print('\nRequest timeout! Please check your network and try again...!!')
|
||||||
sys.exit()
|
sys.exit()
|
||||||
|
|
||||||
|
if not nodejs_installed():
|
||||||
|
print("\nWarning: Node.js is not installed or not found in PATH!")
|
||||||
|
print("BotGuard poToken generation will not work properly without Node.js environment")
|
||||||
|
print("Please install Node.js from https://nodejs.org/en/download\n")
|
||||||
|
|
||||||
if is_valid_url(link):
|
if is_valid_url(link):
|
||||||
link = is_valid_url(link).group(1)
|
link = is_valid_url(link).group(1)
|
||||||
self.video = YouTube(link, 'ANDROID', on_progress_callback=progress)
|
self.video = YouTube(link, 'WEB', on_progress_callback=progress)
|
||||||
self.author = self.video.author
|
self.author = self.video.author
|
||||||
self.title = re.sub(r'[\\/*?:"<>|]', '_', self.author + ' - ' + self.video.title)
|
self.title = re.sub(r'[\\/*?:"<>|]', '_', self.author + ' - ' + self.video.title)
|
||||||
self.thumbnail = self.video.thumbnail_url
|
self.thumbnail = self.video.thumbnail_url
|
||||||
@@ -90,7 +95,7 @@ class YouTubeDownloader:
|
|||||||
'ado_bitrate': matching_stream.abr
|
'ado_bitrate': matching_stream.abr
|
||||||
}
|
}
|
||||||
else:
|
else:
|
||||||
_select_suitable_audio_stream = lambda stream: 139 if stream.itag in [160, 133] else (251 if stream.mime_type == 'video/webm' else 140)
|
_select_suitable_audio_stream = lambda stream: 251 if stream.mime_type == 'video/webm' else 140
|
||||||
# Check for HDR variants first
|
# Check for HDR variants first
|
||||||
hdr_stream = None
|
hdr_stream = None
|
||||||
if res in ['4320p', '2160p', '1440p', '1080p', '720p']:
|
if res in ['4320p', '2160p', '1440p', '1080p', '720p']:
|
||||||
@@ -152,6 +157,24 @@ class YouTubeDownloader:
|
|||||||
else:
|
else:
|
||||||
print('\nInvalid video link! Please enter a valid video url...!!')
|
print('\nInvalid video link! Please enter a valid video url...!!')
|
||||||
|
|
||||||
|
def show_all_streams(self, link):
|
||||||
|
if self.set_video_info(link):
|
||||||
|
print(f"Available Streams({len(self.stream)}):")
|
||||||
|
if self.stream:
|
||||||
|
for stream in self.stream:
|
||||||
|
print(stream)
|
||||||
|
else:
|
||||||
|
print('No stream available!')
|
||||||
|
|
||||||
|
print(f"\nAvailable Captions({len(self.captions)}):")
|
||||||
|
if self.captions:
|
||||||
|
for caption in self.captions:
|
||||||
|
print(caption)
|
||||||
|
else:
|
||||||
|
print('No caption available!')
|
||||||
|
else:
|
||||||
|
print('\nInvalid video link! Please enter a valid video url...!!')
|
||||||
|
|
||||||
def show_raw_info(self, link, prettify=False):
|
def show_raw_info(self, link, prettify=False):
|
||||||
if self.set_video_info(link):
|
if self.set_video_info(link):
|
||||||
streams_list = []
|
streams_list = []
|
||||||
@@ -217,22 +240,38 @@ class YouTubeDownloader:
|
|||||||
print('\nInvalid video link! Please enter a valid video url...!!')
|
print('\nInvalid video link! Please enter a valid video url...!!')
|
||||||
return []
|
return []
|
||||||
|
|
||||||
def print_short_info(self, chosen_stream):
|
def print_short_info(self, chosen_stream, chosen_caption=None):
|
||||||
resolution_map = {
|
print(f'\nTitle: {self.title}')
|
||||||
'4320': '4320p (8K)', '4320p': '4320p (8K)', '8k': '4320p (8K)',
|
|
||||||
'2160': '2160p (4K)', '2160p': '2160p (4K)', '4k': '2160p (4K)',
|
if chosen_stream == 'mp3':
|
||||||
'1440': '1440p (2K)', '1440p': '1440p (2K)', '2k': '1440p (2K)',
|
print(f'Selected: Audio [128kbps (140)]')
|
||||||
'1080': '1080p (FHD)', '1080p': '1080p (FHD)', 'fhd': '1080p (FHD)',
|
return
|
||||||
'720': '720p (HD)', '720p': '720p (HD)', 'hd': '720p (HD)',
|
|
||||||
'480': '480p (SD)', '480p': '480p (SD)',
|
if chosen_stream in ['360', '360p']:
|
||||||
'360': '360p (SD)', '360p': '360p (SD)',
|
print(f"Selected: Video [360p (18)] + Audio [96kbps (18)]{f' + Caption [{chosen_caption}]' if chosen_caption else ''}")
|
||||||
'240': '240p (LD)', '240p': '240p (LD)',
|
return
|
||||||
'144': '144p (LD)', '144p': '144p (LD)',
|
|
||||||
'mp3': 'mp3 (Audio)'
|
_select_suitable_audio_stream = lambda stream: 251 if stream.mime_type == 'video/webm' else 140
|
||||||
}
|
res = next((k for k, v in self.stream_resolutions.items() if chosen_stream in v['allowed_streams']), None)
|
||||||
print(f'\nTitle: {self.title}\nSelected Stream: {resolution_map.get(chosen_stream, "Unknown")}\n')
|
|
||||||
|
if res:
|
||||||
|
hdr_stream = None
|
||||||
|
if res in ['4320p', '2160p', '1440p', '1080p', '720p']:
|
||||||
|
hdr_itags = {'4320p': 702, '2160p': 701, '1440p': 700, '1080p': 699, '720p': 698}
|
||||||
|
hdr_stream = self.stream.get_by_itag(hdr_itags.get(res))
|
||||||
|
|
||||||
|
matching_stream = hdr_stream if hdr_stream else self.stream.filter(res=res).first()
|
||||||
|
audio_stream = self.stream.get_by_itag(_select_suitable_audio_stream(matching_stream))
|
||||||
|
|
||||||
|
print(f"Selected: Video [{res} ({matching_stream.itag})] + Audio [{audio_stream.abr} ({audio_stream.itag})]{f' + Caption [{chosen_caption}]' if chosen_caption else ''}")
|
||||||
|
|
||||||
def download_stream(self, link, chosen_stream, chosen_caption=None):
|
def download_stream(self, link, chosen_stream, chosen_caption=None):
|
||||||
|
if not ffmpeg_installed():
|
||||||
|
print("\nWarning: FFmpeg is not installed or not found in PATH!")
|
||||||
|
print("Some core functionalities like video processing will not work properly without FFmpeg")
|
||||||
|
print("Please install FFmpeg, read https://github.com/neosubhamoy/pytubepp#%EF%B8%8F-installation for instructions\n")
|
||||||
|
sys.exit()
|
||||||
|
|
||||||
if self.set_video_info(link):
|
if self.set_video_info(link):
|
||||||
allowed_streams = self.get_allowed_streams(link)
|
allowed_streams = self.get_allowed_streams(link)
|
||||||
allowed_captions = self.get_allowed_captions(link)
|
allowed_captions = self.get_allowed_captions(link)
|
||||||
@@ -242,7 +281,7 @@ class YouTubeDownloader:
|
|||||||
sys.exit()
|
sys.exit()
|
||||||
|
|
||||||
if chosen_stream in allowed_streams:
|
if chosen_stream in allowed_streams:
|
||||||
self.print_short_info(chosen_stream)
|
self.print_short_info(chosen_stream, chosen_caption)
|
||||||
if chosen_stream in ['360', '360p']:
|
if chosen_stream in ['360', '360p']:
|
||||||
download_progressive(self.stream, 18, self.title, '360p', 'mp4', self.captions, chosen_caption)
|
download_progressive(self.stream, 18, self.title, '360p', 'mp4', self.captions, chosen_caption)
|
||||||
elif chosen_stream in ['1080', '1080p', 'fhd']:
|
elif chosen_stream in ['1080', '1080p', 'fhd']:
|
||||||
@@ -252,9 +291,9 @@ class YouTubeDownloader:
|
|||||||
elif chosen_stream in ['480', '480p']:
|
elif chosen_stream in ['480', '480p']:
|
||||||
merge_audio_video(self.title, '480p', 'mp4', download_nonprogressive(self.stream, 135, 140, 'mp4', self.temp_dir), self.captions, chosen_caption)
|
merge_audio_video(self.title, '480p', 'mp4', download_nonprogressive(self.stream, 135, 140, 'mp4', self.temp_dir), self.captions, chosen_caption)
|
||||||
elif chosen_stream in ['240', '240p']:
|
elif chosen_stream in ['240', '240p']:
|
||||||
merge_audio_video(self.title, '240p', 'mp4', download_nonprogressive(self.stream, 133, 139, 'mp4', self.temp_dir), self.captions, chosen_caption)
|
merge_audio_video(self.title, '240p', 'mp4', download_nonprogressive(self.stream, 133, 140, 'mp4', self.temp_dir), self.captions, chosen_caption)
|
||||||
elif chosen_stream in ['144', '144p']:
|
elif chosen_stream in ['144', '144p']:
|
||||||
merge_audio_video(self.title, '144p', 'mp4', download_nonprogressive(self.stream, 160, 139, 'mp4', self.temp_dir), self.captions, chosen_caption)
|
merge_audio_video(self.title, '144p', 'mp4', download_nonprogressive(self.stream, 160, 140, 'mp4', self.temp_dir), self.captions, chosen_caption)
|
||||||
elif chosen_stream in ['4320', '4320p', '8k']:
|
elif chosen_stream in ['4320', '4320p', '8k']:
|
||||||
self._handle_4320p_download(chosen_caption)
|
self._handle_4320p_download(chosen_caption)
|
||||||
elif chosen_stream in ['2160', '2160p', '4k']:
|
elif chosen_stream in ['2160', '2160p', '4k']:
|
||||||
@@ -315,8 +354,9 @@ def main():
|
|||||||
parser.add_argument('-ds', '--default-stream', default=argparse.SUPPRESS, help='set default download stream (default: max) [available arguments: 144p, 240p, 360p, 480p, 720p, 1080p, 1440p, 2160p, 4320p, mp3, max]')
|
parser.add_argument('-ds', '--default-stream', default=argparse.SUPPRESS, help='set default download stream (default: max) [available arguments: 144p, 240p, 360p, 480p, 720p, 1080p, 1440p, 2160p, 4320p, mp3, max]')
|
||||||
parser.add_argument('-dc', '--default-caption', default=argparse.SUPPRESS, help='set default caption (default: none) [available arguments: all language codes, none]')
|
parser.add_argument('-dc', '--default-caption', default=argparse.SUPPRESS, help='set default caption (default: none) [available arguments: all language codes, none]')
|
||||||
parser.add_argument('-s', '--stream', default=argparse.SUPPRESS, help='choose download stream for the current video (default: your chosen --default-stream) [available arguments: 144p, 240p, 360p, 480p, 720p, 1080p, 1440p, 2160p, 4320p, 144, 240, 360, 480, 720, 1080, 1440, 2160, 4320, mp3, hd, fhd, 2k, 4k, 8k]')
|
parser.add_argument('-s', '--stream', default=argparse.SUPPRESS, help='choose download stream for the current video (default: your chosen --default-stream) [available arguments: 144p, 240p, 360p, 480p, 720p, 1080p, 1440p, 2160p, 4320p, 144, 240, 360, 480, 720, 1080, 1440, 2160, 4320, mp3, hd, fhd, 2k, 4k, 8k]')
|
||||||
parser.add_argument('-c', '--caption', default=argparse.SUPPRESS, help='choose caption to embed for the current video (default: none)')
|
parser.add_argument('-c', '--caption', default=argparse.SUPPRESS, help='choose caption to embed for the current video (default: your chosen --default-caption) [available arguments: all language codes, none]')
|
||||||
parser.add_argument('-i', '--show-info', action='store_true', help='show video info (title, author, views and available_streams)')
|
parser.add_argument('-i', '--show-info', action='store_true', help='show video info (title, author, views and available_streams)')
|
||||||
|
parser.add_argument('-ls', '--list-stream', action='store_true', help='list all available streams (video, audio, caption) (only for debuging purposes)')
|
||||||
parser.add_argument('-ri', '--raw-info', action='store_true', help='show video info in raw json format')
|
parser.add_argument('-ri', '--raw-info', action='store_true', help='show video info in raw json format')
|
||||||
parser.add_argument('-jp', '--json-prettify', action='store_true', help='show json in prettified indented view')
|
parser.add_argument('-jp', '--json-prettify', action='store_true', help='show json in prettified indented view')
|
||||||
parser.add_argument('-sc', '--show-config', action='store_true', help='show all current user config settings')
|
parser.add_argument('-sc', '--show-config', action='store_true', help='show all current user config settings')
|
||||||
@@ -352,6 +392,8 @@ def main():
|
|||||||
# Handle info display flags
|
# Handle info display flags
|
||||||
if args.show_info:
|
if args.show_info:
|
||||||
downloader.show_video_info(args.url)
|
downloader.show_video_info(args.url)
|
||||||
|
if args.list_stream:
|
||||||
|
downloader.show_all_streams(args.url)
|
||||||
if args.raw_info:
|
if args.raw_info:
|
||||||
downloader.show_raw_info(args.url, args.json_prettify)
|
downloader.show_raw_info(args.url, args.json_prettify)
|
||||||
if args.json_prettify and not args.raw_info:
|
if args.json_prettify and not args.raw_info:
|
||||||
@@ -360,9 +402,11 @@ def main():
|
|||||||
# Handle download cases
|
# Handle download cases
|
||||||
if hasattr(args, 'stream') and hasattr(args, 'caption'):
|
if hasattr(args, 'stream') and hasattr(args, 'caption'):
|
||||||
if downloader.set_video_info(args.url):
|
if downloader.set_video_info(args.url):
|
||||||
if args.caption not in downloader.captions.keys():
|
if (args.caption not in downloader.captions.keys()) and (args.caption != 'none'):
|
||||||
print('\nInvalid caption code or caption not available! Please choose a different caption...!! (use -i to see available captions)')
|
print('\nInvalid caption code or caption not available! Please choose a different caption...!! (use -i to see available captions)')
|
||||||
sys.exit()
|
sys.exit()
|
||||||
|
elif args.caption == 'none':
|
||||||
|
downloader.download_stream(args.url, args.stream)
|
||||||
elif args.stream == 'mp3' and downloader.stream.get_by_itag(140):
|
elif args.stream == 'mp3' and downloader.stream.get_by_itag(140):
|
||||||
print(f'\nYou have chosen to download mp3 stream! ( Captioning audio files is not supported )')
|
print(f'\nYou have chosen to download mp3 stream! ( Captioning audio files is not supported )')
|
||||||
answer = input('Do you still want to continue downloading ? [yes/no]\n')
|
answer = input('Do you still want to continue downloading ? [yes/no]\n')
|
||||||
@@ -403,9 +447,29 @@ def main():
|
|||||||
print('Download cancelled! exiting...!!')
|
print('Download cancelled! exiting...!!')
|
||||||
elif hasattr(args, 'caption'):
|
elif hasattr(args, 'caption'):
|
||||||
if downloader.set_video_info(args.url):
|
if downloader.set_video_info(args.url):
|
||||||
if args.caption not in downloader.captions.keys():
|
if (args.caption not in downloader.captions.keys()) and (args.caption != 'none'):
|
||||||
print('\nInvalid caption code or caption not available! Please choose a different caption...!! (use -i to see available captions)')
|
print('\nInvalid caption code or caption not available! Please choose a different caption...!! (use -i to see available captions)')
|
||||||
sys.exit()
|
sys.exit()
|
||||||
|
elif args.caption == 'none':
|
||||||
|
if downloader.default_stream == 'max' and downloader.maxres:
|
||||||
|
downloader.download_stream(args.url, downloader.maxres)
|
||||||
|
elif downloader.default_stream == 'mp3' and downloader.stream.get_by_itag(140):
|
||||||
|
downloader.download_stream(args.url, downloader.default_stream)
|
||||||
|
elif downloader.default_stream != 'max' and downloader.stream.filter(res=downloader.default_stream):
|
||||||
|
downloader.download_stream(args.url, downloader.default_stream)
|
||||||
|
else:
|
||||||
|
if downloader.maxres:
|
||||||
|
print(f'\nDefault stream not available! ( Default: {downloader.default_stream} | Available: {downloader.maxres} )')
|
||||||
|
answer = input('Do you want to download the maximum available stream ? [yes/no]\n')
|
||||||
|
while answer not in ['yes', 'y', 'no', 'n']:
|
||||||
|
print('Invalid answer! try again...!! answer with: [yes/y/no/n]')
|
||||||
|
answer = input('Do you want to download the maximum available stream ? [yes/no]\n')
|
||||||
|
if answer in ['yes', 'y']:
|
||||||
|
downloader.download_stream(args.url, downloader.maxres)
|
||||||
|
else:
|
||||||
|
print('Download cancelled! exiting...!!')
|
||||||
|
else:
|
||||||
|
print('Sorry, No downloadable video stream found....!!!')
|
||||||
elif downloader.default_stream == 'max' and downloader.maxres:
|
elif downloader.default_stream == 'max' and downloader.maxres:
|
||||||
downloader.download_stream(args.url, downloader.maxres, args.caption)
|
downloader.download_stream(args.url, downloader.maxres, args.caption)
|
||||||
elif downloader.default_stream == 'mp3' and downloader.stream.get_by_itag(140):
|
elif downloader.default_stream == 'mp3' and downloader.stream.get_by_itag(140):
|
||||||
@@ -433,7 +497,7 @@ def main():
|
|||||||
print('Download cancelled! exiting...!!')
|
print('Download cancelled! exiting...!!')
|
||||||
else:
|
else:
|
||||||
print('Sorry, No downloadable video stream found....!!!')
|
print('Sorry, No downloadable video stream found....!!!')
|
||||||
elif not any([args.show_info, args.raw_info, args.json_prettify]): # If no info flags are set
|
elif not any([args.show_info, args.raw_info, args.json_prettify, args.list_stream]): # If no info flags are set
|
||||||
if downloader.set_video_info(args.url):
|
if downloader.set_video_info(args.url):
|
||||||
if downloader.default_stream == 'max' and downloader.maxres:
|
if downloader.default_stream == 'max' and downloader.maxres:
|
||||||
if downloader.default_caption == 'none':
|
if downloader.default_caption == 'none':
|
||||||
@@ -546,6 +610,9 @@ def main():
|
|||||||
if args.show_info:
|
if args.show_info:
|
||||||
print('\nNo video url supplied! exiting...!!')
|
print('\nNo video url supplied! exiting...!!')
|
||||||
|
|
||||||
|
if args.list_stream:
|
||||||
|
print('\nNo video url supplied! exiting...!!')
|
||||||
|
|
||||||
if args.raw_info:
|
if args.raw_info:
|
||||||
print('\nNo video url supplied! exiting...!!')
|
print('\nNo video url supplied! exiting...!!')
|
||||||
|
|
||||||
|
|||||||
@@ -14,6 +14,20 @@ def network_available():
|
|||||||
return True
|
return True
|
||||||
except subprocess.CalledProcessError:
|
except subprocess.CalledProcessError:
|
||||||
return False
|
return False
|
||||||
|
|
||||||
|
def nodejs_installed():
|
||||||
|
try:
|
||||||
|
subprocess.run(['node', '--version'], stdout=subprocess.DEVNULL, stderr=subprocess.DEVNULL, check=True)
|
||||||
|
return True
|
||||||
|
except (subprocess.CalledProcessError, FileNotFoundError):
|
||||||
|
return False
|
||||||
|
|
||||||
|
def ffmpeg_installed():
|
||||||
|
try:
|
||||||
|
subprocess.run(['ffmpeg', '-version'], stdout=subprocess.DEVNULL, stderr=subprocess.DEVNULL, check=True)
|
||||||
|
return True
|
||||||
|
except (subprocess.CalledProcessError, FileNotFoundError):
|
||||||
|
return False
|
||||||
|
|
||||||
def get_version():
|
def get_version():
|
||||||
try:
|
try:
|
||||||
|
|||||||
Reference in New Issue
Block a user