- Sponsor
-
Notifications
You must be signed in to change notification settings - Fork 313
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Loading status checks…
Use knowit to parse video metadata (frame_rate, duration, subtitles..…
….) (#1154) * use knowit to parse video metadata * add doc about knowit installation
Showing
9 changed files
with
345 additions
and
93 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,8 @@ | ||
Use `knowit` to extract information from video file, instead of `enzyme`: | ||
frame rate, duration and subtitles. | ||
`knowit` relies on external programs (`mediainfo`, `ffmpeg`, `mkvmerge`) | ||
and falls back to using `enzyme` if none is installed. | ||
On Windows and MacOS, `libmediainfo` is installed automatically | ||
via the `pymediainfo` python package dependency. | ||
On Linux, the `libmediainfo` or `mediainfo` package needs to be installed | ||
with the package manager of your distribution. |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,30 @@ | ||
Installation | ||
============ | ||
|
||
From Pypi | ||
--------- | ||
|
||
For a better isolation with your system you should use a dedicated virtualenv. | ||
The preferred installation method is to use `pipx <https://github.com/pypa/pipx>`_ that does that for you:: | ||
|
||
$ pipx install subliminal | ||
|
||
Subliminal can be also be installed as a regular python module by running:: | ||
|
||
$ pip install --user subliminal | ||
|
||
From source | ||
----------- | ||
|
||
If you want to modify the code, `fork <https://github.com/Diaoul/subliminal/fork>`_ this repo, | ||
clone your fork locally and install a development version:: | ||
|
||
$ git clone https://github.com/<my-username>/subliminal | ||
$ cd subliminal | ||
$ pip install --user -e '.[dev,test,docs]' | ||
|
||
External dependencies | ||
--------------------- | ||
|
||
To extract information about the video files, `subliminal` uses `knowit <https://github.com/ratoaq2/knowit`. | ||
For better results, make sure one of its provider is installed, for instance `MediaInfo <https://mediaarea.net/en/MediaInfo>`. |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,31 +1,142 @@ | ||
from __future__ import annotations | ||
|
||
import logging | ||
from datetime import timedelta | ||
from typing import Any | ||
|
||
import pytest | ||
from babelfish import Language # type: ignore[import-untyped] | ||
from knowit.units import units # type: ignore[import-untyped] | ||
from subliminal.core import scan_video | ||
from subliminal.refiners.metadata import refine | ||
from subliminal.video import Movie | ||
from subliminal.refiners.metadata import ( | ||
get_float, | ||
get_subtitle_format, | ||
loaded_providers, | ||
refine, | ||
) | ||
|
||
providers = ['mediainfo', 'ffmpeg', 'mkvmerge', 'enzyme'] | ||
|
||
def test_refine_video_metadata(mkv): | ||
scanned_video = scan_video(mkv['test5']) | ||
refine(scanned_video, embedded_subtitles=True) | ||
|
||
assert type(scanned_video) is Movie | ||
@pytest.mark.parametrize( | ||
('value', 'expected'), | ||
[ | ||
(None, None), | ||
(1, 1.0), | ||
(2, 2.0), | ||
('3.14', 3.14), | ||
(timedelta(hours=1, minutes=60, seconds=60), 7260.0), | ||
(24 * units.FPS, 24.0), | ||
], | ||
) | ||
def test_get_float(value: Any, expected: float | None) -> None: | ||
ret = get_float(value) | ||
assert ret is None or isinstance(ret, float) | ||
assert ret == expected | ||
|
||
|
||
def test_get_float_error() -> None: | ||
with pytest.raises(TypeError): | ||
get_float((1.0,)) | ||
|
||
|
||
@pytest.mark.parametrize( | ||
('value', 'expected'), | ||
[ | ||
(None, None), | ||
('ass', 'ass'), | ||
('ssa', 'ssa'), | ||
('subrip', 'srt'), | ||
('pgs', 'pgs'), | ||
], | ||
) | ||
def test_get_subtitle_format(value: str | None, expected: str | None) -> None: | ||
"""Convert str subrip -> srt""" | ||
subtitle_format = get_subtitle_format(value) | ||
assert subtitle_format == expected | ||
|
||
|
||
@pytest.mark.parametrize('provider', providers) | ||
def test_refine_video_metadata(mkv: dict[str, Any], provider: str) -> None: | ||
# Skip test if provider is not installed | ||
if not loaded_providers().get(provider, False): | ||
pytest.skip(f'uninstalled provider {provider}') | ||
|
||
# Scan video | ||
scanned_video = scan_video(mkv['test5']) | ||
assert scanned_video.name == mkv['test5'] | ||
assert scanned_video.source is None | ||
assert scanned_video.release_group is None | ||
assert scanned_video.resolution is None | ||
assert scanned_video.size == 31762747 | ||
|
||
# Refine with file metadata | ||
refine(scanned_video, embedded_subtitles=True, metadata_provider=provider) | ||
assert scanned_video.resolution is None | ||
assert scanned_video.duration == 46.665 | ||
assert scanned_video.video_codec == 'H.264' | ||
assert scanned_video.audio_codec == 'AAC' | ||
assert scanned_video.imdb_id is None | ||
assert scanned_video.size == 31762747 | ||
assert scanned_video.subtitle_languages == { | ||
# Language('eng'), # bug in enzyme | ||
Language('spa'), | ||
Language('deu'), | ||
Language('jpn'), | ||
Language('und'), | ||
Language('ita'), | ||
Language('fra'), | ||
Language('hun'), | ||
} | ||
assert scanned_video.title == 'test5' | ||
assert scanned_video.year is None | ||
|
||
# Enzyme has limited functionalities | ||
if provider == 'enzyme': | ||
assert scanned_video.subtitle_languages == { | ||
# Language('eng'), # bug with enzyme | ||
Language('spa'), | ||
Language('deu'), | ||
Language('jpn'), | ||
Language('und'), | ||
Language('ita'), | ||
Language('fra'), | ||
Language('hun'), | ||
} | ||
|
||
# other providers | ||
else: | ||
if provider != 'mkvmerge': | ||
assert scanned_video.frame_rate == 24 | ||
|
||
assert scanned_video.subtitle_languages == { | ||
Language('eng'), | ||
Language('spa'), | ||
Language('deu'), | ||
Language('jpn'), | ||
Language('und'), | ||
Language('ita'), | ||
Language('fra'), | ||
Language('hun'), | ||
} | ||
for subtitle in scanned_video.subtitles: | ||
assert subtitle.subtitle_format == 'srt' | ||
|
||
|
||
def test_refine_video_metadata_no_provider(mkv: dict[str, Any]) -> None: | ||
scanned_video = scan_video(mkv['test5']) | ||
refine(scanned_video, embedded_subtitles=True) | ||
|
||
assert scanned_video.duration == 46.665 | ||
# cannot put 8, because if enzyme is used it finds only 7 | ||
assert len(scanned_video.subtitle_languages) >= 7 | ||
|
||
|
||
def test_refine_video_metadata_wrong_provider(mkv: dict[str, Any], caplog) -> None: | ||
scanned_video = scan_video(mkv['test5']) | ||
with caplog.at_level(logging.WARNING): | ||
refine(scanned_video, embedded_subtitles=True, metadata_provider='not-a-provider') | ||
|
||
assert "metadata_provider='not-a-provider' is not a valid argument" in caplog.text | ||
|
||
|
||
def test_refine_video_metadata_no_embedded_subtitles(mkv: dict[str, Any]) -> None: | ||
scanned_video = scan_video(mkv['test5']) | ||
refine(scanned_video, embedded_subtitles=False) | ||
|
||
assert scanned_video.duration == 46.665 | ||
assert len(scanned_video.subtitle_languages) == 0 | ||
|
||
|
||
def test_refine_no_subtitle_track(mkv: dict[str, Any]) -> None: | ||
"""Also tests resolution 480p.""" | ||
scanned_video = scan_video(mkv['test1']) | ||
refine(scanned_video, embedded_subtitles=True) | ||
|
||
assert scanned_video.duration == 87.336 | ||
assert scanned_video.resolution == '480p' | ||
assert len(scanned_video.subtitle_languages) == 0 |