Skip to main content

fm-dlp-core — Core Library for YouTube & 1000+ Sites

Python PyPI License Platform Ruff

fm-dlp-core is a powerful Python library for searching and downloading content from YouTube, YouTube Music, and over 1000+ supported sites. Built on top of yt-dlp, it provides a clean, async-first API with rich features including concurrent downloads, metadata embedding, and flexible output formatting.


✨ Key Features

Feature Description
🎵 Audio Extraction Extract audio in 8 formats: MP3, AAC, FLAC, M4A, Opus, Vorbis, WAV, ALAC
🎬 Video Download Download videos in MP4, MKV, WebM, MOV, AVI, FLV with quality selection
🔍 Search Search YouTube videos and YouTube Music tracks/albums with formatted output
Concurrent Downloads Download multiple files in parallel with configurable job limits
🏷️ Metadata Embedding Automatically embed tags and thumbnails into audio files
🔐 Authentication Support for cookies (file or browser) to access restricted content
💾 Persistent Config Save and load download preferences across sessions
🎨 Colored Output Beautiful terminal output with ANSI colors (toggleable)
🔌 Extensible Create custom search providers for any platform

📋 Table of Contents


🚀 Quick Start

import asyncio
from fm_dlp_core import search, run_downloader

# 1. Search for a track
for result in search("Sewerslvt", limit=3, yt_video=False, album=False):
    print(result)

# 2. Download a track
asyncio.run(
    run_downloader(
        url="https://music.youtube.com/watch?v=y55fzyXZDSE",
        codec="mp3",
        kbps=320,
        path="./music",
        metadata=True,
        color=True,
    )
)

📦 Installation

pip install fm-dlp-core

For development:

git clone https://github.com/Fkernel653/fm-dlp-core
cd fm-dlp-core
pip install -e .

⚙️ Requirements

Python Version

  • Python 3.11+ — Required for tomllib, asyncio and type hint features

FFmpeg (Required)

FFmpeg is essential for audio/video processing, conversion, and metadata embedding.

Platform Installation Command
macOS brew install ffmpeg
Debian/Ubuntu sudo apt install ffmpeg
Fedora sudo dnf install ffmpeg
Windows Download from ffmpeg.org and add to PATH

🧠 Core Concepts

Async-First Design

All download operations are asynchronous, allowing you to run multiple downloads concurrently without blocking your application.

Configuration Persistence

Settings like codec, bitrate, quality, and download path can be saved to a TOML file and reused across sessions.

Provider Pattern

Search functionality is built on a provider pattern, making it easy to add support for new platforms by subclassing BaseProvider.


🎵 Downloading Content

Basic Usage

import asyncio
from fm_dlp_core import run_downloader

asyncio.run(
    run_downloader(
        url="https://youtube.com/watch?v=VIDEO_ID",
        codec="mp3",
        kbps=192,
        path="./downloads",
    )
)

Advanced Usage with Context Manager

from fm_dlp_core import Download

async def download_video():
    async with Download(
        url="https://youtube.com/watch?v=VIDEO_ID",
        codec="mp4",
        quality="1080p",
        jobs=4,
        path="./videos",
        metadata=True,
        only_video=True,
        color=True,
    ) as downloader:
        await downloader.download_all()

Batch Downloads

# Multiple URLs (comma or space separated)
async with Download(
    url="url1,url2,url3",  # or "url1 url2 url3"
    codec="flac",
    kbps=0,  # Lossless
    jobs=3,
) as downloader:
    await downloader.download_all()

# URLs from a text file (one per line)
async with Download(
    url="urls.txt",
    codec="m4a",
    kbps=256,
) as downloader:
    await downloader.download_all()

Supported Codecs

Type Formats
Audio mp3, aac, flac, m4a, opus, vorbis, wav, alac
Video mp4, mov, mkv, webm, avi, flv

Download Parameters

Parameter Type Description Default
url str URL(s) to download (comma/space separated or path to file) Required
codec str Output format (see Supported Codecs) "m4a" (macOS) / "opus" (others)
kbps int Audio bitrate in kbps 192
quality str Video quality (best, worst, 1080p, 720p, etc.) "best"
jobs int Number of concurrent downloads 4
quiet bool Suppress output messages False
metadata bool Embed metadata and thumbnail True
keep bool Keep original downloaded file False
save bool Save parameters to config False
use_config bool Load parameters from config False
path str Download directory Current directory
only_video bool Download video only (skip audio extraction) False
cookies str | None Cookies file path or browser name None
color bool Enable colored output True

🔍 Searching Content

