AI prompts
base on Modern YouTube downloader with a clean PySide6 interface. Download videos in any quality, extract audio, fetch subtitles, sponsorBlock, and view video metadata. Built with yt-dlp for reliable performance. <div align="center">
<img src="assets\branding\svg\ytsage-wordmark.svg" width="400" alt="ytsage-wordmark">
<img src="assets\branding\screenshots\main.png" width="800" alt="YTSage Interface"/>
[](https://badge.fury.io/py/ytsage)
[](https://opensource.org/licenses/MIT)
[](https://www.python.org/downloads/)
[](https://pepy.tech/project/ytsage)
[](https://github.com/oop7/YTSage/stargazers)
**A modern YouTube downloader with a clean PySide6 interface.**
Download videos in any quality, extract audio, fetch subtitles, and more.
<p align="center">
<a href="#installation">Installation</a> •
<a href="#features">Features</a> •
<a href="#usage">Usage</a> •
<a href="#screenshots">Screenshots</a> •
<a href="#troubleshooting">Troubleshooting</a> •
<a href="#contributing">Contributing</a>
</p>
</div>
---
<a id="why-ytsage"></a>
## ❓ Why YTSage?
YTSage is designed for users who want a **simple yet powerful YouTube downloader**. Unlike other tools, it offers:
- A clean, modern PySide6 interface
- One-click downloads for video, audio, and subtitles
- Advanced features like SponsorBlock, subtitle merging, and playlist selection
- Cross-platform support and easy installation
<a id="features"></a>
## ✨ Features
<div align="center">
| Core Features | Advanced Features | Extra Features |
|-----------------------------------|-----------------------------------------|------------------------------------|
| 🎥 Format Table | 🚫 SponsorBlock Integration | 💾 Save Download Path |
| 🎵 Audio Extraction | 📝 Multi-Subtitle Select & Merge | 🔄 Auto-Update yt-dlp |
| ✨ Simple UI | 💾 Save Description | 🛠️ FFmpeg/yt-dlp Detection |
| 📋 Playlist Support | 🖼️ Save thumbnail | ⚙️ Custom Commands |
| 🖼️ Playlist Selector | 🚀 Speed Limiter | 🍪 Login with Cookies |
| 📑 Embed Chapters | ✂️ Trim Video Sections | |
</div>
<a id="installation"></a>
## 🚀 Installation
### ⚡ Quick Install (Recommended)
Install YTSage from PyPI:
```bash
pip install ytsage
```
Then launch the app:
```bash
ytsage
```
### 📦 Pre-built Executables
#### 🪟 Windows
| Format | Description |
|--------|-------------|
|  | Standard installer |
|  | With FFmpeg bundled |
|  | Portable version, no installation required |
|  | Portable with FFmpeg, zipped |
#### 🐧 Linux
| Format | Description |
|--------|-------------|
|  | Debian package |
|  | AppImage, portable |
|  | RPM package |
#### 🍎 macOS
| Format | Description |
|--------|-------------|
|  | Zipped application for ARM64 |
|  | Disk image installer for ARM64 |
|  | Zipped application for x64 |
|  | Disk image installer for x64 |
> [👉 Download Latest Release](https://github.com/oop7/YTSage/releases/latest)
<details>
<summary>🛠️ Manual Installation from Source</summary>
### 1. Clone the Repository
```bash
git clone https://github.com/oop7/YTSage.git
cd YTSage
```
### 2. Install Dependencies
#### ⚡ With uv
```bash
uv pip install -r requirements.txt
```
#### 📦 Or with standard pip
```bash
pip install -r requirements.txt
```
### 3. Run the Application
```bash
python main.py
```
</details>
<a id="screenshots"></a>
## 📸 Screenshots
<div align="center">
<table>
<tr>
<td><img src="assets\branding\screenshots\main.png" alt="Main Interface" width="400"/></td>
<td><img src="assets\branding\screenshots\playlist.png" alt="Playlist Download" width="400"/></td>
</tr>
<tr>
<td align="center"><em>Main Interface</em></td>
<td align="center"><em>Playlist Download</em></td>
</tr>
<tr>
<td><img src="assets\branding\screenshots\audio_format.png" alt="Audio Format Selection with Save Thumbnail" width="400"/></td>
<td><img src="assets\branding\screenshots\subtitle_options.png" alt="Subtitle Options merged with Remove Sponsor Segments" width="400"/></td>
</tr>
<tr>
<td align="center"><em>Audio Format</em></td>
<td align="center"><em>Subtitle Options</em></td>
</tr>
</table>
</div>
<a id="usage"></a>
## 📖 Usage
<details>
<summary>🎯 Basic Usage</summary>
1. **Launch YTSage**
2. **Paste YouTube URL** (or use "Paste URL" button)
3. **Click "Analyze"**
4. **Select Format:**
- `Video` for video downloads
- `Audio Only` for audio extraction
5. **Choose Options:**
- Enable subtitles & select language
- Enable subtitle merge
- Save thumbnail
- Remove sponsor segments
- Save description
- Embed chapters
6. **Select Output Directory**
7. **Click "Download"**
</details>
<details>
<summary>📋 Playlist Download</summary>
1. **Paste Playlist URL**
2. **Click "Analyze"**
3. **Select videos from the playlist selector (optional, defaults to all)**
4. **Choose desired format/quality**
5. **Click "Download"**
> 💡 The application automatically handles the download queue
</details>
<details>
<summary>🧰 Advanced Options</summary>
- **Quality Selection:** Choose the highest resolution for best quality
- **Subtitle Options:** Filter languages and embed into video
- **Custom Commands:** Access advanced yt-dlp features
- **Save Description:** Save the description of the video
- **Save Thumbnail:** Save the thumbnail of the video
- **Embed Chapters:** Embed chapter markers as metadata in the downloaded video file for compatible video players
- **Remove Sponsor Segments:** Remove sponsor segments from the video
- **Speed Limiter:** Limit the download speed
- **Login with Cookies:** Login to YouTube using cookies to access private content
How to use it:
1. **Recommended:** Use the built-in "Extract cookies from browser" option in the app. Select your browser (Chrome, Firefox, etc.) and then select Profile (optional).
2. Alternatively, extract cookies manually:
a. Extract cookies from your browser using an extension like [cookie-editor](https://github.com/moustachauve/cookie-editor?tab=readme-ov-file)
b. Copy the cookies in Netscape format
c. Create a file named `cookies.txt` and paste the cookies into it
d. Select the `cookies.txt` file in the app
- **Save Download Path:** Save the download path
- **Update yt-dlp:** Update yt-dlp
- **FFmpeg/yt-dlp Detection:** Automatically detect FFmpeg/yt-dlp
- **Trim Video:** Download only specific parts of a video by specifying time ranges (HH:MM:SS format)
</details>
<a id="troubleshooting"></a>
## 🛠️ Troubleshooting
<details>
<summary>Click to view common issues and solutions</summary>
- **Format table not displaying:** Update yt-dlp to the latest version.
- **Download fails:** Check your internet connection and ensure the video is available.
- **Specific download errors:**
- **Private videos:** Use cookie authentication to access private content.
- **Age-restricted content:** Login to YouTube account to view age-restricted videos.
- **Geo-blocked videos:** Consider using a VPN to bypass regional restrictions.
- **Removed/deleted videos:** Video is no longer available on YouTube.
- **Live streams:** Live streams cannot be downloaded; wait for the stream to end.
- **Network errors:** Check your internet connection and try again.
- **Invalid URLs:** Ensure the URL is correct and from a supported platform.
- **Premium content:** Requires YouTube Premium membership.
- **Copyright blocks:** Content is blocked due to copyright restrictions.
- **Separate video and audio files after download:** This happens when FFmpeg is missing or not detected. YTSage requires FFmpeg to merge high-quality video and audio streams.
- **Solution:** Ensure FFmpeg is installed and accessible in your system's PATH. For Windows users, the easiest option is to download the `YTSage-v<version>-ffmpeg.exe` file, which comes bundled with FFmpeg.
---
#### 🛡️ Windows Defender / Antivirus Warning
Some antivirus software may flag the `.exe` files as false positives. This is a **known limitation** of packaged applications.
**Why this happens:**
- Antivirus heuristics can misidentify packed executables as suspicious
**Safe alternatives:**
- ✅ **Use pip installation:** `pip install ytsage` (recommended)
- ✅ **Build from source**: by following this [guide](.github/CI_CD_README.md)
- ✅ **Whitelist the application** in your antivirus software
#### 🍎 macOS: "App is damaged and can’t be opened"
If you see this error on macOS Sonoma or newer, you need to remove the quarantine attribute.
1. **Open Terminal** (you can find it using Spotlight).
2. **Type the following command** but **do not** press Enter yet. Make sure to include the space at the end:
```bash
xattr -d com.apple.quarantine
```
3. **Drag the `YTSage.app` file** from your Finder window and drop it directly into the Terminal window. This will automatically paste the correct file path.
4. **Press Enter** to run the command.
5. **Try opening YTSage.app again.** It should now launch correctly.
---
#### **Configuration Locations (Advanced)**
- **Windows:** `%LOCALAPPDATA%\YTSage`
- **macOS:** `~/Library/Application Support/YTSage`
- **Linux:** `~/.local/share/YTSage`
</details>
<a id="contributing"></a>
## 👥 Contributing
We welcome contributions! Here's how you can help:
1. 🍴 Fork the repository
2. 🌿 Create your feature branch:
```bash
git checkout -b feature/AmazingFeature
```
3. 💾 Commit your changes:
```bash
git commit -m 'Add some AmazingFeature'
```
4. 📤 Push to the branch:
```bash
git push origin feature/AmazingFeature
```
5. 🔄 Open a Pull Request
<details>
<summary>📂 Project Structure</summary>
## YTSage - Project Structure
This document describes the organized folder structure of YTSage.
### 📁 Project Structure
```
YTSage/
├── 📁 .github/ # GitHub configuration
│ ├── 📄 CI_CD_README.md # CI/CD documentation
│ ├── 📁 ISSUE_TEMPLATE/ # Issue templates
│ │ └── 🐛-bug-report.md # Bug report template
│ └── 📁 workflows/ # GitHub Actions workflows
│ ├── build-linux.yml # Linux build workflow
│ ├── build-macos.yml # macOS build workflow
│ └── build-windows.yml # Windows build workflow
├── .gitignore # Git ignore rules
├── 📁 assets/ # Static assets and resources
│ ├── 📁 branding/ # Branding assets
│ │ ├── 📁 icons/ # Application icons
│ │ │ ├── icon.icns # macOS icon
│ │ │ ├── icon.png # PNG icon
│ │ │ └── YTSage.ico # Windows icon
│ │ └── 📁 screenshots/ # Screenshots for documentation
│ │ ├── audio_format.png
│ │ ├── main.png
│ │ ├── playlist.png
│ │ └── subtitle_options.png
│ │ └── 📁 svg/ # SVG assets
│ │ └── ytsage-wordmark.svg
│ ├── 📁 Icon/ # Legacy icon directory
│ │ └── icon.png
│ └── 📁 sound/ # Audio files
│ └── notification.mp3
├── 📄 LICENSE # License file
├── 📄 main.py # Application entry point
├── 📄 README.md # Project documentation
├── 📄 requirements.txt # Python dependencies
└── 📁 src/ # Source code
├── 📄 __init__.py # Main package init
├── 📁 core/ # Core business logic
│ ├── 📄 __init__.py # Core package init
│ ├── 📄 ytsage_downloader.py # Download functionality
│ ├── 📄 ytsage_ffmpeg.py # FFmpeg integration
│ ├── 📄 ytsage_logging.py # Logging utilities
│ ├── 📄 ytsage_style.py # UI styling
│ ├── 📄 ytsage_utils.py # Utility functions
│ └── 📄 ytsage_yt_dlp.py # yt-dlp integration
├── 📁 gui/ # User interface components
│ ├── 📄 __init__.py # GUI package init
│ ├── 📄 ytsage_gui_format_table.py # Format table functionality
│ ├── 📄 ytsage_gui_main.py # Main application window
│ ├── 📄 ytsage_gui_video_info.py # Video information display
│ └── 📁 ytsage_gui_dialogs/ # Dialog classes
│ ├── 📄 __init__.py # Dialogs package init
│ ├── 📄 ytsage_dialogs_base.py # Basic dialogs
│ ├── 📄 ytsage_dialogs_custom.py # Custom functionality dialogs
│ ├── 📄 ytsage_dialogs_ffmpeg.py # FFmpeg-related dialogs
│ ├── 📄 ytsage_dialogs_selection.py # Selection dialogs
│ ├── 📄 ytsage_dialogs_settings.py # Settings dialogs
│ └── 📄 ytsage_dialogs_update.py # Update dialogs
└── 📁 utils/ # Utility modules
├── 📄 __init__.py # Utils package init
└── 📄 ytsage_constants.py # Application constants
```
</details>
## ⭐️ Star History
<div align="center">
## Star History
<a href="https://www.star-history.com/#oop7/YTSage&Date">
<picture>
<source media="(prefers-color-scheme: dark)" srcset="https://api.star-history.com/svg?repos=oop7/YTSage&type=Date&theme=dark" />
<source media="(prefers-color-scheme: light)" srcset="https://api.star-history.com/svg?repos=oop7/YTSage&type=Date" />
<img alt="Star History Chart" src="https://api.star-history.com/svg?repos=oop7/YTSage&type=Date" />
</picture>
</a>
</div>
## 📜 License
This project is licensed under the MIT License - see the [LICENSE](LICENSE) file for details.
## 🙏 Acknowledgments
<details>
<summary>Show Acknowledgments</summary>
<div align="center">
<p>A heartfelt thank you to everyone who has contributed to this project by opening an issue to suggest an improvement or report a bug.</p>
<table>
<tr class="section"><th colspan="2">Core Components</th></tr>
<tr>
<td width="35%"><a href="https://github.com/yt-dlp/yt-dlp">yt-dlp</a></td>
<td>Download Engine</td>
</tr>
<tr>
<td><a href="https://ffmpeg.org/">FFmpeg</a></td>
<td>Media Processing</td>
</tr>
<tr class="section"><th colspan="2">Libraries & Frameworks</th></tr>
<tr>
<td><a href="https://wiki.qt.io/Qt_for_Python">PySide6</a></td>
<td>GUI Framework</td>
</tr>
<tr>
<td><a href="https://python-pillow.org/">Pillow</a></td>
<td>Image Processing</td>
</tr>
<tr>
<td><a href="https://requests.readthedocs.io/">requests</a></td>
<td>HTTP Requests</td>
</tr>
<tr>
<td><a href="https://packaging.python.org/">packaging</a></td>
<td>Version & Package Handling</td>
</tr>
<tr>
<td><a href="https://python-markdown.github.io/">markdown</a></td>
<td>Markdown Rendering</td>
</tr>
<tr>
<td><a href="https://pyglet.org/">pyglet</a></td>
<td>Audio Playback</td>
</tr>
<tr>
<td><a href="https://github.com/Delgan/loguru">loguru</a></td>
<td>Logging</td>
</tr>
<tr class="section"><th colspan="2">Assets & Contributors</th></tr>
<tr>
<td><a href="https://pixabay.com/sound-effects/new-notification-09-352705/">New Notification 09 by Universfield</a></td>
<td>Notification Sound</td>
</tr>
<tr>
<td><a href="https://github.com/viru185">viru185</a></td>
<td>Code Contributor</td>
</tr>
</table>
</div>
</details>
## ⚠️ Disclaimer
This tool is for personal use only. Please respect YouTube's terms of service and content creators' rights.
---
<div align="center">
Made with ❤️ by [oop7](https://github.com/oop7)
</div>
", Assign "at most 3 tags" to the expected json: {"id":"14575","tags":[]} "only from the tags list I provide: [{"id":77,"name":"3d"},{"id":89,"name":"agent"},{"id":17,"name":"ai"},{"id":54,"name":"algorithm"},{"id":24,"name":"api"},{"id":44,"name":"authentication"},{"id":3,"name":"aws"},{"id":27,"name":"backend"},{"id":60,"name":"benchmark"},{"id":72,"name":"best-practices"},{"id":39,"name":"bitcoin"},{"id":37,"name":"blockchain"},{"id":1,"name":"blog"},{"id":45,"name":"bundler"},{"id":58,"name":"cache"},{"id":21,"name":"chat"},{"id":49,"name":"cicd"},{"id":4,"name":"cli"},{"id":64,"name":"cloud-native"},{"id":48,"name":"cms"},{"id":61,"name":"compiler"},{"id":68,"name":"containerization"},{"id":92,"name":"crm"},{"id":34,"name":"data"},{"id":47,"name":"database"},{"id":8,"name":"declarative-gui "},{"id":9,"name":"deploy-tool"},{"id":53,"name":"desktop-app"},{"id":6,"name":"dev-exp-lib"},{"id":59,"name":"dev-tool"},{"id":13,"name":"ecommerce"},{"id":26,"name":"editor"},{"id":66,"name":"emulator"},{"id":62,"name":"filesystem"},{"id":80,"name":"finance"},{"id":15,"name":"firmware"},{"id":73,"name":"for-fun"},{"id":2,"name":"framework"},{"id":11,"name":"frontend"},{"id":22,"name":"game"},{"id":81,"name":"game-engine "},{"id":23,"name":"graphql"},{"id":84,"name":"gui"},{"id":91,"name":"http"},{"id":5,"name":"http-client"},{"id":51,"name":"iac"},{"id":30,"name":"ide"},{"id":78,"name":"iot"},{"id":40,"name":"json"},{"id":83,"name":"julian"},{"id":38,"name":"k8s"},{"id":31,"name":"language"},{"id":10,"name":"learning-resource"},{"id":33,"name":"lib"},{"id":41,"name":"linter"},{"id":28,"name":"lms"},{"id":16,"name":"logging"},{"id":76,"name":"low-code"},{"id":90,"name":"message-queue"},{"id":42,"name":"mobile-app"},{"id":18,"name":"monitoring"},{"id":36,"name":"networking"},{"id":7,"name":"node-version"},{"id":55,"name":"nosql"},{"id":57,"name":"observability"},{"id":46,"name":"orm"},{"id":52,"name":"os"},{"id":14,"name":"parser"},{"id":74,"name":"react"},{"id":82,"name":"real-time"},{"id":56,"name":"robot"},{"id":65,"name":"runtime"},{"id":32,"name":"sdk"},{"id":71,"name":"search"},{"id":63,"name":"secrets"},{"id":25,"name":"security"},{"id":85,"name":"server"},{"id":86,"name":"serverless"},{"id":70,"name":"storage"},{"id":75,"name":"system-design"},{"id":79,"name":"terminal"},{"id":29,"name":"testing"},{"id":12,"name":"ui"},{"id":50,"name":"ux"},{"id":88,"name":"video"},{"id":20,"name":"web-app"},{"id":35,"name":"web-server"},{"id":43,"name":"webassembly"},{"id":69,"name":"workflow"},{"id":87,"name":"yaml"}]" returns me the "expected json"