|
|
|
import os
|
|
|
|
import traceback
|
|
|
|
import typing
|
|
|
|
|
|
|
|
from knowit import __version__
|
|
|
|
from knowit.config import Config
|
|
|
|
from knowit.provider import Provider
|
|
|
|
from .providers import (
|
|
|
|
EnzymeProvider,
|
|
|
|
FFmpegProvider,
|
|
|
|
MediaInfoProvider,
|
|
|
|
MkvMergeProvider,
|
|
|
|
)
|
|
|
|
|
|
|
|
_provider_map = {
|
|
|
|
'mediainfo': MediaInfoProvider,
|
|
|
|
'ffmpeg': FFmpegProvider,
|
|
|
|
'mkvmerge': MkvMergeProvider,
|
|
|
|
'enzyme': EnzymeProvider,
|
|
|
|
}
|
|
|
|
|
|
|
|
provider_names = _provider_map.keys()
|
|
|
|
|
|
|
|
available_providers: typing.Dict[str, Provider] = {}
|
|
|
|
|
|
|
|
|
|
|
|
class KnowitException(Exception):
|
|
|
|
"""Exception raised when knowit encounters an internal error."""
|
|
|
|
|
|
|
|
|
|
|
|
def initialize(context: typing.Optional[typing.Mapping] = None) -> None:
|
|
|
|
"""Initialize knowit."""
|
|
|
|
if not available_providers:
|
|
|
|
context = context or {}
|
|
|
|
config = Config.build(context.get('config'))
|
|
|
|
for name, provider_cls in _provider_map.items():
|
|
|
|
general_config = getattr(config, 'general', {})
|
|
|
|
mapping = context.get(name) or general_config.get(name)
|
|
|
|
available_providers[name] = provider_cls(config, mapping)
|
|
|
|
|
|
|
|
|
|
|
|
def know(
|
|
|
|
video_path: typing.Union[str, os.PathLike],
|
|
|
|
context: typing.Optional[typing.MutableMapping] = None
|
|
|
|
) -> typing.Mapping:
|
|
|
|
"""Return a mapping of video metadata."""
|
|
|
|
video_path = os.fspath(video_path)
|
|
|
|
|
|
|
|
try:
|
|
|
|
context = context or {}
|
|
|
|
context.setdefault('profile', 'default')
|
|
|
|
initialize(context)
|
|
|
|
|
|
|
|
for name, provider in available_providers.items():
|
|
|
|
if name != (context.get('provider') or name):
|
|
|
|
continue
|
|
|
|
|
|
|
|
if provider.accepts(video_path):
|
|
|
|
result = provider.describe(video_path, context)
|
|
|
|
if result:
|
|
|
|
return result
|
|
|
|
|
|
|
|
return {}
|
|
|
|
except Exception:
|
|
|
|
raise KnowitException(debug_info(context=context, exc_info=True))
|
|
|
|
|
|
|
|
|
|
|
|
def dependencies(context: typing.Optional[typing.Mapping] = None) -> typing.Mapping:
|
|
|
|
"""Return all dependencies detected by knowit."""
|
|
|
|
deps = {}
|
|
|
|
try:
|
|
|
|
initialize(context)
|
|
|
|
for name, provider_cls in _provider_map.items():
|
|
|
|
if name in available_providers:
|
|
|
|
deps[name] = available_providers[name].version
|
|
|
|
else:
|
|
|
|
deps[name] = {}
|
|
|
|
except Exception:
|
|
|
|
pass
|
|
|
|
|
|
|
|
return deps
|
|
|
|
|
|
|
|
|
|
|
|
def _centered(value: str) -> str:
|
|
|
|
value = value[-52:]
|
|
|
|
return f'| {value:^53} |'
|
|
|
|
|
|
|
|
|
|
|
|
def debug_info(
|
|
|
|
context: typing.Optional[typing.MutableMapping] = None,
|
|
|
|
exc_info: bool = False,
|
|
|
|
) -> str:
|
|
|
|
lines = [
|
|
|
|
'+-------------------------------------------------------+',
|
|
|
|
_centered(f'KnowIt {__version__}'),
|
|
|
|
'+-------------------------------------------------------+'
|
|
|
|
]
|
|
|
|
|
|
|
|
first = True
|
|
|
|
for key, info in dependencies(context).items():
|
|
|
|
if not first:
|
|
|
|
lines.append(_centered(''))
|
|
|
|
first = False
|
|
|
|
|
|
|
|
for k, v in info.items():
|
|
|
|
lines.append(_centered(k))
|
|
|
|
lines.append(_centered(v))
|
|
|
|
|
|
|
|
if context:
|
|
|
|
debug_data = context.pop('debug_data', None)
|
|
|
|
|
|
|
|
lines.append('+-------------------------------------------------------+')
|
|
|
|
for k, v in context.items():
|
|
|
|
if v:
|
|
|
|
lines.append(_centered(f'{k}: {v}'))
|
|
|
|
|
|
|
|
if debug_data:
|
|
|
|
lines.append('+-------------------------------------------------------+')
|
|
|
|
lines.append(debug_data())
|
|
|
|
|
|
|
|
if exc_info:
|
|
|
|
lines.append('+-------------------------------------------------------+')
|
|
|
|
lines.append(traceback.format_exc())
|
|
|
|
|
|
|
|
lines.append('+-------------------------------------------------------+')
|
|
|
|
lines.append(_centered('Please report any bug or feature request at'))
|
|
|
|
lines.append(_centered('https://github.com/ratoaq2/knowit/issues.'))
|
|
|
|
lines.append('+-------------------------------------------------------+')
|
|
|
|
|
|
|
|
return '\n'.join(lines)
|