YouTube Music Search

Search for tracks and albums on YouTube Music:

from fm_dlp_core import search

# Search for tracks
for result in search(
    query="Sewerslvt",
    limit=5,
    yt_video=False,   # Use YouTube Music
    album=False,      # Search for tracks
    color=True,
):
    print(result)

# Search for albums
for result in search(
    query="Draining Love Story",
    limit=3,
    yt_video=False,
    album=True,       # Search for albums
):
    print(result)

YouTube Video Search

Search for videos on YouTube:

# Search YouTube videos
for result in search(
    query="Python tutorial",
    limit=5,
    yt_video=True,    # Use YouTube (videos)
    album=False,
):
    print(result)

Output Modes

Mode Parameter Description
Formatted raw=False, only_url=False Beautiful colored output with metadata
URL-Only only_url=True Just the URLs (great for piping)
Raw Data raw=True Python dictionaries with full metadata
# Get only URLs
urls = list(search("breakcore", limit=10, only_url=True))

# Get raw data
for data in search("Goreshit", limit=2, raw=True):
    print(data["title"], data["url"])

# Chain search → download
urls = list(search("chill beats", limit=5, only_url=True))
if urls:
    asyncio.run(run_downloader(url=" ".join(urls), codec="mp3", kbps=320))

Search Parameters

Parameter Type Description
query str Search query string
limit int Maximum number of results (1-100)
yt_video bool True = YouTube videos, False = YouTube Music
album bool True = search albums, False = search tracks
raw bool Output raw Python dicts
only_url bool Output only URLs
color bool Enable colored output

⚙️ Configuration

Persistent Download Parameters

Save your preferred settings to reuse them later:

from fm_dlp_core.utils.config.parametrs import set_parameters, get_parameters

# Save parameters
set_parameters(
    codec="mp3",
    kbps=256,
    quality="720p",
    jobs=4,
    quiet=False,
    metadata=True,
    keep=False,
    only_video=False,
    cookies="chrome",  # Use browser cookies
    color=True,
)

# Load saved parameters
params = get_parameters()
print(params)  # {'codec': 'mp3', 'kbps': 256, ...}

Download Path

Set and get the default download directory:

from fm_dlp_core.utils.config.path import set_path, get_path

# Set download path
result = set_path("/my/download/folder")
print(result)  # "Configuration saved successfully"

# Get current path
path = get_path()
print(f"Downloads will be saved to: {path}")

Configuration File Location

Platform Path
Windows %LOCALAPPDATA%\fm-dlp\config.toml
macOS ~/Library/Application Support/fm-dlp/config.toml
Linux ~/.config/fm-dlp/config.toml

Configuration Structure

without cookies:

path = "/home/user/folder"

[parameters]
codec = "opus"
kbps = 256
quality = "best"
jobs = 5
quiet = false
metadata = true
keep = false
only_video = false

with cookies:

path = "/home/user/folder"

[parameters]
codec = "opus"
kbps = 256
quality = "best"
jobs = 5
quiet = false
metadata = true
keep = false
only_video = false
cookies = "firefox"

🔧 Advanced Topics

Custom Search Providers

Create your own search provider by subclassing BaseProvider:

from fm_dlp_core.commands.search.providers import BaseProvider

class SoundCloudProvider(BaseProvider):
    def _extract_results(self, query: str, limit: int, is_track: bool) -> list:
        # Implement your search logic
        # Return list of entries (dicts)
        return results

    def _extract_url(self, entry: dict, is_track: bool) -> str | None:
        return entry.get("permalink_url")

    def _fmt_entry(self, entry: dict, num: int, is_track: bool) -> str | None:
        return self.formatter.fmt_result(
            num=num,
            title=entry.get("title", "Unknown"),
            artist=entry.get("user", {}).get("username", "Unknown"),
            url=self._extract_url(entry, is_track),
            is_yt_video=False,
            is_track=is_track,
        )

    def _get_empty_message(self, query: str, is_track: bool) -> str:
        return f"No results found for '{query}'\n"

# Use your provider
provider = SoundCloudProvider(color=True, error_prefix="Error: ")
for result in provider.search(query="lo-fi", limit=5, is_track=True):
    print(result)

Building Custom yt-dlp Options

For advanced use cases, you can build custom yt-dlp options:

from fm_dlp_core.commands.downloader.options_builder import OptionsBuilder

builder = OptionsBuilder(
    codec="mp3",
    kbps=320,
    quality="best",
    jobs=4,
    quiet=False,
    metadata=True,
    keep=False,
    only_video=False,
    cookies="firefox",
    path="./downloads",
    color=True,
)

