Telegram-бот для скачивания видео на Python, aiogram и yt-dlp

Telegram-бот для скачивания видео на Python, aiogram и yt-dlp

Сегодня разберём как сделать телеграм-бота для скачивания видео и аудио по ссылке — бот будет работать с разными видеохостингами. Часто бывает, что нужно сохранить пару треков перед поездкой или собрать материалы для подкаста, а тратить деньги на сторонние сервисы не хочется. Решим задачу через две библиотеки: yt-dlp (универсальная утилита скачивания видео) и aiogram 3 (фреймворк для работы с Telegram Bot API). 

Я дам удобный шаблон для работы с AIOGram, где уже будет структурированный проект. Хотя для такого маленького проекта можно все собрать и в один файл, мы всё же оставим место для расширения нашего помощника.

Сразу обозначу, что мы не будем разжёвывать материал досконально. Но я оставлю ссылки на более подробную информацию о тех моментах, на которых сам спотыкался.

Подготовка: установка aiogram 3 и yt-dlp

Для нашего бота для скачивания видео понадобится минимум: Python 3.10+, библиотека aiogram 3 для работы с Telegram и yt-dlp для извлечения видео и аудио с различных видеохостингов.

Открываем терминал и ставим всё одной командой:

pip install aiogram yt-dlp

Если у вас несколько версий Python:

pip3 install aiogram yt-dlp

Зачем именно эти библиотеки:

  • aiogram 3 — асинхронный фреймворк для Telegram-ботов. Старая версия 2.x уже не развивается, поэтому работаем сразу на 3.
  • yt-dlp — современный стандарт скачивания видео в сообществе Python. Заменил устаревший pytube, который ломается каждые 2-3 месяца. Поддерживает десятки сервисов: YouTube, Rutube, VK Видео, TikTok, Twitter и сотни других источников.

Обязательно нужен ffmpeg — без него yt-dlp не сможет конвертировать видео в mp3. Ставится отдельно:

  • Windows: скачать с https://ffmpeg.org/download.html и добавить путь в PATH, либо choco install ffmpeg
  • macOS: brew install ffmpeg
  • Linux (Ubuntu/Debian): sudo apt install ffmpeg

После установки проверяем что всё работает:

python -c "import aiogram, yt_dlp; print(aiogram.__version__, yt_dlp.version.__version__)"
ffmpeg -version

Получение токена через BotFather

Любой телеграм бот, в том числе наш бот для скачивания видео, работает через токен от BotFather. Это официальный бот Telegram, через которого создаются и настраиваются все остальные боты.

Шаги:

  1. Открыть https://t.me/BotFather в Telegram и нажать «Start».
  2. Отправить команду /newbot.
  3. Ввести имя бота (отображается в чате, например "Мой YouTube Downloader").
  4. Ввести username — заканчивается на _bot (например my_yt_downloader_bot).
  5. Получить токен вида 1234567890:AAH...XYZ.

Этот токен — секрет. Не выкладывайте его в публичный репозиторий и не делитесь в чатах. Удобно хранить в переменной окружения или отдельном файле .env.

Структура проекта бота для скачивания видео

В отличие от старого подхода с десятком файлов и папок (handlers/users/audio.py, states/, utils/), в aiogram 3 можно начать с одного файла. Это удобнее для понимания и поддержки.

Создаём файл youtube_bot.py:

import asyncio
import os
import uuid
import yt_dlp
from aiogram import Bot, Dispatcher, F
from aiogram.client.default import DefaultBotProperties
from aiogram.enums import ParseMode
from aiogram.filters import CommandStart, Command
from aiogram.fsm.context import FSMContext
from aiogram.fsm.state import StatesGroup, State
from aiogram.fsm.storage.memory import MemoryStorage
from aiogram.types import Message, FSInputFile

TOKEN = "ВАШ_ТОКЕН_ОТ_BOTFATHER"
DOWNLOAD_DIR = "downloads"
os.makedirs(DOWNLOAD_DIR, exist_ok=True)

bot = Bot(token=TOKEN, default=DefaultBotProperties(parse_mode=ParseMode.HTML))
dp = Dispatcher(storage=MemoryStorage())


class Download(StatesGroup):
    waiting_url = State()

