Высокоуровневая обертка над yt-dlp, написанная на Python, которая фокусируется на принципе «всё включено» и максимальной автоматизации. Основная цель проекта — избавить пользователя от необходимости вручную настраивать аргументы командной строки, скачивать бинарные файлы или разбираться в селекторах форматов.
Так же: ytdlp-simple-api и ytdlp-simple-gui
- Dependency Free: никакие дополнительные pyhon-библиотеки не требуются, только стандартная библиотека Python 3.13+
- Zero Configuration: библиотека сама скачивает и обновляет необходимые исполняемые файлы (
yt-dlp,ffmpeg,bun) под Windows/Linux. Фоновое обновление бинарников черезBackgroundUpdater. Если папка приложения защищена от записи, библиотека автоматически перенесет бинарники вLocal AppDataили временную директорию. - Smart Formatting: автоматический выбор лучшего качества или оптимизация видео специально для мессенджеров (Telegram/Discord).
- Vertical Video Support: корректная обработка разрешений для Shorts, Reels и TikTok.
- Invidious Fallback: если YouTube недоступен, загрузка автоматически пойдет через зеркала Invidious.
- AI Ready: специальный режим для подготовки аудио к ASR-транскрибации (Whisper, Faster-Whisper, Speech-to-Text).
- SponsorBlock: автоматическое вырезание рекламных интеграций из видео.
- Поддержка cookies: случайный выбор из доступных файлов Netscape-формата в указанной папке.
- Performance: используется рантайм
Bunдля ускорения обработки JavaScript-сигнатур YouTube. - Auto-Repair: все скачанные файлы проходят через стадию ремуксинга. Это гарантирует правильное отображение длительности и поддержку стриминга (FastStart) в браузерах и плеерах.
uv add ytdlp-simpleили:
pip install ytdlp-simpledownload_best_audio- скачивание аудио максимального качества (opus ~130kbps)download_audio_for_transcription- подготовка аудио для транскрипции (нормализация, моно, ресемплинг)download_video_for_chat- оптимизированное видео для мессенджеров (480p/360p, минимальный битрейт)download_best_quality- максимальное качество видео (vp9 + opus)download_manual- ручной выбор всех параметровupdate_binaries_sync/async- обновление бинарниковget_binaries_sync/async- загрузка бинарников
Все функции загрузки в ytdlp-simple являются асинхронными и возвращают объект DownloadResult. Это позволяет удобно обрабатывать результаты даже в случае частичного успеха (например, когда видео скачалось, но в более низком разрешении).
| Поле | Тип | Описание |
|---|---|---|
success |
bool |
True, если загрузка завершена успешно. |
path |
Path | None |
Объект pathlib.Path к скачанному файлу. None, если произошла ошибка. |
error |
str | None |
Текст критической ошибки, из-за которой загрузка прервалась. |
warnings |
list[str] |
Список некритических предупреждений. |
result = await download_best_audio("https://...")
if result.success:
print(f"✅ Успешно: {result.path.name}")
if result.warnings:
print(f"⚠️ Внимание: {', '.join(result.warnings)}")
else:
print(f"❌ Ошибка: {result.error}")Объект имеет встроенный метод .to_json(), что делает его идеально подходящим для использования в веб-API или логах:
print(result.to_json())Пример вывода JSON:
{
"success": true,
"path": "/home/user/downloads/ytdlp_downloads/video_id.mp4",
"error": null,
"warnings": [
"480p unavailable, using 360p",
"original YouTube failed: HTTP Error 403",
"used Invidious: yewtu.be"
]
}Скачивает аудио в максимальном качестве (Opus ~130 kbps).
async def download_best_audio(
url: str,
output_dir: Path | str = None, # Директория для сохранения
prefer_lang: list[str] = None, # Предпочтительные языки ['ru', 'en']
sponsorblock: bool = True, # Вырезать рекламу через SponsorBlock
cookies_folder: Path | str = None, # Папка с cookies в Netscape-формате
) -> DownloadResultПример:
result = await download_best_audio(
"https://youtube.com/watch?v=...",
output_dir="~/Music",
prefer_lang=["ru", "en"],
sponsorblock=True
)Подготавливает аудио для систем распознавания речи (ASR): нормализация громкости, конвертация в моно, ресемплинг.
async def download_audio_for_transcription(
url: str,
output_dir: Path | str = None,
cookies_folder: Path | str = None,
sample_rate: Literal[16000, 24000] = 16000, # Whisper использует 16kHz
output_format: Literal['opus', 'flac', 'pcm'] = 'opus',
prefer_lang: list[str] = None,
) -> DownloadResultПример для Whisper:
result = await download_audio_for_transcription(
"https://youtube.com/watch?v=...",
sample_rate=16000,
output_format='flac' # Lossless для максимального качества
)
# Использование с Whisper
import whisper
model = whisper.load_model("base")
result = model.transcribe(str(result.path))Оптимизированное видео для мессенджеров и Telegram: 480p/360p, минимальный битрейт аудио, fps ≤ 30.
async def download_video_for_chat(
url: str,
output_dir: Path | str = None,
prefer_lang: list[str] = None,
sponsorblock: bool = True,
cookies_folder: Path | str = None,
) -> DownloadResultОсобенности:
- Автоматически определяет ориентацию (вертикальное/горизонтальное)
- Корректно обрабатывает YouTube Shorts, Instagram Reels, TikTok
- Remux в MP4 для совместимости с Telegram
Пример:
# Скачать Shorts для пересылки в Telegram
result = await download_video_for_chat(
"https://youtube.com/shorts/abc123"
)
# Видео будет в правильной ориентации и оптимального размераСкачивает видео в максимальном качестве: лучшее видео (VP9/AV1) + лучшее аудио (Opus).
async def download_best_quality(
url: str,
output_dir: Path | str = None,
prefer_lang: list[str] = None,
sponsorblock: bool = True,
cookies_folder: Path | str = None,
container: Literal['mp4', 'mkv', 'webm', 'mov'] = 'mp4',
) -> DownloadResultПример:
result = await download_best_quality(
"https://youtube.com/watch?v=...",
container='mkv' # MKV поддерживает все кодеки
)Полный контроль над параметрами загрузки.
async def download_manual(
url: str,
output_dir: Path | str = None,
max_resolution: Literal['8k', '4k', '2k', '1080p', '720p', '480p', '360p', '240p', '144p'] = '4k',
audio_bitrate: Literal['best', 'medium', 'low'] = 'best',
vcodec: Literal['av1', 'vp9', 'avc', 'hevc'] = 'avc',
acodec: Literal['opus', 'aac'] = 'opus',
speech_lang: Literal['orig', 'ru', 'en'] = 'ru',
limit_fps: bool = False,
container: Literal['mp4', 'mkv', 'webm', 'mov'] = 'mp4',
sponsorblock: bool = True,
cookies_folder: Path | str = None,
) -> DownloadResultПример — видео для старого устройства:
result = await download_manual(
"https://youtube.com/watch?v=...",
max_resolution='720p',
vcodec='avc', # H.264 — максимальная совместимость
acodec='aac', # AAC — поддерживается везде
limit_fps=True, # Не более 30fps
container='mp4'
)Пример — максимальное качество для архива:
result = await download_manual(
"https://youtube.com/watch?v=...",
max_resolution='4k',
vcodec='av1', # Лучшее сжатие
acodec='opus', # Лучшее качество аудио
container='mkv', # Все кодеки без перекодирования
sponsorblock=False # Сохранить оригинал
)Для доступа к возрастным ограничениям или приватным видео и для обхода проверки на бота:
result = await download_best_audio(
"https://youtube.com/watch?v=...",
cookies_folder="./cookies" # Папка с .txt файлами в Netscape-формате
)Экспорт cookies из браузера:
- Установите расширение Cookie-Editor
- Зайдите на youtube.com под своим аккаунтом
- Кликните на иконку расширения Cookie-Editor
- Выберите "Export", затем: "Export as" -> "Netscape"
- Вставьте из буфера обмена текст в файл, например в:
./cookies/youtube.txtи сохраните - То же самое можно проделать и для x.com и т.п. если требуется, объединяя cookies с разных сайтов в один файл.
- Если разместить в папку несколько файлов с cookies от разных аккаунтов - они будут ротироваться случайным образом.
Библиотека автоматически скачивает и обновляет необходимые бинарники.
from ytdlp_simple import update_binaries_sync, update_binaries_async
# Синхронно
update_binaries_sync(force=True) # force=True — обновить даже если актуальны
# Асинхронно
await update_binaries_async(parallel=True)Запускается автоматически при импорте. Проверяет обновления каждые 24 часа.
from ytdlp_simple.bins import binaries_bg_updater
# Уже запущен, но можно остановить
binaries_bg_updater.stop()
# И запустить снова
binaries_bg_updater.start()ytdlp_simple/bin/— если директория библиотеки доступна для записи~/.local/share/ytdlp_simple/bin/(Linux) или%LOCALAPPDATA%\ytdlp_simple\bin\(Windows)- Системная временная директория (fallback)
import asyncio
from ytdlp_simple import download_best_audio
async def download_playlist(urls: list[str]):
tasks = [download_best_audio(url) for url in urls]
results = await asyncio.gather(*tasks, return_exceptions=True)
for url, result in zip(urls, results):
if isinstance(result, Exception):
print(f"❌ {url}: {result}")
elif result.success:
print(f"✅ {url}: {result.path.name}")
else:
print(f"❌ {url}: {result.error}")
urls = [
"https://youtube.com/watch?v=...",
"https://youtube.com/watch?v=...",
]
asyncio.run(download_playlist(urls))from telegram import Update
from telegram.ext import Application, CommandHandler, ContextTypes
from ytdlp_simple import download_video_for_chat
async def download_handler(update: Update, context: ContextTypes.DEFAULT_TYPE):
url = context.args[0] if context.args else None
if not url:
await update.message.reply_text("Укажите URL: /download <url>")
return
await update.message.reply_text("⏳ Загружаю...")
result = await download_video_for_chat(url)
if result.success:
await update.message.reply_video(
video=open(result.path, 'rb'),
caption=result.path.stem
)
result.path.unlink() # Удалить после отправки
else:
await update.message.reply_text(f"❌ {result.error}")from ytdlp_simple.ytdlp import get_video_formats, analyze_available_formats
async def get_available_options(url: str):
formats = await get_video_formats(url)
if formats:
analysis = analyze_available_formats(formats)
return {
"resolutions": analysis['resolutions'], # [360, 480, 720, 1080]
"orientation": analysis['orientation'], # 'horizontal' | 'vertical'
"codecs": list(analysis['vcodecs']), # ['vp9', 'avc1']
"languages": list(analysis['languages']) # ['ru', 'en']
}
return None