opts = builder.build()
# Add custom options
opts["extractor_args"] = {"youtube": {"skip": ["hls"]}}

# Use with yt-dlp directly
from yt_dlp import YoutubeDL
with YoutubeDL(opts) as ydl:
    ydl.download(["https://youtube.com/watch?v=..."])

Cookie Authentication

For private or age-restricted content:

# Using browser cookies
asyncio.run(
    run_downloader(
        url="https://youtube.com/watch?v=...",
        codec="mp3",
        cookies="chrome",  # or "firefox", "edge", "opera"
        path="./downloads",
    )
)

# Using cookies file
asyncio.run(
    run_downloader(
        url="https://youtube.com/watch?v=...",
        codec="mp3",
        cookies="./cookies.txt",
        path="./downloads",
    )
)

📚 API Reference

Core Package

Module Description
fm_dlp_core Main package with Download, Search, and utilities
fm_dlp_core.commands.downloader Download functionality with Download and run_downloader
fm_dlp_core.commands.search Search functionality with Search and search
fm_dlp_core.utils Shared utilities (colors, constants, config)
fm_dlp_core.utils.config Configuration management (paths, parameters)
fm_dlp_core.utils.colors Terminal color utilities

Key Classes

Class Module Description
Download commands.downloader Async downloader with context manager
DownloadConfig commands.downloader.config Configuration container
OptionsBuilder commands.downloader.options_builder yt-dlp options builder
URLParser commands.downloader.url_parser Parse URLs from string/file
Search commands.search Main search handler
ResultFormatter commands.search.formatters Format search results
BaseProvider commands.search.providers Abstract provider base
YouTubeProvider commands.search.providers YouTube video search
YouTubeMusicProvider commands.search.providers YouTube Music search

Key Functions

Function Module Description
run_downloader commands.downloader Async download entry point
search commands.search Convenience search function
set_parameters utils.config.parametrs Save download parameters
get_parameters utils.config.parametrs Load download parameters
set_path utils.config.path Set download directory
get_path utils.config.path Get download directory
echo utils Print with color support
success/error/info/hint utils.colors Formatted colored messages

💡 Examples

Example 1: Download a Music Playlist

import asyncio
from fm_dlp_core import search, run_downloader

async def download_playlist(playlist_url: str):
    await run_downloader(
        url=playlist_url,
        codec="flac",
        kbps=0,  # Lossless
        jobs=4,
        metadata=True,
        path="./music",
        color=True,
    )

asyncio.run(download_playlist("https://music.youtube.com/playlist?list=..."))

Example 2: Search and Download Top Tracks

import asyncio
from fm_dlp_core import search, run_downloader

def get_top_tracks(artist: str, limit: int = 5) -> list[str]:
    return list(search(artist, limit=limit, yt_video=False, only_url=True))

async def download_artist(artist: str):
    urls = get_top_tracks(artist, limit=3)
    if urls:
        await run_downloader(
            url=" ".join(urls),
            codec="mp3",
            kbps=320,
            metadata=True,
            path=f"./music/{artist}",
        )

asyncio.run(download_artist("Porter Robinson"))

Example 3: Custom Download with Progress Callback

import asyncio
from fm_dlp_core import Download

class MyDownloader(Download):
    def _sync_download(self, url: str):
        # Override to add custom behavior
        print(f"Downloading: {url}")
        super()._sync_download(url)

async def main():
    async with MyDownloader(
        url="https://youtube.com/watch?v=...",
        codec="mp4",
        quality="1080p",
        path="./videos",
    ) as downloader:
        await downloader.download_all()

Example 4: Working with Raw Search Data

from fm_dlp_core import search

# Get raw data for programmatic use
for result in search(
    query="Daft Punk",
    limit=10,
    yt_video=False,
    album=False,
    raw=True,  # Returns dicts
):
    print(f"Title: {result['title']}")
    print(f"Artist: {result.get('artists', [{}])[0].get('name', 'Unknown')}")
    print(f"Duration: {result.get('duration')}s")
    print(f"URL: https://music.youtube.com/watch?v={result.get('videoId')}")
    print("-" * 40)

Example 5: Error Handling

import asyncio
from fm_dlp_core import run_downloader

async def safe_download(url: str):
    try:
        await run_downloader(
            url=url,
            codec="mp3",
            kbps=192,
            path="./downloads",
        )
    except Exception as e:
        print(f"Download failed for {url}: {e}")

asyncio.run(safe_download("https://youtube.com/watch?v=invalid_id"))