Что тут происходит:

  • Bot создаётся с DefaultBotProperties — в aiogram 3 параметры по умолчанию вынесли в отдельный объект.
  • Dispatcher теперь не требует передачи бота в конструктор — бот передаётся в start_polling() в самом конце.
  • MemoryStorage для FSM — хранит состояния пользователей в памяти (для прода стоит взять Redis).
  • Download.waiting_url — состояние "ждём ссылку от пользователя". Простой механизм диалога: бот спрашивает ссылку, ставит состояние, при следующем сообщении срабатывает обработчик с этим состоянием.

Скачивание видео и аудио через yt-dlp

Главная функция нашего бота для скачивания видео — скачивание. Делаем универсальную функцию которая умеет качать и аудио, и видео:

def download_audio(url: str) -> str:
    """Скачать аудиодорожку и сохранить в mp3."""
    file_id = str(uuid.uuid4().fields[-1])
    output = f"{DOWNLOAD_DIR}/{file_id}.%(ext)s"
    options = {
        "format": "bestaudio/best",
        "outtmpl": output,
        "postprocessors": [{
            "key": "FFmpegExtractAudio",
            "preferredcodec": "mp3",
            "preferredquality": "192",
        }],
        "quiet": True,
    }
    with yt_dlp.YoutubeDL(options) as ydl:
        ydl.download([url])
    return f"{DOWNLOAD_DIR}/{file_id}.mp3"


def download_video(url: str) -> str:
    """Скачать видео в mp4."""
    file_id = str(uuid.uuid4().fields[-1])
    output = f"{DOWNLOAD_DIR}/{file_id}.%(ext)s"
    options = {
        "format": "best[ext=mp4]/best",
        "outtmpl": output,
        "quiet": True,
    }
    with yt_dlp.YoutubeDL(options) as ydl:
        ydl.download([url])
    return f"{DOWNLOAD_DIR}/{file_id}.mp4"

Параметры yt-dlp которые тут используются:

  • format — что скачивать. bestaudio/best берёт лучшее аудио. best[ext=mp4]/best — лучшее видео в mp4.
  • outtmpl — шаблон имени файла. %(ext)s подставит правильное расширение в зависимости от исходника.
  • postprocessors — что делать после скачивания. FFmpegExtractAudio конвертирует в mp3.
  • quiet — не печатать прогресс в консоль (для бота не нужно).

Скачивание yt-dlp умное: если YouTube отдаёт webm — конвертирует в mp3 через ffmpeg. Если отдаёт mp4 — сразу извлекает аудио без потери качества.

Обработка команд /start, /help, /audio

Теперь добавляем команды для пользователя. В aiogram 3 декораторы стали лаконичнее:

@dp.message(CommandStart())
async def cmd_start(message: Message):
    await message.answer(
        f"Привет, {message.from_user.full_name}!\n\n"
        f"Я бот, помогу скачать видео и аудио по ссылке.\n"
        f"Команды:\n"
        f"/audio — скачать аудио с YouTube\n"
        f"/video — скачать видео с YouTube\n"
        f"/help — справка"
    )


@dp.message(Command("help"))
async def cmd_help(message: Message):
    await message.answer(
        "Использование:\n"
        "1. Отправь /audio или /video\n"
        "2. Пришли ссылку на YouTube\n"
        "3. Получи файл\n\n"
        "Поддерживаются также Rutube, VK Видео, TikTok."
    )


@dp.message(Command("audio"))
async def cmd_audio(message: Message, state: FSMContext):
    await state.update_data(media_type="audio")
    await message.answer("Пришли ссылку на видео — извлеку аудио.")
    await state.set_state(Download.waiting_url)


@dp.message(Command("video"))
async def cmd_video(message: Message, state: FSMContext):
    await state.update_data(media_type="video")
    await message.answer("Пришли ссылку на видео — скачаю в mp4.")
    await state.set_state(Download.waiting_url)


@dp.message(Download.waiting_url, F.text)
async def process_url(message: Message, state: FSMContext):
    data = await state.get_data()
    media_type = data.get("media_type", "audio")

    await message.answer("Качаю, подожди...")
    try:
        if media_type == "audio":
            path = download_audio(message.text)
        else:
            path = download_video(message.text)
        await bot.send_document(message.chat.id, FSInputFile(path))
        os.remove(path)
    except Exception as e:
        await message.answer(f"Ошибка: {e}")
    await state.clear()

