Skip to main content

Developing Plugins for yt-dlp

This comprehensive guide covers everything you need to know about developing plugins for yt-dlp, from basic extractor creation to advanced post-processor development.

Plugin Development Overview

Prerequisites

  • Python 3.9+ with strong programming skills
  • Understanding of yt-dlp's core functionality
  • Web technologies knowledge (HTML, CSS, JavaScript)
  • HTTP/networking understanding
  • Git version control

Plugin Types

1. Extractor Plugins

Extract video information and download URLs from websites.

2. Post-Processor Plugins

Process downloaded files or metadata after download.

3. Downloader Plugins

Custom download methods and protocols.

Basic Extractor Example

from yt_dlp.extractor.common import InfoExtractor
from yt_dlp.utils import ExtractorError, int_or_none

class ExampleSiteIE(InfoExtractor):
IE_NAME = 'examplesite'
IE_DESC = 'Example video hosting site'
_VALID_URL = r'https?://(?:www\.)?example\.com/watch/(?P<id>[a-zA-Z0-9]+)'

_TESTS = [{
'url': 'https://example.com/watch/abc123',
'info_dict': {
'id': 'abc123',
'ext': 'mp4',
'title': 'Test Video',
'description': 'Test video description',
'duration': 120,
}
}]

def _real_extract(self, url):
video_id = self._match_id(url)
webpage = self._download_webpage(url, video_id)

title = self._html_search_regex(
r'<h1[^>]*>([^<]+)</h1>', webpage, 'title')

video_url = self._html_search_regex(
r'videoUrl\s*:\s*["\']([^"\']+)["\']',
webpage, 'video URL')

return {
'id': video_id,
'title': title,
'url': video_url,
}

Post-Processor Example

from yt_dlp.postprocessor.common import PostProcessor
from yt_dlp.utils import PostProcessingError

class CustomProcessor(PostProcessor):
def __init__(self, downloader=None, **kwargs):
super().__init__(downloader)
self.custom_option = kwargs.get('custom_option', 'default')

def run(self, info):
filepath = info['filepath']

try:
# Custom processing logic here
self.to_screen(f'Processing {info["title"]}')

except Exception as e:
raise PostProcessingError(f'Processing failed: {str(e)}')

return [], info

Testing and Debugging

Unit Testing

import unittest
from yt_dlp.extractor import get_info_extractor

class TestExampleSiteIE(unittest.TestCase):
def setUp(self):
self.ie = get_info_extractor('ExampleSite')()

def test_video_extraction(self):
url = 'https://example.com/watch/abc123'
info = self.ie.extract(url)

self.assertEqual(info['id'], 'abc123')
self.assertIsNotNone(info['url'])

Debug Logging

def _real_extract(self, url):
video_id = self._match_id(url)
self.write_debug(f'Extracting video ID: {video_id}')

webpage = self._download_webpage(url, video_id)
self.write_debug(f'Downloaded webpage, length: {len(webpage)}')

# Continue extraction...

Plugin Packaging

Setup.py Configuration

from setuptools import setup, find_packages

setup(
name='yt-dlp-example-plugin',
version='1.0.0',
description='Example plugin for yt-dlp',
packages=find_packages(),
install_requires=['yt-dlp>=2024.1.1'],
entry_points={
'yt_dlp.plugins': [
'example = yt_dlp_example.extractors:ExampleSiteIE',
],
},
python_requires='>=3.9',
)

Plugin Directory Structure

yt-dlp-example-plugin/
yt_dlp_example/
__init__.py
extractors/
__init__.py
example.py
postprocessors/
__init__.py
example.py
tests/
setup.py
README.md
LICENSE