सामग्री पर जाएँ

Python से yt-dlp: embedded API, options, hooks और सर्वर में चलाना

लेखक Tunelio टीमप्रकाशित

yt-dlp एक Python package है, तो shell से बुलाने की जगह इसे import कर सकते हैं: yt_dlp.YoutubeDL(opts).extract_info(url) metadata देता है और चाहें तो file भी। यह गाइड options dict, बिना download के format पाना, progress hooks, error handling, async web server को responsive रखना, और ज़रूरी Docker image cover करती है — साथ ही यह कि दूसरों के लिए चलाने पर प्रति वीडियो CPU लागत क्या है।

Install

python3 -m pip install -U "yt-dlp[default]"
# साथ में मशीन पर ffmpeg (merge / audio) और Deno जैसा JS runtime (YouTube challenge)

न्यूनतम download

import yt_dlp

opts = {
    "format": "bv*+ba/b",              # best video + best audio, merged (ffmpeg चाहिए)
    "merge_output_format": "mp4",
    "outtmpl": "downloads/%(title)s.%(ext)s",
    "noplaylist": True,
    "quiet": True,
}
with yt_dlp.YoutubeDL(opts) as ydl:
    ydl.download(["https://youtu.be/dQw4w9WgXcQ"])

हर command-line flag की एक dictionary key है; mapping yt_dlp/YoutubeDL.py (class docstring) और yt_dlp/options.py में documented है। संदेह हो तो CLI को चाहे गए flags और --print-json के साथ चलाएँ, फिर option नाम copy करें।

बिना download के metadata और format

import yt_dlp

with yt_dlp.YoutubeDL({"quiet": True, "skip_download": True}) as ydl:
    info = ydl.extract_info("https://youtu.be/dQw4w9WgXcQ", download=False)

print(info["title"], info["duration"])
for f in info["formats"]:
    if f.get("vcodec") != "none" and f.get("acodec") != "none":     # progressive (एक file में video+audio)
        print(f["format_id"], f.get("height"), f.get("ext"), f.get("filesize_approx"))
best_audio = max((f for f in info["formats"] if f.get("vcodec") == "none"), key=lambda f: f.get("abr") or 0)
print("audio:", best_audio["format_id"], best_audio["url"][:60], "...")

extract_info वही JSON लौटाता है जो CLI -j से छापता है: सीधे googlevideo URL वाले format, thumbnail, subtitles, chapter। ये URL उसी IP और client के लिए signed हैं जिसने माँगा और लगभग छह घंटे में expire हो जाते हैं — इन्हें उसी मशीन पर ffmpeg या downloader को दें, अपने users को नहीं।

Progress hooks और logging

def on_progress(d):
    if d["status"] == "downloading":
        print(d.get("_percent_str"), d.get("_speed_str"), end="\r")
    elif d["status"] == "finished":
        print("\nहो गया, post-processing:", d["filename"])

class QuietLogger:
    def debug(self, msg): pass
    def warning(self, msg): print("WARN", msg)
    def error(self, msg): print("ERR", msg)

opts = {"progress_hooks": [on_progress], "logger": QuietLogger(), "format": "bv*+ba/b"}

Error handling

from yt_dlp.utils import DownloadError, ExtractorError

try:
    with yt_dlp.YoutubeDL(opts) as ydl:
        info = ydl.extract_info(url, download=False)
except DownloadError as e:
    msg = str(e)
    if "Sign in to confirm" in msg:      # bot wall → IP/cookies/PO token, bot-check गाइड देखें
        ...
    elif "HTTP Error 403" in msg:       # 403 गाइड देखें
        ...
    elif "Private video" in msg or "Video unavailable" in msg:
        ...
    raise

yt-dlp लगभग सब कुछ DownloadError में लपेटता है जिसके अंदर मूल संदेश होता है; message text पर match करें। playlist के लिए "ignoreerrors": True रखें ताकि एक मृत item पूरा run न रोके (ऐसे entries None लौटते हैं)।

Cookies, proxy और अन्य production options

opts = {
    "cookiefile": "/secrets/cookies.txt",           # Netscape format; सिर्फ़ spare account
    "proxy": "socks5h://user:pass@exit.example:1080",
    "source_address": "0.0.0.0",                    # IPv4 force (-4 flag)
    "extractor_args": {"youtube": {"player_client": ["tv", "web"]}},
    "sleep_interval_requests": 1,
    "retries": 3,
    "socket_timeout": 30,
}

command line जैसे ही नियम लागू हैं: spare account की private window से cookies, datacenter की जगह residential exit, IPv6 range साफ़ होने का यक़ीन न हो तो IPv4। cookies, proxy और 403 गाइड हर एक को समझाती हैं।

