mirror of
https://github.com/neosubhamoy/pytubepp.git
synced 2026-02-04 18:22:23 +05:30
Compare commits
8 Commits
v1.0.3-sta
...
v1.0.5-sta
12
README.md
12
README.md
@@ -1,16 +1,18 @@
|
|||||||
# pytubePP - (Pytube Post Processor)
|
# PytubePP - (Pytube Post Processor)
|
||||||
|
|
||||||
### A Simple CLI Tool to Download Your Favourite YouTube Videos Effortlessly!
|
### A Simple CLI Tool to Download Your Favourite YouTube Videos Effortlessly!
|
||||||
|
|
||||||
[](https://github.com/neosubhamoy/pytubepp/)
|
[](https://github.com/neosubhamoy/pytubepp/)
|
||||||
[](https://github.com/neosubhamoy/pytubepp/)
|
[](https://github.com/neosubhamoy/pytubepp/)
|
||||||
[](https://www.python.org/downloads/)
|
[](https://www.python.org/downloads/)
|
||||||
[](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 Computer and add [PytubePP Extension](https://github.com/neosubhamoy/pytubepp-extension) in your Browser to get started.
|
||||||
|
|
||||||
### **🏷️ Features**
|
### **🏷️ Features**
|
||||||
* Auto Post-Process & Merge YouTube DASH Streams
|
* Auto Post-Process & Merge YouTube DASH Streams
|
||||||
|
* Supports upto 8K 60fps HDR Stream Download
|
||||||
* Supports MP3 Download (with Embeded Thumbnail and Tags)
|
* Supports MP3 Download (with Embeded Thumbnail and Tags)
|
||||||
* Smart Stream Selection
|
* Smart Stream Selection
|
||||||
* Highly Configurable and Many More 😉
|
* Highly Configurable and Many More 😉
|
||||||
@@ -56,7 +58,11 @@ pytubepp "https://youtube.com/watch?v=2lAe1cqCOXo" -s 480p
|
|||||||
```terminal
|
```terminal
|
||||||
pytubepp "https://youtube.com/watch?v=2lAe1cqCOXo" -s mp3
|
pytubepp "https://youtube.com/watch?v=2lAe1cqCOXo" -s mp3
|
||||||
```
|
```
|
||||||
* To cancel/stop an ongoing download press `CTRL` + `C` on keyboard.
|
* To fetch the video information the command will be:
|
||||||
|
```terminal
|
||||||
|
pytubepp "https://youtube.com/watch?v=2lAe1cqCOXo" -i
|
||||||
|
```
|
||||||
|
* To cancel/stop an ongoing download press `CTRL` + `C` on keyboard (it is recommended to run the `-ct` flag once after canceling an ongoing download).
|
||||||
* List of all available flags are given below:
|
* List of all available flags are given below:
|
||||||
|
|
||||||
| Flag | Usage | Requires Parameter | Requires URL | Parameters | Default |
|
| Flag | Usage | Requires Parameter | Requires URL | Parameters | Default |
|
||||||
|
|||||||
123
pytubepp/main.py
123
pytubepp/main.py
@@ -2,12 +2,22 @@ from pytubefix import YouTube
|
|||||||
from mutagen.id3 import ID3, APIC, TIT2, TPE1, TALB
|
from mutagen.id3 import ID3, APIC, TIT2, TPE1, TALB
|
||||||
from tabulate import tabulate
|
from tabulate import tabulate
|
||||||
from tqdm import tqdm
|
from tqdm import tqdm
|
||||||
import appdirs, ffmpy, requests, re, os, sys, random, shutil, platform, json, argparse, tempfile, pkg_resources
|
from importlib.metadata import version
|
||||||
|
import appdirs, ffmpy, requests, re, os, sys, random, shutil, platform, json, argparse, tempfile, subprocess
|
||||||
|
|
||||||
|
def network_available():
|
||||||
|
try:
|
||||||
|
param = '-n' if platform.system().lower() == 'windows' else '-c'
|
||||||
|
command = ['ping', param, '1', 'youtube.com']
|
||||||
|
subprocess.run(command, stdout=subprocess.DEVNULL, stderr=subprocess.DEVNULL, check=True)
|
||||||
|
return True
|
||||||
|
except subprocess.CalledProcessError:
|
||||||
|
return False
|
||||||
|
|
||||||
def get_version():
|
def get_version():
|
||||||
try:
|
try:
|
||||||
return pkg_resources.get_distribution("pytubepp").version
|
return version('pytubepp')
|
||||||
except pkg_resources.DistributionNotFound:
|
except Exception as e:
|
||||||
return "Unknown"
|
return "Unknown"
|
||||||
|
|
||||||
def get_download_folder():
|
def get_download_folder():
|
||||||
@@ -231,6 +241,10 @@ def is_valid_url(url):
|
|||||||
return match
|
return match
|
||||||
|
|
||||||
def set_global_video_info(link):
|
def set_global_video_info(link):
|
||||||
|
if not network_available():
|
||||||
|
print('\nRequest timeout! Please check your network and try again...!!')
|
||||||
|
sys.exit()
|
||||||
|
|
||||||
if is_valid_url(link):
|
if is_valid_url(link):
|
||||||
global video, author, title, thumbnail, views, stream, stream_resolutions, maxres
|
global video, author, title, thumbnail, views, stream, stream_resolutions, maxres
|
||||||
link = is_valid_url(link).group(1)
|
link = is_valid_url(link).group(1)
|
||||||
@@ -311,15 +325,75 @@ def show_video_info(link):
|
|||||||
ado_codec = stream.get_by_itag(140).audio_codec
|
ado_codec = stream.get_by_itag(140).audio_codec
|
||||||
vdo_bitrate = f"{matching_stream.bitrate / 1024:.0f}kbps"
|
vdo_bitrate = f"{matching_stream.bitrate / 1024:.0f}kbps"
|
||||||
ado_bitrate = stream.get_by_itag(140).abr
|
ado_bitrate = stream.get_by_itag(140).abr
|
||||||
if res in ['2160p', '1440p']:
|
if res == '2160p':
|
||||||
type = matching_stream.mime_type
|
if stream.get_by_itag(701):
|
||||||
filesize = f"{(matching_stream.filesize + stream.get_by_itag(251).filesize) / (1024 * 1024):.2f} MB"
|
type = stream.get_by_itag(701).mime_type
|
||||||
fps = f"{matching_stream.fps}fps"
|
filesize = f"{(stream.get_by_itag(701).filesize + stream.get_by_itag(140).filesize) / (1024 * 1024):.2f} MB"
|
||||||
vdo_codec = matching_stream.video_codec
|
fps = f"{stream.get_by_itag(701).fps}fps"
|
||||||
ado_codec = stream.get_by_itag(251).audio_codec
|
vdo_codec = stream.get_by_itag(701).video_codec
|
||||||
vdo_bitrate = f"{matching_stream.bitrate / 1024:.0f}kbps"
|
ado_codec = stream.get_by_itag(140).audio_codec
|
||||||
ado_bitrate = stream.get_by_itag(251).abr
|
vdo_bitrate = f"{stream.get_by_itag(701).bitrate / 1024:.0f}kbps"
|
||||||
elif res in ['1080p', '720p', '480p']:
|
ado_bitrate = stream.get_by_itag(140).abr
|
||||||
|
else:
|
||||||
|
type = matching_stream.mime_type
|
||||||
|
filesize = f"{(matching_stream.filesize + stream.get_by_itag(251).filesize) / (1024 * 1024):.2f} MB"
|
||||||
|
fps = f"{matching_stream.fps}fps"
|
||||||
|
vdo_codec = matching_stream.video_codec
|
||||||
|
ado_codec = stream.get_by_itag(251).audio_codec
|
||||||
|
vdo_bitrate = f"{matching_stream.bitrate / 1024:.0f}kbps"
|
||||||
|
ado_bitrate = stream.get_by_itag(251).abr
|
||||||
|
elif res == '1440p':
|
||||||
|
if stream.get_by_itag(700):
|
||||||
|
type = stream.get_by_itag(700).mime_type
|
||||||
|
filesize = f"{(stream.get_by_itag(700).filesize + stream.get_by_itag(140).filesize) / (1024 * 1024):.2f} MB"
|
||||||
|
fps = f"{stream.get_by_itag(700).fps}fps"
|
||||||
|
vdo_codec = stream.get_by_itag(700).video_codec
|
||||||
|
ado_codec = stream.get_by_itag(140).audio_codec
|
||||||
|
vdo_bitrate = f"{stream.get_by_itag(700).bitrate / 1024:.0f}kbps"
|
||||||
|
ado_bitrate = stream.get_by_itag(140).abr
|
||||||
|
else:
|
||||||
|
type = matching_stream.mime_type
|
||||||
|
filesize = f"{(matching_stream.filesize + stream.get_by_itag(251).filesize) / (1024 * 1024):.2f} MB"
|
||||||
|
fps = f"{matching_stream.fps}fps"
|
||||||
|
vdo_codec = matching_stream.video_codec
|
||||||
|
ado_codec = stream.get_by_itag(251).audio_codec
|
||||||
|
vdo_bitrate = f"{matching_stream.bitrate / 1024:.0f}kbps"
|
||||||
|
ado_bitrate = stream.get_by_itag(251).abr
|
||||||
|
elif res == '1080p':
|
||||||
|
if stream.get_by_itag(699):
|
||||||
|
type = stream.get_by_itag(699).mime_type
|
||||||
|
filesize = f"{(stream.get_by_itag(699).filesize + stream.get_by_itag(140).filesize) / (1024 * 1024):.2f} MB"
|
||||||
|
fps = f"{stream.get_by_itag(699).fps}fps"
|
||||||
|
vdo_codec = stream.get_by_itag(699).video_codec
|
||||||
|
ado_codec = stream.get_by_itag(140).audio_codec
|
||||||
|
vdo_bitrate = f"{stream.get_by_itag(699).bitrate / 1024:.0f}kbps"
|
||||||
|
ado_bitrate = stream.get_by_itag(140).abr
|
||||||
|
else:
|
||||||
|
type = matching_stream.mime_type
|
||||||
|
filesize = f"{(matching_stream.filesize + stream.get_by_itag(140).filesize) / (1024 * 1024):.2f} MB"
|
||||||
|
fps = f"{matching_stream.fps}fps"
|
||||||
|
vdo_codec = matching_stream.video_codec
|
||||||
|
ado_codec = stream.get_by_itag(140).audio_codec
|
||||||
|
vdo_bitrate = f"{matching_stream.bitrate / 1024:.0f}kbps"
|
||||||
|
ado_bitrate = stream.get_by_itag(140).abr
|
||||||
|
elif res == '720p':
|
||||||
|
if stream.get_by_itag(698):
|
||||||
|
type = stream.get_by_itag(698).mime_type
|
||||||
|
filesize = f"{(stream.get_by_itag(698).filesize + stream.get_by_itag(140).filesize) / (1024 * 1024):.2f} MB"
|
||||||
|
fps = f"{stream.get_by_itag(698).fps}fps"
|
||||||
|
vdo_codec = stream.get_by_itag(698).video_codec
|
||||||
|
ado_codec = stream.get_by_itag(140).audio_codec
|
||||||
|
vdo_bitrate = f"{stream.get_by_itag(698).bitrate / 1024:.0f}kbps"
|
||||||
|
ado_bitrate = stream.get_by_itag(140).abr
|
||||||
|
else:
|
||||||
|
type = matching_stream.mime_type
|
||||||
|
filesize = f"{(matching_stream.filesize + stream.get_by_itag(140).filesize) / (1024 * 1024):.2f} MB"
|
||||||
|
fps = f"{matching_stream.fps}fps"
|
||||||
|
vdo_codec = matching_stream.video_codec
|
||||||
|
ado_codec = stream.get_by_itag(140).audio_codec
|
||||||
|
vdo_bitrate = f"{matching_stream.bitrate / 1024:.0f}kbps"
|
||||||
|
ado_bitrate = stream.get_by_itag(140).abr
|
||||||
|
elif res == '480p':
|
||||||
type = matching_stream.mime_type
|
type = matching_stream.mime_type
|
||||||
filesize = f"{(matching_stream.filesize + stream.get_by_itag(140).filesize) / (1024 * 1024):.2f} MB"
|
filesize = f"{(matching_stream.filesize + stream.get_by_itag(140).filesize) / (1024 * 1024):.2f} MB"
|
||||||
fps = f"{matching_stream.fps}fps"
|
fps = f"{matching_stream.fps}fps"
|
||||||
@@ -362,7 +436,7 @@ def show_video_info(link):
|
|||||||
sys.exit()
|
sys.exit()
|
||||||
|
|
||||||
print(f'\nTitle: {video.title}\nAuthor: {author}\nViews: {views}\n')
|
print(f'\nTitle: {video.title}\nAuthor: {author}\nViews: {views}\n')
|
||||||
print(tabulate(table, headers=['Stream', 'Alias', 'Format', 'Size', 'FrameRate', 'V-Codec', 'A-Codec', 'V-BitRate', 'A-BitRate']))
|
print(tabulate(table, headers=['Stream', 'Alias (for -s flag)', 'Format', 'Size', 'FrameRate', 'V-Codec', 'A-Codec', 'V-BitRate', 'A-BitRate']))
|
||||||
print('\n')
|
print('\n')
|
||||||
else:
|
else:
|
||||||
print('\nInvalid video link! Please enter a valid video url...!!')
|
print('\nInvalid video link! Please enter a valid video url...!!')
|
||||||
@@ -411,13 +485,17 @@ def download_stream(link, chosen_stream):
|
|||||||
download_progressive(stream, 18, title, '360p', 'mp4')
|
download_progressive(stream, 18, title, '360p', 'mp4')
|
||||||
|
|
||||||
elif chosen_stream in ['1080', '1080p', 'fhd']:
|
elif chosen_stream in ['1080', '1080p', 'fhd']:
|
||||||
if stream.get_by_itag(299):
|
if stream.get_by_itag(699):
|
||||||
|
merge_audio_video(title, '1080p', 'mp4', download_nonprogressive(stream, 699, 140, 'mp4', tempDIR))
|
||||||
|
elif stream.get_by_itag(299):
|
||||||
merge_audio_video(title, '1080p', 'mp4', download_nonprogressive(stream, 299, 140, 'mp4', tempDIR))
|
merge_audio_video(title, '1080p', 'mp4', download_nonprogressive(stream, 299, 140, 'mp4', tempDIR))
|
||||||
elif stream.get_by_itag(137):
|
elif stream.get_by_itag(137):
|
||||||
merge_audio_video(title, '1080p', 'mp4', download_nonprogressive(stream, 137, 140, 'mp4', tempDIR))
|
merge_audio_video(title, '1080p', 'mp4', download_nonprogressive(stream, 137, 140, 'mp4', tempDIR))
|
||||||
|
|
||||||
elif chosen_stream in ['720', '720p', 'hd']:
|
elif chosen_stream in ['720', '720p', 'hd']:
|
||||||
if stream.get_by_itag(298):
|
if stream.get_by_itag(698):
|
||||||
|
merge_audio_video(title, '720p', 'mp4', download_nonprogressive(stream, 698, 140, 'mp4', tempDIR))
|
||||||
|
elif stream.get_by_itag(298):
|
||||||
merge_audio_video(title, '720p', 'mp4', download_nonprogressive(stream, 298, 140, 'mp4', tempDIR))
|
merge_audio_video(title, '720p', 'mp4', download_nonprogressive(stream, 298, 140, 'mp4', tempDIR))
|
||||||
elif stream.get_by_itag(136):
|
elif stream.get_by_itag(136):
|
||||||
merge_audio_video(title, '720p', 'mp4', download_nonprogressive(stream, 136, 140, 'mp4', tempDIR))
|
merge_audio_video(title, '720p', 'mp4', download_nonprogressive(stream, 136, 140, 'mp4', tempDIR))
|
||||||
@@ -432,16 +510,23 @@ def download_stream(link, chosen_stream):
|
|||||||
merge_audio_video(title, '144p', 'mp4', download_nonprogressive(stream, 160, 139, 'mp4', tempDIR))
|
merge_audio_video(title, '144p', 'mp4', download_nonprogressive(stream, 160, 139, 'mp4', tempDIR))
|
||||||
|
|
||||||
elif chosen_stream in ['4320', '4320p', '8k']:
|
elif chosen_stream in ['4320', '4320p', '8k']:
|
||||||
merge_audio_video(title, '8k', 'mp4', download_nonprogressive(stream, 571, 140, 'mp4', tempDIR))
|
if stream.get_by_itag(702):
|
||||||
|
merge_audio_video(title, '8k', 'mp4', download_nonprogressive(stream, 702, 140, 'mp4', tempDIR))
|
||||||
|
elif stream.get_by_itag(571):
|
||||||
|
merge_audio_video(title, '8k', 'mp4', download_nonprogressive(stream, 571, 140, 'mp4', tempDIR))
|
||||||
|
|
||||||
elif chosen_stream in ['2160', '2160p', '4k']:
|
elif chosen_stream in ['2160', '2160p', '4k']:
|
||||||
if stream.get_by_itag(315):
|
if stream.get_by_itag(701):
|
||||||
|
merge_audio_video(title, '4k', 'mp4', download_nonprogressive(stream, 701, 140, 'mp4', tempDIR))
|
||||||
|
elif stream.get_by_itag(315):
|
||||||
merge_audio_video(title, '4k', 'webm', download_nonprogressive(stream, 315, 251, 'webm', tempDIR))
|
merge_audio_video(title, '4k', 'webm', download_nonprogressive(stream, 315, 251, 'webm', tempDIR))
|
||||||
elif stream.get_by_itag(313):
|
elif stream.get_by_itag(313):
|
||||||
merge_audio_video(title, '4k', 'webm', download_nonprogressive(stream, 313, 251, 'webm', tempDIR))
|
merge_audio_video(title, '4k', 'webm', download_nonprogressive(stream, 313, 251, 'webm', tempDIR))
|
||||||
|
|
||||||
elif chosen_stream in ['1440', '1440p', '2k']:
|
elif chosen_stream in ['1440', '1440p', '2k']:
|
||||||
if stream.get_by_itag(308):
|
if stream.get_by_itag(700):
|
||||||
|
merge_audio_video(title, '2k', 'mp4', download_nonprogressive(stream, 700, 140, 'mp4', tempDIR))
|
||||||
|
elif stream.get_by_itag(308):
|
||||||
merge_audio_video(title, '2k', 'webm', download_nonprogressive(stream, 308, 251, 'webm', tempDIR))
|
merge_audio_video(title, '2k', 'webm', download_nonprogressive(stream, 308, 251, 'webm', tempDIR))
|
||||||
elif stream.get_by_itag(271):
|
elif stream.get_by_itag(271):
|
||||||
merge_audio_video(title, '2k', 'webm', download_nonprogressive(stream, 271, 251, 'webm', tempDIR))
|
merge_audio_video(title, '2k', 'webm', download_nonprogressive(stream, 271, 251, 'webm', tempDIR))
|
||||||
@@ -549,7 +634,7 @@ def main():
|
|||||||
print(f'\ndownloadDIR: {downloadDIR}\ntempDIR: {tempDIR}\nconfigDIR: {configDIR}\ndefaultStream: {defaultStream}\n')
|
print(f'\ndownloadDIR: {downloadDIR}\ntempDIR: {tempDIR}\nconfigDIR: {configDIR}\ndefaultStream: {defaultStream}\n')
|
||||||
|
|
||||||
if args.version:
|
if args.version:
|
||||||
print(f'\npytubePP (Pytube Post Processor) - version: {version}\n')
|
print(f'pytubepp {version}')
|
||||||
|
|
||||||
if args.show_info:
|
if args.show_info:
|
||||||
print('\nNo video url supplied! exiting...!!')
|
print('\nNo video url supplied! exiting...!!')
|
||||||
|
|||||||
2
setup.py
2
setup.py
@@ -6,7 +6,7 @@ with open('README.md', 'r', encoding='utf8') as file:
|
|||||||
|
|
||||||
setup(
|
setup(
|
||||||
name='pytubepp',
|
name='pytubepp',
|
||||||
version='1.0.3',
|
version='1.0.5',
|
||||||
description='A Simple CLI Tool to Download Your Favorite YouTube Videos Effortlessly!',
|
description='A Simple CLI Tool to Download Your Favorite YouTube Videos Effortlessly!',
|
||||||
long_description=readme,
|
long_description=readme,
|
||||||
long_description_content_type='text/markdown',
|
long_description_content_type='text/markdown',
|
||||||
|
|||||||
Reference in New Issue
Block a user