Что важно знать:

  • CommandStart() и Command("audio") — фильтры из aiogram.filters, в aiogram 2.x они жили в aiogram.dispatcher.filters.builtin.
  • F.text — магический фильтр на наличие текста в сообщении (в 2.x использовали content_types=["text"]).
  • state.set_state / state.clear / state.update_data — методы FSM, заметно проще чем в 2.x.
  • FSInputFile(path) — обёртка для отправки файла с диска. В 2.x открывали через open(path, "rb").

Финальный код: бот скачать видео и аудио

Собираем всё вместе. Один файл youtube_bot.py:

import asyncio
import os
import uuid
import yt_dlp
from aiogram import Bot, Dispatcher, F
from aiogram.client.default import DefaultBotProperties
from aiogram.enums import ParseMode
from aiogram.filters import CommandStart, Command
from aiogram.fsm.context import FSMContext
from aiogram.fsm.state import StatesGroup, State
from aiogram.fsm.storage.memory import MemoryStorage
from aiogram.types import Message, FSInputFile

TOKEN = "ВАШ_ТОКЕН_ОТ_BOTFATHER"
DOWNLOAD_DIR = "downloads"
os.makedirs(DOWNLOAD_DIR, exist_ok=True)

bot = Bot(token=TOKEN, default=DefaultBotProperties(parse_mode=ParseMode.HTML))
dp = Dispatcher(storage=MemoryStorage())


class Download(StatesGroup):
    waiting_url = State()


def download_audio(url: str) -> str:
    file_id = str(uuid.uuid4().fields[-1])
    output = f"{DOWNLOAD_DIR}/{file_id}.%(ext)s"
    options = {
        "format": "bestaudio/best",
        "outtmpl": output,
        "postprocessors": [{
            "key": "FFmpegExtractAudio",
            "preferredcodec": "mp3",
            "preferredquality": "192",
        }],
        "quiet": True,
    }
    with yt_dlp.YoutubeDL(options) as ydl:
        ydl.download([url])
    return f"{DOWNLOAD_DIR}/{file_id}.mp3"


def download_video(url: str) -> str:
    file_id = str(uuid.uuid4().fields[-1])
    output = f"{DOWNLOAD_DIR}/{file_id}.%(ext)s"
    options = {
        "format": "best[ext=mp4]/best",
        "outtmpl": output,
        "quiet": True,
    }
    with yt_dlp.YoutubeDL(options) as ydl:
        ydl.download([url])
    return f"{DOWNLOAD_DIR}/{file_id}.mp4"


@dp.message(CommandStart())
async def cmd_start(message: Message):
    await message.answer(
        f"Привет, {message.from_user.full_name}!\n"
        f"Команды: /audio, /video, /help"
    )


@dp.message(Command("help"))
async def cmd_help(message: Message):
    await message.answer("Отправь /audio или /video, потом ссылку.")


@dp.message(Command("audio"))
async def cmd_audio(message: Message, state: FSMContext):
    await state.update_data(media_type="audio")
    await message.answer("Пришли ссылку.")
    await state.set_state(Download.waiting_url)


@dp.message(Command("video"))
async def cmd_video(message: Message, state: FSMContext):
    await state.update_data(media_type="video")
    await message.answer("Пришли ссылку.")
    await state.set_state(Download.waiting_url)


@dp.message(Download.waiting_url, F.text)
async def process_url(message: Message, state: FSMContext):
    data = await state.get_data()
    await message.answer("Качаю...")
    try:
        if data.get("media_type") == "audio":
            path = download_audio(message.text)
        else:
            path = download_video(message.text)
        await bot.send_document(message.chat.id, FSInputFile(path))
        os.remove(path)
    except Exception as e:
        await message.answer(f"Ошибка: {e}")
    await state.clear()


async def main():
    await dp.start_polling(bot)


if __name__ == "__main__":
    asyncio.run(main())

Запускаем:

python youtube_bot.py

Бот стартует, заходим в Telegram, пишем /audio, кидаем ссылку — через несколько секунд получаем mp3.

Лимит 50 МБ: как обойти

