Skip to content

Commit

Permalink
chore: Update Pyutube to version 1.2.1
Browse files Browse the repository at this point in the history
- Fix: Show the progress bar in the terminal.
- Fix: Modify the merge method to check if the video has an audio track; if not, download it as audio and merge it with the video.
- Add: Implement functionality to check the latest version of `pyutube` on PyPI, enabling notifications for new updates."
  • Loading branch information
Hetari committed Apr 20, 2024
1 parent 10f8f55 commit ee3a592
Show file tree
Hide file tree
Showing 5 changed files with 125 additions and 34 deletions.
6 changes: 6 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,11 @@
# Pyutube Changelog

## 1.2.1

- Fix: Show the progress bar in the terminal.
- Fix: Modify the merge method to check if the video has an audio track; if not, download it as audio and merge it with the video.
- Add: Implement functionality to check the latest version of `pyutube` on PyPI, enabling notifications for new updates.

## 1.2.0

- Add: New feature:
Expand Down
80 changes: 55 additions & 25 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,16 +1,18 @@
# 📹 YouTube Downloader CLI

## Enjoying my project? Please show your appreciation by starring it on GitHub! ⭐
### Enjoying my project? Please show your appreciation by starring it on GitHub! ⭐

[![Version](https://img.shields.io/pypi/v/pyutube.svg?style=flat)](https://pypi.org/project/pyutube/)
[![Downloads](https://static.pepy.tech/badge/pyutube)](https://pepy.tech/project/pyutube)

> [!NOTE]
> Help me to improve this tool!
> I tested it on Windows, Mac, and Linux, and it works fine, but if there is any issue, please open an issue on [GitHub](https://github.com/Hetari/pyutube/issues/new) and I'll fix it.
>
> Have a new feature? Please don't hesitate to [tell me](https://github.com/Hetari/pyutube/issues/new)!
<!-- for pypi only -->
<!-- <a href="https://ibb.co/27wcFYN">
<img src="https://i.ibb.co/MDbPg56/Screenshot-from-2024-04-08-21-38-02-transformed.png" alt="Pyutube" style="width: 100%;">
</a> -->

<a href="https://ibb.co/27wcFYN">
<img src="images/pyutube.png" alt="Pyutube" style="width: 100%;">
</a>
Expand All @@ -21,20 +23,12 @@ This command-line tool downloads YouTube videos from the `Terminal`, written und

it is cross-platform (Windows, Mac, Linux) and can be used in any terminal.

## 💎 Features

- User-friendly CLI interface.
- Download a single YouTube video format or audio.
- Download YouTube shorts.
- Download YouTube playlists.

## 📈 Upgrade

All the latest updates will be posted on [GitHub](https://github.com/Hetari/pyutube), you can also upgrade the tool via [PyPI](https://pypi.org/project/pyutube/) with this command:

```bash
pip install --upgrade pyutube
```
## :why: why `pyutube`?

## 🛠️ Installation

Expand All @@ -46,18 +40,52 @@ after that, you can install it with the following command:
pip install pyutube
```

## 📈 Upgrade

All the latest updates will be posted on [GitHub](https://github.com/Hetari/pyutube), you can also upgrade the tool via [PyPI](https://pypi.org/project/pyutube/) with this command:

```bash
pip install --upgrade pyutube
```

Then you can use it in your `Terminal` 🥳.

## 🦸 Usage
## 🦸 Quick Start

Pyutube is very easy to use, here are examples of its uses:

```bash
pyutube YOUTUBE_LINK [PATH]
```

> [!NOTE]
> `[PATH]` is an optional input, the default value is the `terminal` path where the CLI is running (the current working directory).
> [!NOTE] > `[PATH]` is an optional input, the default value is the `terminal` path where the CLI is running (the current working directory in your terminal).
## 🦸 Usage

<!-- for pypi only -->
<!-- <div style="text-align: center;">
<p>Download video with specify the save location</p>
<a href="https://ibb.co/0JkdkQy">
<img src="https://i.ibb.co/7yH6Hbt/image1.png" alt="Download video with specify the save location">
</a>
<p>Chose what type you want to download</p>
<a href="https://ibb.co/Kb6qjmg">
<img src="https://i.ibb.co/sbjwvt4/image2.png" alt="Chose what type you want to download">
</a>
<p>Chose what what resolution you want to download(if the type is video)</p>
<a href="https://ibb.co/7ymCS79">
<img src="https://i.ibb.co/h8z9gpq/image4.png" alt="Chose what resolution you want to download">
</a>
<p>If you download a playlist, you can choose what video you want to download, or even all of them</p>
<a href="https://ibb.co/0qwkQNm">
<img src="https://i.ibb.co/1ZS3bV7/Screenshot-from-2024-04-11-16-42-29.png" alt="If you download a playlist, you can choose what video you want to download, or even all of them"/>
</a>
<br /><br />
<p>Do not know how to use it? just type <code>pyutube --help</code></p>
<a href="https://ibb.co/LhT6r3r">
<img src="https://i.ibb.co/WprF0L0/image5.png" alt="image5">
</a>
</div> -->

<div style="text-align: center;">
<p>Download video with specify the save location</p>
Expand All @@ -72,12 +100,12 @@ pyutube YOUTUBE_LINK [PATH]

<p>Chose what what resolution you want to download(if the type is video)</p>
<a href="https://ibb.co/7ymCS79">
<img src="images/image3.png" alt="Chose what what resolution you want to download">
<img src="images/image3.png" alt="Chose what resolution you want to download">
</a>

<p>If you download a playlist, you can chose what video you want to download, or even all of them</p>
<p>If you download a playlist, you can choose what video you want to download, or even all of them</p>
<a href="https://ibb.co/0qwkQNm">
<img src="images/image4.png" alt="If you download a playlist, you can chose what video you want to download, or even all of them"/>
<img src="images/image4.png" alt="If you download a playlist, you can choose what video you want to download, or even all of them"/>
</a>

<br /><br />
Expand Down Expand Up @@ -114,19 +142,21 @@ pyutube -v
### **- Download playlists:**

1. `pyutube <YOUTUBE_PLAYLIST_LINK | PLAYLIST_ID> [the_download_path*]`
> [!NOTE]
> Don't forget, the path is optional.

> [!NOTE]
> Don't forget, the path is optional.
2. Then choose the format of the download, video or audio.
3. Choose the resolution if it is a video you want to download, otherwise, choose audio and it will download it all immediately 🔥.
> [!NOTE]
> It will check all resolutions available in the first video in the playlist, then it will download all of them in the same resolution 👍.
> [!NOTE]
> It will check all resolutions available in the first video in the playlist, then it will download all of them in the same resolution 👍.
### **- Download shorts, videos, or audio:**

1. `pyutube <YOUTUBE_LINK | VIDEO_ID | SHORT_LINK> [the_download_path*]`
> [!NOTE]
> Don't forget, the path is optional.

> [!NOTE]
> Don't forget, the path is optional.
2. Then choose the format of the download, video or audio.
3. Choose the resolution if it is a video you want to download, otherwise, choose audio and it will download it immediately 🔥.
Expand Down
3 changes: 3 additions & 0 deletions pyutube/cli.py
Original file line number Diff line number Diff line change
Expand Up @@ -45,6 +45,7 @@

from pyutube.utils import (
__version__,
__app__,
clear,
error_console,
console,
Expand All @@ -53,6 +54,7 @@
validate_link,
handle_video_link,
ask_playlist_video_names,
check_for_updates
)
from pyutube.downloader import download

Expand Down Expand Up @@ -153,6 +155,7 @@ def pyutube(
error_console.print("❗ Unsupported link type.")
sys.exit()

check_for_updates()
sys.exit()


Expand Down
12 changes: 4 additions & 8 deletions pyutube/downloader.py
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@
ask_resolution,
rename_file,
is_file_exists,
has_audio
)

import os
Expand Down Expand Up @@ -78,8 +79,7 @@ def video_search(self, url: str) -> YouTube:
)

@yaspin(
text=colored("getting video headers ", "green") +
colored("(means the video won't be fully downloaded)", "yellow"),
text=colored("getting video streams", "green"),
spinner=Spinners.point
)
def get_available_resolutions(self, video: YouTube) -> set:
Expand Down Expand Up @@ -152,10 +152,6 @@ def get_audio_streams(self, video: YouTube) -> YouTube:
"""
return video.streams.filter(only_audio=True).order_by('mime_type').first()

@yaspin(
text=colored("Saving the file...", "cyan"),
spinner=Spinners.smiley
)
def save_file(self, video: YouTube, path: str, filename: str) -> None:
"""
Save the file to the specified path with the given filename.
Expand Down Expand Up @@ -388,15 +384,15 @@ def download_video(self) -> bool:
sys.exit()
try:
self.save_file(footage, self.path, video_filename)
if not self.is_audio:
if not self.is_audio and not has_audio(video_filename, os.path.join(self.path, audio_filename)):
self.save_file(video_audio, self.path, audio_filename)
self.merging(video_filename, audio_filename)

except Exception as error:
error_console.print(f"Error: {error}")
sys.exit()

console.print("✅ Download completed", style="info")
console.print("\n\n\n✅ Download completed", style="info")
return True

def get_playlist_links(self):
Expand Down
58 changes: 57 additions & 1 deletion pyutube/utils.py
Original file line number Diff line number Diff line change
Expand Up @@ -13,9 +13,12 @@
from rich.console import Console
from rich.theme import Theme
from termcolor import colored
from moviepy.tools import subprocess_call
from moviepy.config import get_setting


__version__ = "1.2.0"
__version__ = "1.2.1"
__app__ = "pyutube"
ABORTED_PREFIX = "aborted"
CANCEL_PREFIX = "cancel"

Expand Down Expand Up @@ -382,3 +385,56 @@ def handle_video_link() -> bool:
sys.exit()

return is_audio


def has_audio(input_file, output, bitrate=3000, fps=44100):
""" extract the sound from a video file and save it in ``output`` """

try:
cmd = [
get_setting("FFMPEG_BINARY"),
"-y",
"-i",
input_file,
"-ab",
"%dk" % bitrate,
"-ar",
"%d" % fps,
output
]
subprocess_call(cmd, logger=None)
except Exception as error:
return False

os.remove(output)
return True


def check_for_updates() -> None:
"""
A function to check for updates of a given package.
Returns:
None
"""
try:
r = requests.get(
f'https://pypi.org/pypi/{__app__}/json', headers={'Accept': 'application/json'})
except Exception as error:
error_console.print(f"❗ Error checking for updates: {error}")
else:
if r.status_code == 200:
latest_version = r.json()['info']['version']
if latest_version != __version__:
console.print(
f"👉 A new version of {__app__} is available: {latest_version}. Update it by running [bold red link=https://github.com/Hetari/pyutube]pip install --upgrade {__app__}[/bold red link]",
style="warning"
)
else:
error_console.print(
f"❗ Error checking for updates: {r.status_code}")
sys.exit()


if __name__ == "__main__":
check_for_updates()

0 comments on commit ee3a592

Please sign in to comment.