async server के अंदर (FastAPI, aiohttp, Telegram bot)

import asyncio
from fastapi import FastAPI

app = FastAPI()
_sem = asyncio.Semaphore(4)   # concurrent extraction सीमित करें — हर एक ≈ 1 s CPU

def _extract(url: str) -> dict:
    with yt_dlp.YoutubeDL({"quiet": True, "skip_download": True}) as ydl:
        return ydl.extract_info(url, download=False)

@app.get("/info")
async def info(url: str):
    async with _sem:
        data = await asyncio.to_thread(_extract, url)   # event loop पर yt-dlp कभी न बुलाएँ
    return {"title": data["title"], "duration": data["duration"]}

yt-dlp synchronous और CPU-heavy है: हमारे सर्वर पर एक YouTube extraction लगभग 1.2–1.3 सेकंड CPU लेता है, ज़्यादातर player JavaScript चलाने में। async handler में सीधे बुलाने पर यह बाकी हर request को जमा देता है; इसे thread या process pool में चलाएँ और concurrency सीमित करें, वरना सेवा कुछ request प्रति सेकंड पर ही गिर जाएगी।

Docker

FROM python:3.12-slim
RUN apt-get update && apt-get install -y --no-install-recommends ffmpeg curl unzip ca-certificates \
 && rm -rf /var/lib/apt/lists/* \
 && curl -fsSL https://deno.land/install.sh | DENO_INSTALL=/usr/local sh
RUN pip install --no-cache-dir "yt-dlp[default]" fastapi uvicorn
COPY app.py /app/app.py
USER 1000
CMD ["uvicorn", "app:app", "--host", "0.0.0.0", "--port", "8000", "--app-dir", "/app"]

तीन runtime dependencies: yt-dlp, ffmpeg और JavaScript runtime। image कम से कम मासिक rebuild करें (update गाइड देखें) — तीन महीने पुराने yt-dlp वाला container ज़्यादातर वीडियो पर fail होगा। अपनी cache directory वाले non-root user से चलाएँ।

बड़े पैमाने पर लागत और भरोसेमंदी

  • CPU: आधुनिक core पर प्रति extraction ~1.2–1.3 s, हर request पर (player JS फिर से evaluate होता है)। दस request प्रति सेकंड के लिए सिर्फ़ yt-dlp को दर्जन भर core चाहिए।
  • IP reputation: एक पते से रोज़ सैकड़ों वीडियो निकालने वाला सर्वर bot wall से टकराएगा; अंत में आप proxy और PO-token service चलाते हैं।
  • टूटना: YouTube का हर बदलाव एक redeploy है; क्यों, update गाइड बताती है।
  • Bandwidth: users को relay किया media आपके सर्वर से दो बार गुज़रता है।

hosted API इसीलिए मौजूद हैं। Tunelio (हमारी अपनी सेवा) extraction करता है और हर request पर download URL लौटाता है, तो आपका Python एक HTTP call रहता है और container में न ffmpeg, न runtime, न proxy। laptop पर script के लिए ऊपर का embedded API सही औज़ार है। नए account को 100 free credits।

स्रोत

  • yt-dlp README — “Embedding yt-dlp” section और yt_dlp/YoutubeDL.py में options reference।
  • yt-dlp wiki — Extractor args (player_client) और PO token guide।
  • हमारे अपने माप (Tunelio extraction fleet, 2026): प्रति extraction CPU, datacenter IP पर bot-wall दर।

सामान्य सवाल

yt-dlp CLI को subprocess से बुलाऊँ या import करूँ?

import साफ़ है और structured data देता है; subprocess crash और memory को अलग रखता है। दोनों में event loop से बाहर चलाएँ और concurrency सीमित करें।

क्या बिना download के सीधा video URL मिल सकता है?

हाँ: extract_info(url, download=False) हर format उसके URL के साथ लौटाता है। ये आपके IP/client से बंधे हैं और लगभग छह घंटे में expire होते हैं, इसलिए सर्वर-साइड तुरंत इस्तेमाल करें।

yt-dlp चलते समय मेरा FastAPI app क्यों जम जाता है?

yt-dlp blocking और CPU-heavy है। इसे asyncio.to_thread (या process pool) में लपेटें और semaphore से समानांतर extraction सीमित करें।

कौन-सी option key किस flag से मेल खाती है?

ज़्यादातर flag snake_case key बनते हैं (--merge-output-format → merge_output_format)। आधिकारिक सूची yt_dlp/YoutubeDL.py में YoutubeDL class का docstring है।

संबंधित गाइड