Plugin support
Extractor plugins are loaded from <root-dir>/ytdlp_plugins/extractor/__init__.py Inspired by https://github.com/un-def/dl-plus :ci skip dl
This commit is contained in:
parent
c571435f9c
commit
f74980cbae
9 changed files with 72 additions and 14 deletions
10
.gitignore
vendored
10
.gitignore
vendored
|
@ -65,6 +65,14 @@ venv/
|
|||
# VS Code related files
|
||||
.vscode
|
||||
|
||||
# SublimeText files
|
||||
*.sublime-workspace
|
||||
|
||||
# Cookies
|
||||
cookies
|
||||
cookies.txt
|
||||
|
||||
*.sublime-workspace
|
||||
# Plugins
|
||||
ytdlp_plugins/extractor/*
|
||||
!ytdlp_plugins/extractor/__init__.py
|
||||
!ytdlp_plugins/extractor/sample.py
|
|
@ -40,6 +40,7 @@ This is a fork of [youtube-dlc](https://github.com/blackjack4494/yt-dlc) which i
|
|||
* [Filtering Formats](#filtering-formats)
|
||||
* [Sorting Formats](#sorting-formats)
|
||||
* [Format Selection examples](#format-selection-examples)
|
||||
* [PLUGINS](#plugins)
|
||||
* [MORE](#more)
|
||||
|
||||
|
||||
|
@ -1082,9 +1083,11 @@ $ youtube-dlc -S 'res:720,fps'
|
|||
$ youtube-dlc -S '+res:480,codec,br'
|
||||
```
|
||||
|
||||
# PLUGINS
|
||||
|
||||
Plugins are loaded from `<root-dir>/ytdlp_plugins/<type>/__init__.py`. Currently only `extractor` plugins are supported. Support for `downloader` and `postprocessor` plugins may be added in the future. See [ytdlp_plugins](ytdlp_plugins) for example.
|
||||
|
||||
|
||||
**Note**: `<root-dir>` is the directory of the binary (`<root-dir>/youtube-dlc`), or the root directory of the module if you are running directly from source-code ((`<root dir>/youtube_dlc/__main__.py`)
|
||||
|
||||
# MORE
|
||||
For FAQ, Developer Instructions etc., see the [original README](https://github.com/ytdl-org/youtube-dl)
|
||||
|
|
|
@ -1 +1 @@
|
|||
py -m PyInstaller youtube_dlc\__main__.py --onefile --name youtube-dlc --version-file win\ver.txt --icon win\icon\cloud.ico --upx-exclude=vcruntime140.dll
|
||||
py -m PyInstaller youtube_dlc\__main__.py --onefile --name youtube-dlc --version-file win\ver.txt --icon win\icon\cloud.ico --upx-exclude=vcruntime140.dll --exclude-module ytdlp_plugins
|
|
@ -105,7 +105,7 @@ from .utils import (
|
|||
process_communicate_or_kill,
|
||||
)
|
||||
from .cache import Cache
|
||||
from .extractor import get_info_extractor, gen_extractor_classes, _LAZY_LOADER
|
||||
from .extractor import get_info_extractor, gen_extractor_classes, _LAZY_LOADER, _PLUGIN_CLASSES
|
||||
from .extractor.openload import PhantomJSwrapper
|
||||
from .downloader import get_suitable_downloader
|
||||
from .downloader.rtmp import rtmpdump_version
|
||||
|
@ -2652,9 +2652,12 @@ class YoutubeDL(object):
|
|||
self.get_encoding()))
|
||||
write_string(encoding_str, encoding=None)
|
||||
|
||||
self._write_string('[debug] yt-dlp version ' + __version__ + '\n')
|
||||
self._write_string('[debug] yt-dlp version %s\n' % __version__)
|
||||
if _LAZY_LOADER:
|
||||
self._write_string('[debug] Lazy loading extractors enabled' + '\n')
|
||||
self._write_string('[debug] Lazy loading extractors enabled\n')
|
||||
if _PLUGIN_CLASSES:
|
||||
self._write_string(
|
||||
'[debug] Plugin Extractors: %s\n' % [ie.ie_key() for ie in _PLUGIN_CLASSES])
|
||||
try:
|
||||
sp = subprocess.Popen(
|
||||
['git', 'rev-parse', '--short', 'HEAD'],
|
||||
|
@ -2663,7 +2666,7 @@ class YoutubeDL(object):
|
|||
out, err = process_communicate_or_kill(sp)
|
||||
out = out.decode().strip()
|
||||
if re.match('[0-9a-f]+', out):
|
||||
self._write_string('[debug] Git HEAD: ' + out + '\n')
|
||||
self._write_string('[debug] Git HEAD: %s\n' % out)
|
||||
except Exception:
|
||||
try:
|
||||
sys.exc_clear()
|
||||
|
|
|
@ -1,13 +1,19 @@
|
|||
from __future__ import unicode_literals
|
||||
|
||||
from ..utils import load_plugins
|
||||
|
||||
try:
|
||||
from .lazy_extractors import *
|
||||
from .lazy_extractors import _ALL_CLASSES
|
||||
_LAZY_LOADER = True
|
||||
_PLUGIN_CLASSES = []
|
||||
|
||||
except ImportError:
|
||||
_LAZY_LOADER = False
|
||||
from .extractors import *
|
||||
|
||||
_PLUGIN_CLASSES = load_plugins('extractor', 'IE', globals())
|
||||
|
||||
_ALL_CLASSES = [
|
||||
klass
|
||||
for name, klass in globals().items()
|
||||
|
|
|
@ -15,6 +15,7 @@ from .compat import (
|
|||
)
|
||||
from .utils import (
|
||||
expand_path,
|
||||
get_executable_path,
|
||||
preferredencoding,
|
||||
write_string,
|
||||
)
|
||||
|
@ -1226,13 +1227,7 @@ def parseOpts(overrideArguments=None):
|
|||
return [], None
|
||||
return config, current_path
|
||||
|
||||
def get_portable_path():
|
||||
path = os.path.dirname(sys.argv[0])
|
||||
if os.path.abspath(sys.argv[0]) != os.path.abspath(sys.executable): # Not packaged
|
||||
path = os.path.join(path, '..')
|
||||
return os.path.abspath(path)
|
||||
|
||||
configs['portable'], paths['portable'] = read_options(get_portable_path())
|
||||
configs['portable'], paths['portable'] = read_options(get_executable_path())
|
||||
if '--ignore-config' in configs['portable']:
|
||||
return
|
||||
|
||||
|
|
|
@ -16,6 +16,7 @@ import email.header
|
|||
import errno
|
||||
import functools
|
||||
import gzip
|
||||
import imp
|
||||
import io
|
||||
import itertools
|
||||
import json
|
||||
|
@ -5905,3 +5906,31 @@ def make_dir(path, to_screen=None):
|
|||
if callable(to_screen) is not None:
|
||||
to_screen('unable to create directory ' + error_to_compat_str(err))
|
||||
return False
|
||||
|
||||
|
||||
def get_executable_path():
|
||||
path = os.path.dirname(sys.argv[0])
|
||||
if os.path.abspath(sys.argv[0]) != os.path.abspath(sys.executable): # Not packaged
|
||||
path = os.path.join(path, '..')
|
||||
return os.path.abspath(path)
|
||||
|
||||
|
||||
def load_plugins(name, type, namespace):
|
||||
plugin_info = [None]
|
||||
classes = []
|
||||
try:
|
||||
plugin_info = imp.find_module(
|
||||
name, [os.path.join(get_executable_path(), 'ytdlp_plugins')])
|
||||
plugins = imp.load_module(name, *plugin_info)
|
||||
for name in dir(plugins):
|
||||
if not name.endswith(type):
|
||||
continue
|
||||
klass = getattr(plugins, name)
|
||||
classes.append(klass)
|
||||
namespace[name] = klass
|
||||
except ImportError:
|
||||
pass
|
||||
finally:
|
||||
if plugin_info[0] is not None:
|
||||
plugin_info[0].close()
|
||||
return classes
|
||||
|
|
2
ytdlp_plugins/extractor/__init__.py
Normal file
2
ytdlp_plugins/extractor/__init__.py
Normal file
|
@ -0,0 +1,2 @@
|
|||
# flake8: noqa
|
||||
from .sample import SamplePluginIE
|
12
ytdlp_plugins/extractor/sample.py
Normal file
12
ytdlp_plugins/extractor/sample.py
Normal file
|
@ -0,0 +1,12 @@
|
|||
from __future__ import unicode_literals
|
||||
|
||||
from youtube_dlc.extractor.common import InfoExtractor
|
||||
|
||||
|
||||
class SamplePluginIE(InfoExtractor):
|
||||
_WORKING = False
|
||||
IE_DESC = False
|
||||
_VALID_URL = r'^sampleplugin:'
|
||||
|
||||
def _real_extract(self, url):
|
||||
self.to_screen('URL "%s" sucessfully captured' % url)
|
Loading…
Reference in a new issue