saveapi.org

YouTube в MP3 через API — два вызова, одна подписанная ссылка

Эндпоинта «дай мне MP3», скрывающего работу, нет, потому что файла не существует, пока он не собран. Вместо него два честных вызова: info говорит, сколько весит аудио, create собирает файл и возвращает ссылку со сроком действия. Руководство проходит оба и объясняет, что делать со ссылкой.

Обновлено

Спросите, сколько весит аудио

info отвечает массивом audio_formats[]: строка m4a с точным размером в байтах и строка mp3 с оценочным размером. Название, длительность и превью приходят вместе, так что бот может показать пользователю, что собирается отправить, до того как потратит 10 кредитов на файл.

Terminal
curl -s "https://api.saveapi.org/v1/youtube/info" \
  -H "Authorization: Bearer sk_live_xxxx" \
  -G --data-urlencode "url=https://www.youtube.com/watch?v=dQw4w9WgXcQ"

Соберите файл

Та же ссылка плюс quality=mp3 (или m4a). В ответе url, filename с названием внутри, mode "audio", file_size и expires. На нашей стороне ничего не хранится: байты производятся по мере чтения ссылки.

Terminal
curl -s "https://api.saveapi.org/v1/youtube/create" \
  -H "Authorization: Bearer sk_live_xxxx" \
  -G --data-urlencode "url=https://www.youtube.com/watch?v=aqz-KE-bpKQ" \
  --data-urlencode "quality=mp3"

Читайте ссылку правильно

Это поток, а не сохранённый файл: без Content-Length, без Range, один проход от начала до конца. После отметки expires она отвечает 410 — вызывайте create снова, а не храните ссылки. Относитесь к этому как к загрузке, которая должна произойти сейчас.

Заберите и передайте дальше

Запишите ответ потоком на диск под выданным filename, затем отправьте файл из бота или сохраните там, где нужно. Отправляйте файл, а не ссылку: Telegram сам скачивает URL со своими лимитами (20 МБ для аудио по URL), и поток без объявленного размера для этого плохо подходит.

Python
import httpx

def fetch_audio(made: dict, dest: str) -> str:
    """Pull the file behind a /v1/youtube/create link onto disk."""
    path = f"{dest}/{made['filename']}"
    with httpx.stream("GET", made["url"], timeout=None) as r, open(path, "wb") as f:
        if r.status_code == 410:            # past expires: call create again
            raise RuntimeError("link expired")
        for chunk in r.iter_bytes():        # no Content-Length: read to the end
            f.write(chunk)
    return path

# made = youtube_link(url, "mp3")          # from the yt-dlp guide
# audio = fetch_audio(made, "/tmp")
# bot.send_audio(chat_id, open(audio, "rb"), title=made["title"])

MP3 или M4A

M4A — AAC-дорожка, которую публикует YouTube: точный размер, без перекодирования, поток начинается сразу. MP3 собирается из неё через ffmpeg, поэтому стартует позже, а размер оценочный. Выбирайте M4A, если плеер на другой стороне не требует именно MP3 — Telegram играет оба.

Вопросы перед началом

Обязательно ли сначала вызывать info?
Нет. create работает сам по себе с quality=mp3 или m4a — 10 кредитов. info нужен, чтобы показать размер или название до решения, и стоит 2.
Можно ли выбрать битрейт?
Нет. На каждый формат один аудио-вариант: лучший M4A, который публикует источник, и одна кодировка MP3. Параметр quality принимает mp3 или m4a.
Что, если видео недоступно?
В ответе success: false и стабильный код из той же таблицы ошибок, что и у всех платформ. Ссылка, которую отклонил сам YouTube, стоит 0.1 кредита; сбой на нашей стороне — бесплатно, и повтор безопасен.

Платформы, использованные здесь

Другие руководства

Запустите это руководство со своим ключом

Ключ за минуту. 1 000 бесплатных кредитов, без карты и без срока.

Получить ключ и попробоватьПолный справочник API