A feature-rich command-line audio/video downloader forked from youtube-dl
Configurable pipeline of processors for audio extraction, video conversion, subtitle handling, metadata embedding, and other file transformations applied after download. The post-processing system provides extensive capabilities for format conversion, quality optimization, and content enhancement.
Post-processors for audio extraction, conversion, and quality optimization using FFmpeg.
class FFmpegExtractAudioPP:
"""
Extract audio from video files using FFmpeg.
Supports various audio formats and quality settings,
with automatic codec selection and quality optimization.
"""
def __init__(self, downloader=None, preferredcodec=None, preferredquality=None, nopostoverwrites=False):
"""
Initialize audio extraction post-processor.
Parameters:
- downloader: YoutubeDL instance
- preferredcodec: str|None, preferred audio codec ('mp3', 'aac', 'flac', etc.)
- preferredquality: str|None, quality setting ('0'-'9' for VBR, or bitrate)
- nopostoverwrites: bool, don't overwrite existing files
"""
class FFmpegPostProcessor:
"""
Base class for FFmpeg-based post-processors.
Provides common functionality for running FFmpeg commands,
handling options, and managing temporary files.
"""
def __init__(self, downloader=None):
"""
Initialize FFmpeg post-processor.
Parameters:
- downloader: YoutubeDL instance
"""
def run_ffmpeg(self, path, out_path, opts):
"""
Run FFmpeg command with specified options.
Parameters:
- path: str, input file path
- out_path: str, output file path
- opts: list[str], FFmpeg options
"""
def run_ffmpeg_multiple_files(self, input_paths, out_path, opts):
"""
Run FFmpeg with multiple input files.
Parameters:
- input_paths: list[str], input file paths
- out_path: str, output file path
- opts: list[str], FFmpeg options
"""Post-processors for video format conversion, quality adjustment, and container remuxing.
class FFmpegVideoConvertorPP(FFmpegPostProcessor):
"""
Convert video files to different formats using FFmpeg.
Supports various video codecs, quality settings, and container formats
with automatic parameter optimization for different use cases.
"""
def __init__(self, downloader=None, preferedformat=None):
"""
Initialize video conversion post-processor.
Parameters:
- downloader: YoutubeDL instance
- preferedformat: str|None, preferred output format ('mp4', 'mkv', 'webm', etc.)
"""
class FFmpegVideoRemuxerPP(FFmpegPostProcessor):
"""
Remux video files to different containers without re-encoding.
Changes container format while preserving original video and audio streams,
providing fast conversion with no quality loss.
"""
def __init__(self, downloader=None, preferedformat=None):
"""
Initialize video remuxing post-processor.
Parameters:
- downloader: YoutubeDL instance
- preferedformat: str|None, preferred container format
"""
class FFmpegMergerPP(FFmpegPostProcessor):
"""
Merge separate video and audio files using FFmpeg.
Combines video-only and audio-only streams into single files,
commonly used for high-quality YouTube formats.
"""
def __init__(self, downloader=None):
"""Initialize merger post-processor."""Post-processors for handling subtitles, captions, and thumbnail images.
class FFmpegSubtitlesConvertorPP(FFmpegPostProcessor):
"""
Convert subtitle files to different formats using FFmpeg.
Supports conversion between various subtitle formats including
SRT, VTT, ASS, and others with proper encoding handling.
"""
def __init__(self, downloader=None, format=None):
"""
Initialize subtitle conversion post-processor.
Parameters:
- downloader: YoutubeDL instance
- format: str|None, target subtitle format ('srt', 'vtt', 'ass', etc.)
"""
class FFmpegThumbnailsConvertorPP(FFmpegPostProcessor):
"""
Convert thumbnail images to different formats using FFmpeg.
Handles format conversion, resizing, and quality optimization
for thumbnail images.
"""
def __init__(self, downloader=None, format=None):
"""
Initialize thumbnail conversion post-processor.
Parameters:
- downloader: YoutubeDL instance
- format: str|None, target image format ('jpg', 'png', 'webp', etc.)
"""
class EmbedThumbnailPP:
"""
Embed thumbnail images into media files.
Adds thumbnail images as embedded artwork in supported
container formats like MP4, MKV, and MP3.
"""
def __init__(self, downloader=None, already_have_thumbnail=False):
"""
Initialize thumbnail embedding post-processor.
Parameters:
- downloader: YoutubeDL instance
- already_have_thumbnail: bool, whether thumbnail file already exists
"""Post-processors for parsing, extracting, and embedding metadata information.
class FFmpegMetadataPP(FFmpegPostProcessor):
"""
Embed metadata into media files using FFmpeg.
Adds title, artist, album, date, and other metadata
to media files in supported container formats.
"""
def __init__(self, downloader=None, add_chapters=True, add_metadata=True, add_infojson=None):
"""
Initialize metadata embedding post-processor.
Parameters:
- downloader: YoutubeDL instance
- add_chapters: bool, add chapter information
- add_metadata: bool, add basic metadata
- add_infojson: bool|str|None, embed info JSON ('if_exists', True, False, None)
"""
class MetadataFromFieldPP:
"""
Extract metadata from existing fields using regex patterns.
Parses title, description, or other fields to extract
structured metadata like artist, album, track number.
"""
def __init__(self, downloader=None, actions=None):
"""
Initialize field-based metadata extraction.
Parameters:
- downloader: YoutubeDL instance
- actions: list[tuple], parsing actions to perform
"""
@staticmethod
def to_action(f):
"""
Convert field specification to action tuple.
Parameters:
- f: str, field specification string
Returns:
tuple: action specification
"""
class MetadataParserPP:
"""
Advanced metadata parsing and manipulation post-processor.
Provides sophisticated metadata parsing, replacement,
and transformation capabilities using various methods.
"""
def __init__(self, downloader=None, actions=None, when=None):
"""
Initialize metadata parser post-processor.
Parameters:
- downloader: YoutubeDL instance
- actions: list[tuple], parsing actions
- when: str|None, when to run processor
"""
@staticmethod
def validate_action(*action):
"""
Validate action specification.
Parameters:
- *action: action components
Raises:
ValueError: if action is invalid
"""Post-processors for specialized tasks like SponsorBlock integration and file operations.
class SponsorBlockPP:
"""
SponsorBlock integration for marking/removing sponsored segments.
Integrates with SponsorBlock API to identify and handle
sponsored content, intros, outros, and other segments.
"""
def __init__(self, downloader=None, categories=None, api=None, when=None):
"""
Initialize SponsorBlock post-processor.
Parameters:
- downloader: YoutubeDL instance
- categories: set|None, segment categories to process
- api: str|None, SponsorBlock API URL
- when: str|None, when to run processor
"""
class ModifyChaptersPP:
"""
Modify chapter information in media files.
Adds, removes, or modifies chapters based on patterns,
SponsorBlock data, or custom specifications.
"""
def __init__(self, downloader=None, remove_chapters_patterns=None, remove_sponsor_segments=None, remove_ranges=None, sponsorblock_chapter_title=None, force_keyframes=False):
"""
Initialize chapter modification post-processor.
Parameters:
- downloader: YoutubeDL instance
- remove_chapters_patterns: list|None, patterns for chapters to remove
- remove_sponsor_segments: set|None, sponsor segment types to remove
- remove_ranges: list|None, time ranges to remove
- sponsorblock_chapter_title: str|None, title template for SponsorBlock chapters
- force_keyframes: bool, force keyframes at cuts
"""
class XAttrMetadataPP:
"""
Store metadata in file extended attributes (xattrs).
Saves metadata information in filesystem extended attributes
for preservation across file operations.
"""
def __init__(self, downloader=None):
"""Initialize extended attributes post-processor."""
class MoveFilesAfterDownloadPP:
"""
Move files to different locations after processing.
Handles file relocation based on templates and patterns,
useful for organizing downloads into directory structures.
"""
def __init__(self, downloader=None):
"""Initialize file moving post-processor."""Functions for discovering and managing post-processors.
def get_postprocessor(key):
"""
Get post-processor class by key name.
Parameters:
- key: str, post-processor identifier
Returns:
type: post-processor class
Raises:
KeyError: if post-processor not found
"""import yt_dlp
# Extract MP3 audio at high quality
ydl_opts = {
'format': 'bestaudio/best',
'postprocessors': [{
'key': 'FFmpegExtractAudio',
'preferredcodec': 'mp3',
'preferredquality': '192',
}],
}
with yt_dlp.YoutubeDL(ydl_opts) as ydl:
ydl.download(['https://www.youtube.com/watch?v=example'])import yt_dlp
# Convert to MP4 with specific quality
ydl_opts = {
'format': 'best[height<=720]',
'postprocessors': [{
'key': 'FFmpegVideoConvertor',
'preferedformat': 'mp4',
}],
}
with yt_dlp.YoutubeDL(ydl_opts) as ydl:
ydl.download(['https://www.youtube.com/watch?v=example'])import yt_dlp
# Embed metadata and thumbnail
ydl_opts = {
'writethumbnail': True,
'postprocessors': [
{
'key': 'FFmpegMetadata',
'add_metadata': True,
'add_chapters': True,
},
{
'key': 'EmbedThumbnail',
'already_have_thumbnail': False,
},
],
}
with yt_dlp.YoutubeDL(ydl_opts) as ydl:
ydl.download(['https://www.youtube.com/watch?v=example'])import yt_dlp
# Download and convert subtitles to SRT
ydl_opts = {
'writesubtitles': True,
'writeautomaticsub': True,
'subtitleslangs': ['en', 'es'],
'postprocessors': [{
'key': 'FFmpegSubtitlesConvertor',
'format': 'srt',
}],
}
with yt_dlp.YoutubeDL(ydl_opts) as ydl:
ydl.download(['https://www.youtube.com/watch?v=example'])import yt_dlp
# Complex processing pipeline
ydl_opts = {
'format': 'best',
'writethumbnail': True,
'writesubtitles': True,
'postprocessors': [
# First: Convert subtitles
{
'key': 'FFmpegSubtitlesConvertor',
'format': 'srt',
},
# Second: Extract audio
{
'key': 'FFmpegExtractAudio',
'preferredcodec': 'mp3',
'preferredquality': '192',
},
# Third: Embed metadata
{
'key': 'FFmpegMetadata',
'add_metadata': True,
},
# Fourth: Embed thumbnail
{
'key': 'EmbedThumbnail',
},
# Fifth: Store in extended attributes
{
'key': 'XAttrMetadata',
},
],
}
with yt_dlp.YoutubeDL(ydl_opts) as ydl:
ydl.download(['https://www.youtube.com/watch?v=example'])import yt_dlp
# Remove sponsored segments using SponsorBlock
ydl_opts = {
'postprocessors': [{
'key': 'SponsorBlock',
'categories': ['sponsor', 'intro', 'outro'],
'api': 'https://sponsor.ajay.app',
'when': 'after_filter',
}],
}
with yt_dlp.YoutubeDL(ydl_opts) as ydl:
ydl.download(['https://www.youtube.com/watch?v=example'])import yt_dlp
from yt_dlp.postprocessor import PostProcessor
class CustomPP(PostProcessor):
def __init__(self, downloader=None):
super().__init__(downloader)
def run(self, info):
# Custom processing logic
filename = info['filepath']
self.to_screen(f'Custom processing: {filename}')
# Return updated info and files to delete
return [], info
# Use custom post-processor
ydl_opts = {
'postprocessors': [{'key': 'Custom'}],
}
with yt_dlp.YoutubeDL(ydl_opts) as ydl:
# Register custom post-processor
ydl.add_post_processor(CustomPP())
ydl.download(['https://www.youtube.com/watch?v=example'])# Base post-processor class
class PostProcessor:
def __init__(self, downloader=None): ...
def run(self, info): ...
def to_screen(self, message, skip_eol=False): ...
# Post-processor configuration dictionary
PostProcessorDict = dict[str, Any]
# Processing phases when post-processors can run
POSTPROCESS_WHEN = [
'pre_process', # Before extraction
'after_filter', # After filtering but before download
'before_dl', # Before download
'post_process', # After download (default)
'after_move', # After moving files
'after_video', # After video processing
'playlist', # After playlist processing
]Install with Tessl CLI
npx tessl i tessl/pypi-yt-dlp