🖥️ Output Formatting

Search Results Format

    1. Mr. Kill Myself
        ├─ Sewerslvt
        ├─ Draining Love Story
        ├─ 13,456,789 │ 7:52
        └─ https://music.youtube.com/watch?v=y55fzyXZDSE
           ──────────────────────────────────────────────────

Format Elements

Element Description
N. Sequential result number
Title Track, album, or video title
Artist Artist or channel name
├─└─│ Tree structure for visual hierarchy
Views │ Duration View count and length
URL Direct link to content

Colored Output Functions

from fm_dlp_core.utils.colors import success, error, info, hint

print(success("Download completed!"))
print(error("Failed to process video"))
print(info("Extracting metadata..."))
print(hint("Try using a higher bitrate for better quality"))

📄 License

This project is licensed under the AGPLv3 License — see the LICENSE file for details.

Acknowledgments

Library Purpose
yt-dlp Download engine supporting 1000+ sites
ytmusicapi YouTube Music search API
mutagen Metadata tagging for audio files

Author: Fkernel653
Project: GitHubPyPI
Documentation: fm-dlp-core Docs


If you encounter any issues, please open an issue on GitHub.

Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

fm_dlp_core-0.1.6.tar.gz (55.4 kB view details)

Uploaded Source

Built Distribution

If you're not sure about the file name format, learn more about wheel file names.

fm_dlp_core-0.1.6-py3-none-any.whl (44.4 kB view details)

Uploaded Python 3

File details

Details for the file fm_dlp_core-0.1.6.tar.gz.

File metadata

  • Download URL: fm_dlp_core-0.1.6.tar.gz
  • Upload date:
  • Size: 55.4 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? No
  • Uploaded via: uv/0.12.5 {"installer":{"name":"uv","version":"0.12.5","subcommand":["publish"]},"python":null,"implementation":{"name":null,"version":null},"distro":{"name":"Ubuntu","version":"24.04","id":"noble","libc":null},"system":{"name":null,"release":null},"cpu":null,"openssl_version":null,"setuptools_version":null,"rustc_version":null,"ci":true}

File hashes

Hashes for fm_dlp_core-0.1.6.tar.gz
Algorithm Hash digest
SHA256 8a0bd8069fcf92d0f77110ac07c18397dbf4924f36aa9abc6e6e8f9226104775
MD5 8c54741b4377c376fd46ff24cabe7a2c
BLAKE2b-256 5a4a8e20f152f7d3a524b8b3b9d6601146c8e76f39cc846717ddea12a47941cb

See more details on using hashes here.

File details

Details for the file fm_dlp_core-0.1.6-py3-none-any.whl.

File metadata

  • Download URL: fm_dlp_core-0.1.6-py3-none-any.whl
  • Upload date:
  • Size: 44.4 kB
  • Tags: Python 3
  • Uploaded using Trusted Publishing? No
  • Uploaded via: uv/0.12.5 {"installer":{"name":"uv","version":"0.12.5","subcommand":["publish"]},"python":null,"implementation":{"name":null,"version":null},"distro":{"name":"Ubuntu","version":"24.04","id":"noble","libc":null},"system":{"name":null,"release":null},"cpu":null,"openssl_version":null,"setuptools_version":null,"rustc_version":null,"ci":true}

File hashes

Hashes for fm_dlp_core-0.1.6-py3-none-any.whl
Algorithm Hash digest
SHA256 fd6c301a8e6813cfc05f3d4db0d8a18910f124c225e3c21ea61d3a1ae48930a4
MD5 60d049925c64e1c434f55851289032e5
BLAKE2b-256 4cedaf6a94b0228a83d5e89ad64197904298b06cf19d53cad405e89a3056436a

See more details on using hashes here.

Release history Release notifications | RSS feed

0.2.5

2 files

0.2.4

2 files

0.2.3

2 files

0.2.2

2 files

0.2.1

2 files

0.2.0

2 files

0.1.9

2 files

0.1.8

2 files

0.1.7

2 files

This release

0.1.6 This release

2 files

0.1.5.4

2 files

0.1.5.3

2 files

0.1.5.2

2 files

0.1.5

2 files

Anthropic, PBC Visionary sponsor Bloomberg Visionary sponsor Hudson River Trading Visionary sponsor Meta Visionary sponsor NVIDIA Visionary sponsor Microsoft Sustainability sponsor Depot Continuous Integration AWS Cloud computing and Security Sponsor Datadog Monitoring Fastly CDN Google Download Analytics Sentry Error logging StatusPage Status page