Если попробуете скачать длинное видео или высокое качество — словите ошибку отправки. Telegram Bot API ограничивает размер файлов:

  • 50 МБ — для отправки документа, аудио, видео через стандартный bot.send_*
  • 20 МБ — для скачивания файлов ботом
  • 2 ГБ — через self-hosted Local Bot API Server

Три способа обойти ограничение:

  1. Local Bot API Server (правильный путь).

Telegram предоставляет официальный сервер для self-hosted развёртывания. Запускается локально, лимит вырастает до 2 ГБ:

docker run -d --restart=always \
  -e TELEGRAM_API_ID=ваш_api_id \
  -e TELEGRAM_API_HASH=ваш_api_hash \
  -p 8081:8081 \
  aiogram/telegram-bot-api:latest

api_id и api_hash берутся на https://my.telegram.org. В коде указываем base URL:

from aiogram.client.session.aiohttp import AiohttpSession
from aiogram.client.telegram import TelegramAPIServer

session = AiohttpSession(api=TelegramAPIServer.from_base("http://localhost:8081"))
bot = Bot(token=TOKEN, session=session)

Понизить качество. Для аудио хватает 128 kbps, для видео — формат 480p или ниже. Почти всегда укладываемся в 50 МБ.

Резать на части через ffmpeg. Для аудио (подкасты, лекции) — нормально. Для видео выглядит костыльно.

Большинство публичных ютуб ботов работают через Local Bot API Server. Для личного использования хватает понижения качества.

Поддержка других видеохостингов

Главный плюс yt-dlp — он работает не только с YouTube. Поддерживает сотни источников: Rutube, VK Видео, Дзен, TikTok, Twitter и многие другие. Самое удобное, что код скачивания при этом не меняется — просто добавляем список поддерживаемых доменов:

SUPPORTED_DOMAINS = [
    "youtube.com", "youtu.be",
    "rutube.ru", "vk.com",
    "tiktok.com", "dzen.ru",
]

yt-dlp сам определит источник по ссылке и выберет подходящий экстрактор. Бот скачивает видео и аудио одной функцией независимо от платформы. Это удобно ещё и тем, что аудитория расширяется на пользователей разных видеохостингов.

Деплой бота для скачивания видео на сервер

Локально бот работает пока включён компьютер. Для постоянной работы нужен сервер. Два проверенных варианта:

systemd на VPS. Покупаем VPS, кидаем туда youtube_bot.py, создаём systemd-юнит:

[Unit]
Description=YouTube Telegram bot
After=network.target

[Service]
WorkingDirectory=/opt/youtube_bot
ExecStart=/usr/bin/python3 /opt/youtube_bot/youtube_bot.py
Restart=always
User=botuser

[Install]
WantedBy=multi-user.target

Сохраняем как /etc/systemd/system/youtube_bot.service, запускаем:

sudo systemctl enable --now youtube_bot

Бот автоматически перезапускается при падении и при ребуте сервера.

Docker. Удобно если несколько ботов или нужна изоляция:

FROM python:3.11-slim
RUN apt-get update && apt-get install -y ffmpeg && rm -rf /var/lib/apt/lists/*
WORKDIR /app
RUN pip install --no-cache-dir aiogram yt-dlp
COPY youtube_bot.py .
CMD ["python", "youtube_bot.py"]

Сборка и запуск:

docker build -t youtube_bot .
docker run -d --restart=always youtube_bot

ffmpeg ставим внутрь контейнера — без него yt-dlp не сможет извлекать аудио. Размер итогового образа около 200-300 МБ.

Хостинг. Для маленького бота для скачивания видео хватит обычного VDS — например, на Hostland подходящий тариф стоит 300-400 рублей в месяц. Это базовая Linux-машина с Python и ffmpeg на борту, достаточная и для домашнего и для небольшого публичного бота.

Авторские права при скачивании видео

Юридический момент о котором забывают. YouTube ToS прямо запрещает скачивание видео без согласия правообладателя (пункт 4.D Соглашения). Если хочется сделать публичный телеграм-бот для скачивания видео для тысяч пользователей — это серая зона.

Что обычно делают:

  • Личный бот для себя — никаких претензий. YouTube не отслеживает индивидуальное использование.
  • Бот для семьи/команды до 20 человек — формально нарушение, на практике никто не замечает.
  • Публичный бот с большим трафиком — рискованно. Telegram могут заблокировать по жалобе от YouTube, аккаунт владельца забанить.
  • Бот для собственного контента — никаких проблем. Например, скачивание своих видео.

Лучшие практики для публичных проектов:

  1. Дисклеймер в /start что бот для личного использования.
  2. Не сохранять контент на сервере дольше 1 минуты (удалять после отправки — в нашем коде уже есть os.remove(path)).
  3. Не хранить базу скачанных видео.
  4. Не предлагать массовое скачивание фильмов и музыки.

Для аудио (подкасты, лекции, разговорные ролики) ситуация проще — редко защищённый контент. Для музыки и фильмов — большие риски.

FAQ: бот для скачивания видео

Какую версию aiogram использовать?

В 2026 году актуален aiogram 3.x. Версия 2.x ещё работает на старых проектах, но новые туториалы и фичи выходят на 3-ке. Если начинаете с нуля — берите 3.

pytube или yt-dlp?

yt-dlp. pytube постоянно ломается из-за изменений YouTube, фиксы выходят медленно. yt-dlp поддерживается активно, работает с сотнями источников (YouTube, TikTok, Rutube, VK), не только с ютубом. Минус — требует установленного ffmpeg.

Как обойти лимит 50 МБ?

Поднять Local Bot API Server (лимит вырастает до 2 ГБ). Или скачивать в худшем качестве для аудио — 128 kbps хватает. Третий вариант — резать большие файлы на куски через ffmpeg.

Бесплатно ли работает yt-dlp?

Да, yt-dlp — open-source под лицензией Unlicense. Без подписок. Единственная статья расходов — хостинг бота.

Можно ли законно скачивать с YouTube?

Формально YouTube ToS это запрещает. На практике для личного использования никто претензий не предъявляет. Для публичных ботов — дисклеймер и не сохранять контент.

Сколько стоит запустить телеграм-бота для скачивания видео?

Сам Telegram Bot API бесплатный, библиотеки aiogram и yt-dlp тоже. Платить нужно только за хостинг — простого VDS на 300-400 рублей в месяц (например, Hostland) хватит и для домашнего, и для небольшого публичного проекта.

Как сделать бот скачать видео на Python — какие библиотеки нужны?

Связка aiogram 3 + yt-dlp в Python — самый ходовой вариант. Если гуглите «как сделать бот скачать видео на Python» — почти все примеры в выдаче будут именно про эту связку. aiogram отвечает за Telegram API, yt-dlp — за работу с источниками. Никаких сторонних SDK не нужно, всё ставится через pip. Если нужна альтернатива aiogram — есть telebot и python-telegram-bot, но синтаксис менее удобный.

Какие альтернативы pytube кроме yt-dlp?

pytubefix — форк pytube с регулярными фиксами, миграция в одну строку (заменить импорт). youtube-dl — родительский проект yt-dlp, обновляется медленнее.

Python + Telegram + AIOgram - что в итоге?

Итак, мы успешно собрали Telegram-бота, который скачивает аудиодорожку из YouTube и присылает её нам в Telegram. Это может быть очень удобным если мы не хотим или не можем оплатить YouTube Premium;)

Почему мы использовали именно AIOGram? Он имеет обширный функционал и может работать асинхронно со всеми пользователями, чего трудно добиться в pyTelegramBotAPI. 

Помимо этого, мы можем модерировать телеграм каналы и принимать команды, делить пользователей на администраторов, модераторов и других. Всё это даёт поистине огромные возможности для автоматизации различных задач с помощью Telegram.

Я люблю python за простоту использования - он как конструктор LEGO для взрослых. Вам не требуется все время следить за скобками как в C-подобных языках. Вам не надо разбираться в низкоуровневом программировании. Вы можете просто писать код и получать удовольствие от процесса и результата;)

Полезные ссылки:

Справка AIOGram - https://docs.aiogram.dev/en/latest/install.html

Библиотека PyTube - https://pytube.io/en/latest/

Библиотека Uuid - https://docs.python.org/3/library/uuid.html

Библиотека OS - https://docs.python.org/3/library/os.html

Проект из статьи - https://github.com/Redkomel56/PyTube_telegram