diff --git a/.gitignore b/.gitignore index 4577e72..1d7ba1d 100644 --- a/.gitignore +++ b/.gitignore @@ -6,3 +6,4 @@ ansible/inventory/hawaii.yml ansible/inventory/peppermint.yml ffx_test_report.log bin/conversiontest.py + diff --git a/ffx.egg-info/PKG-INFO b/ffx.egg-info/PKG-INFO deleted file mode 100644 index 2967e19..0000000 --- a/ffx.egg-info/PKG-INFO +++ /dev/null @@ -1,57 +0,0 @@ -Metadata-Version: 2.1 -Name: ffx -Version: 0.2.2 -Summary: FFX recoding and metadata managing tool -Home-page: https://gitea.maveno.de/Javanaut/ffx -Author: Javanaut -Author-email: javanaut@maveno.de -Project-URL: Bug Tracker, https://gitea.maveno.de/Javanaut/ffx/issues -Classifier: Operating System :: OS Independent -Requires-Python: >=3.6 -Description-Content-Type: text/markdown -Requires-Dist: requests -Requires-Dist: click -Requires-Dist: textual -Requires-Dist: sqlalchemy - -# FFX - -## Installation - -per https: - -```sh -pip install https:////ffx.git@ -``` - -per git: - -```sh -pip install git+ssh://@//ffx.git@ -``` - -## Version history - -### 0.1.1 - -Bugfixes, TMBD identify shows - -### 0.1.2 - -Bugfixes - -### 0.1.3 - -Subtitle file imports - -### 0.2.0 - -Tests, Config-File - -### 0.2.1 - -Signature, Tags cleaning, Bugfixes, Refactoring - -### 0.2.2 - -CLI-Overrides diff --git a/ffx.egg-info/SOURCES.txt b/ffx.egg-info/SOURCES.txt deleted file mode 100644 index 1917e97..0000000 --- a/ffx.egg-info/SOURCES.txt +++ /dev/null @@ -1,121 +0,0 @@ -README.md -pyproject.toml -setup.cfg -ffx.egg-info/PKG-INFO -ffx.egg-info/SOURCES.txt -ffx.egg-info/dependency_links.txt -ffx.egg-info/entry_points.txt -ffx.egg-info/requires.txt -ffx.egg-info/top_level.txt -src/ffx.py -src/ffx_tests.py -src/ffx/__init__.py -src/ffx/audio_layout.py -src/ffx/configuration_controller.py -src/ffx/constants.py -src/ffx/database.py -src/ffx/ffx_app.py -src/ffx/ffx_controller.py -src/ffx/file_properties.py -src/ffx/help_screen.py -src/ffx/helper.py -src/ffx/iso_language.py -src/ffx/media_controller.py -src/ffx/media_descriptor.py -src/ffx/media_details_screen.py -src/ffx/pattern_controller.py -src/ffx/pattern_delete_screen.py -src/ffx/pattern_details_screen.py -src/ffx/process.py -src/ffx/settings_screen.py -src/ffx/shifted_season_controller.py -src/ffx/shifted_season_delete_screen.py -src/ffx/shifted_season_details_screen.py -src/ffx/show_controller.py -src/ffx/show_delete_screen.py -src/ffx/show_descriptor.py -src/ffx/show_details_screen.py -src/ffx/shows_screen.py -src/ffx/tag_controller.py -src/ffx/tag_delete_screen.py -src/ffx/tag_details_screen.py -src/ffx/tmdb_controller.py -src/ffx/track_controller.py -src/ffx/track_delete_screen.py -src/ffx/track_descriptor.py -src/ffx/track_details_screen.py -src/ffx/track_disposition.py -src/ffx/track_type.py -src/ffx/video_encoder.py -src/ffx/filter/__init__.py -src/ffx/filter/filter.py -src/ffx/filter/nlmeans_filter.py -src/ffx/filter/preset_filter.py -src/ffx/filter/quality_filter.py -src/ffx/filter/scale_filter.py -src/ffx/model/__init__.py -src/ffx/model/media_tag.py -src/ffx/model/pattern.py -src/ffx/model/property.py -src/ffx/model/shifted_season.py -src/ffx/model/show.py -src/ffx/model/track.py -src/ffx/model/track_tag.py -src/ffx/model/conversions/__init__.py -src/ffx/model/conversions/conversion.py -src/ffx/model/conversions/conversion_2_3.py -src/ffx/model/conversions/conversion_3_4.py -src/ffx/test/_basename_combinator_1.py -src/ffx/test/basename_combinator.py -src/ffx/test/basename_combinator_0.py -src/ffx/test/basename_combinator_2.py -src/ffx/test/combinator.py -src/ffx/test/disposition_combinator_2.py -src/ffx/test/disposition_combinator_2_0.py -src/ffx/test/disposition_combinator_2_1.py -src/ffx/test/disposition_combinator_2_2.py -src/ffx/test/disposition_combinator_2_3 .py -src/ffx/test/disposition_combinator_3.py -src/ffx/test/disposition_combinator_3_0.py -src/ffx/test/disposition_combinator_3_1.py -src/ffx/test/disposition_combinator_3_2.py -src/ffx/test/disposition_combinator_3_3.py -src/ffx/test/disposition_combinator_3_4.py -src/ffx/test/helper.py -src/ffx/test/indicator_combinator.py -src/ffx/test/label_combinator.py -src/ffx/test/label_combinator_0.py -src/ffx/test/label_combinator_1.py -src/ffx/test/media_combinator.py -src/ffx/test/media_combinator_0.py -src/ffx/test/media_combinator_1.py -src/ffx/test/media_combinator_2.py -src/ffx/test/media_combinator_3.py -src/ffx/test/media_combinator_4.py -src/ffx/test/media_combinator_5.py -src/ffx/test/media_combinator_6.py -src/ffx/test/media_combinator_7.py -src/ffx/test/media_tag_combinator.py -src/ffx/test/media_tag_combinator_0.py -src/ffx/test/media_tag_combinator_1.py -src/ffx/test/media_tag_combinator_2.py -src/ffx/test/permutation_combinator_2.py -src/ffx/test/permutation_combinator_3.py -src/ffx/test/release_combinator.py -src/ffx/test/scenario.py -src/ffx/test/scenario_1.py -src/ffx/test/scenario_2.py -src/ffx/test/scenario_4.py -src/ffx/test/show_combinator.py -src/ffx/test/title_combinator.py -src/ffx/test/track_tag_combinator_2.py -src/ffx/test/track_tag_combinator_2_0.py -src/ffx/test/track_tag_combinator_2_1.py -src/ffx/test/track_tag_combinator_2_2.py -src/ffx/test/track_tag_combinator_2_3.py -src/ffx/test/track_tag_combinator_3.py -src/ffx/test/track_tag_combinator_3_0.py -src/ffx/test/track_tag_combinator_3_1.py -src/ffx/test/track_tag_combinator_3_2.py -src/ffx/test/track_tag_combinator_3_3.py -src/ffx/test/track_tag_combinator_3_4.py \ No newline at end of file diff --git a/ffx.egg-info/dependency_links.txt b/ffx.egg-info/dependency_links.txt deleted file mode 100644 index 8b13789..0000000 --- a/ffx.egg-info/dependency_links.txt +++ /dev/null @@ -1 +0,0 @@ - diff --git a/ffx.egg-info/entry_points.txt b/ffx.egg-info/entry_points.txt deleted file mode 100644 index ef54e3c..0000000 --- a/ffx.egg-info/entry_points.txt +++ /dev/null @@ -1,2 +0,0 @@ -[console_scripts] -osgw = ffx:ffx diff --git a/ffx.egg-info/requires.txt b/ffx.egg-info/requires.txt deleted file mode 100644 index 00d455c..0000000 --- a/ffx.egg-info/requires.txt +++ /dev/null @@ -1,4 +0,0 @@ -requests -click -textual -sqlalchemy diff --git a/ffx.egg-info/top_level.txt b/ffx.egg-info/top_level.txt deleted file mode 100644 index 25e4d71..0000000 --- a/ffx.egg-info/top_level.txt +++ /dev/null @@ -1,2 +0,0 @@ -ansible -src diff --git a/src/ffx.egg-info/PKG-INFO b/src/ffx.egg-info/PKG-INFO index e94b45e..5d45927 100644 --- a/src/ffx.egg-info/PKG-INFO +++ b/src/ffx.egg-info/PKG-INFO @@ -607,7 +607,6 @@ Classifier: Development Status :: 3 - Alpha Classifier: Programming Language :: Python Description-Content-Type: text/markdown License-File: LICENSE.md -Requires-Dist: rich Requires-Dist: requests Requires-Dist: click Requires-Dist: textual diff --git a/src/ffx.egg-info/SOURCES.txt b/src/ffx.egg-info/SOURCES.txt index f96b92c..ecb61f0 100644 --- a/src/ffx.egg-info/SOURCES.txt +++ b/src/ffx.egg-info/SOURCES.txt @@ -3,6 +3,7 @@ README.md pyproject.toml src/ffx/__init__.py src/ffx/audio_layout.py +src/ffx/codec.py src/ffx/configuration_controller.py src/ffx/constants.py src/ffx/database.py diff --git a/src/ffx.egg-info/requires.txt b/src/ffx.egg-info/requires.txt index bca8e96..00d455c 100644 --- a/src/ffx.egg-info/requires.txt +++ b/src/ffx.egg-info/requires.txt @@ -1,4 +1,3 @@ -rich requests click textual diff --git a/src/ffx/database.py b/src/ffx/database.py index 7676ea8..5c46034 100644 --- a/src/ffx/database.py +++ b/src/ffx/database.py @@ -54,7 +54,6 @@ def databaseContext(databasePath: str = ''): def ensureDatabaseVersion(databaseContext): currentDatabaseVersion = getDatabaseVersion(databaseContext) - click.echo(f"current database version: {currentDatabaseVersion}") if currentDatabaseVersion: if currentDatabaseVersion != DATABASE_VERSION: raise DatabaseVersionException(f"Current database version ({currentDatabaseVersion}) does not match required ({DATABASE_VERSION})") diff --git a/src/ffx/ffx.py b/src/ffx/ffx.py index c8c1832..fe5bde1 100755 --- a/src/ffx/ffx.py +++ b/src/ffx/ffx.py @@ -19,6 +19,7 @@ from ffx.show_descriptor import ShowDescriptor from ffx.track_type import TrackType from ffx.video_encoder import VideoEncoder from ffx.track_disposition import TrackDisposition +from ffx.track_codec import TrackCodec from ffx.process import executeProcess from ffx.helper import filterFilename @@ -105,27 +106,14 @@ def inspect(ctx, filename): app = FfxApp(ctx.obj) app.run() -#TODO: TrackCodec Klasse -CODEC_LOOKUP_TABLE = { - 'h264': {'format': 'h264', 'extension': 'h264'}, - 'aac': { 'extension': 'aac'}, - 'ac3': {'format': 'ac3', 'extension': 'ac3'}, - 'ass': {'format': 'ass', 'extension': 'ass'}, - 'hdmv_pgs_subtitle': {'format': 'sup', 'extension': 'sup'} -} def getUnmuxSequence(trackDescriptor: TrackDescriptor, sourcePath, targetPrefix, targetDirectory = ''): - trackCodec = trackDescriptor.getCodec() - - if not trackCodec in CODEC_LOOKUP_TABLE.keys(): - return [] - # executable and input file commandTokens = FfxController.COMMAND_TOKENS + ['-i', sourcePath] trackType = trackDescriptor.getType() - + targetPathBase = os.path.join(targetDirectory, targetPrefix) if targetDirectory else targetPrefix # mapping @@ -134,14 +122,15 @@ def getUnmuxSequence(trackDescriptor: TrackDescriptor, sourcePath, targetPrefix, '-c', 'copy'] - # TODO #425: Codec Enum + trackCodec = trackDescriptor.getCodec() + # output format - if 'format' in CODEC_LOOKUP_TABLE[trackCodec].keys(): - commandTokens += ['-f', CODEC_LOOKUP_TABLE[trackCodec]['format']] - - # TODO #425: Codec enum + codecFormat = trackCodec.format() + if codecFormat is not None: + commandTokens += ['-f', codecFormat] + # output filename - commandTokens += [f"{targetPathBase}.{CODEC_LOOKUP_TABLE[trackCodec]['extension']}"] + commandTokens += [f"{targetPathBase}.{trackCodec.extension()}"] return commandTokens @@ -204,7 +193,7 @@ def unmux(ctx, if not ctx.obj['dry_run']: #TODO #425: Codec Enum - ctx.obj['logger'].info(f"Unmuxing stream {trackDescriptor.getIndex()} into file {targetPrefix}.{CODEC_LOOKUP_TABLE[trackDescriptor.getCodec()]['extension']}") + ctx.obj['logger'].info(f"Unmuxing stream {trackDescriptor.getIndex()} into file {targetPrefix}.{trackDescriptor.getCodec().extension()}") ctx.obj['logger'].debug(f"Executing unmuxing sequence") @@ -212,7 +201,7 @@ def unmux(ctx, if rc: ctx.obj['logger'].error(f"Unmuxing of stream {trackDescriptor.getIndex()} failed with error ({rc}) {err}") else: - ctx.obj['logger'].warning(f"Skipping stream with unknown codec {trackDescriptor.getCodec()}") + ctx.obj['logger'].warning(f"Skipping stream with unknown codec") except Exception as ex: ctx.obj['logger'].warning(f"Skipping File {sourcePath} ({ex})") diff --git a/src/ffx/ffx_controller.py b/src/ffx/ffx_controller.py index 0bd0f75..4095b71 100644 --- a/src/ffx/ffx_controller.py +++ b/src/ffx/ffx_controller.py @@ -7,6 +7,7 @@ from ffx.track_type import TrackType from ffx.video_encoder import VideoEncoder from ffx.process import executeProcess from ffx.track_disposition import TrackDisposition +from ffx.track_codec import TrackCodec from ffx.constants import DEFAULT_CROP_START, DEFAULT_CROP_LENGTH @@ -163,7 +164,7 @@ class FfxController(): #HINT: No dispositions for pgs subtitle tracks that have no external file source if (td.getExternalSourceFilePath() - or td.getCodec() != TrackDescriptor.CODEC_PGS): + or td.getCodec() != TrackCodec.PGS): subIndex = td.getSubIndex() streamIndicator = td.getType().indicator() diff --git a/src/ffx/media_descriptor.py b/src/ffx/media_descriptor.py index c8b4ca2..d47029c 100644 --- a/src/ffx/media_descriptor.py +++ b/src/ffx/media_descriptor.py @@ -6,6 +6,7 @@ from ffx.track_type import TrackType from ffx.iso_language import IsoLanguage from ffx.track_disposition import TrackDisposition +from ffx.track_codec import TrackCodec from ffx.track_descriptor import TrackDescriptor @@ -446,14 +447,14 @@ class MediaDescriptor: else: - if td.getCodec() != TrackDescriptor.CODEC_PGS: + if td.getCodec() != TrackCodec.PGS: inputMappingTokens += [ "-map", f"0:{trackType.indicator()}:{stdsi}", ] else: - if td.getCodec() != TrackDescriptor.CODEC_PGS: + if td.getCodec() != TrackCodec.PGS: inputMappingTokens += ["-map", f"0:{stdi}"] return inputMappingTokens diff --git a/src/ffx/media_details_screen.py b/src/ffx/media_details_screen.py index 8dc7fcc..e84881e 100644 --- a/src/ffx/media_details_screen.py +++ b/src/ffx/media_details_screen.py @@ -308,7 +308,7 @@ class MediaDetailsScreen(Screen): row = (td.getIndex(), trackType.label(), typeCounter[trackType], - td.getCodec(), + td.getCodec().label(), audioLayout.label() if trackType == TrackType.AUDIO and audioLayout != AudioLayout.LAYOUT_UNDEFINED else ' ', td.getLanguage().label(), diff --git a/src/ffx/model/track.py b/src/ffx/model/track.py index db24343..485e7b1 100644 --- a/src/ffx/model/track.py +++ b/src/ffx/model/track.py @@ -12,8 +12,8 @@ from ffx.track_disposition import TrackDisposition from ffx.track_descriptor import TrackDescriptor from ffx.audio_layout import AudioLayout +from ffx.track_codec import TrackCodec -import click class Track(Base): """ @@ -152,8 +152,8 @@ class Track(Base): def getType(self): return TrackType.fromIndex(self.track_type) - def getCodec(self): - return self.codec_name + def getCodec(self) -> TrackCodec: + return TrackCodec.identify(self.codec_name) def getIndex(self): return int(self.index) if self.index is not None else -1 @@ -206,7 +206,7 @@ class Track(Base): kwargs[TrackDescriptor.SUB_INDEX_KEY] = subIndex kwargs[TrackDescriptor.TRACK_TYPE_KEY] = self.getType() - kwargs[TrackDescriptor.CODEC_NAME_KEY] = self.getCodec() + kwargs[TrackDescriptor.CODEC_KEY] = self.getCodec() kwargs[TrackDescriptor.DISPOSITION_SET_KEY] = self.getDispositionSet() kwargs[TrackDescriptor.TAGS_KEY] = self.getTags() diff --git a/src/ffx/pattern_details_screen.py b/src/ffx/pattern_details_screen.py index 4e951a6..d1e4e79 100644 --- a/src/ffx/pattern_details_screen.py +++ b/src/ffx/pattern_details_screen.py @@ -158,7 +158,7 @@ class PatternDetailsScreen(Screen): row = (td.getIndex(), trackType.label(), typeCounter[trackType], - td.getCodec(), + td.getCodec().label(), audioLayout.label() if trackType == TrackType.AUDIO and audioLayout != AudioLayout.LAYOUT_UNDEFINED else ' ', trackLanguage.label() if trackLanguage != IsoLanguage.UNDEFINED else ' ', diff --git a/src/ffx/track_codec.py b/src/ffx/track_codec.py new file mode 100644 index 0000000..95fcb85 --- /dev/null +++ b/src/ffx/track_codec.py @@ -0,0 +1,39 @@ +from enum import Enum + + +class TrackCodec(Enum): + + H265 = {'identifier': 'hevc', 'format': 'h265', 'extension': 'h265' ,'label': 'H.265'} + H264 = {'identifier': 'h264', 'format': 'h264', 'extension': 'h264' ,'label': 'H.264'} + AAC = {'identifier': 'aac', 'format': None, 'extension': 'aac' , 'label': 'AAC'} + AC3 = {'identifier': 'ac3', 'format': 'ac3', 'extension': 'ac3' , 'label': 'AC3'} + DTS = {'identifier': 'dts', 'format': 'dts', 'extension': 'dts' , 'label': 'DTS'} + ASS = {'identifier': 'ass', 'format': 'ass', 'extension': 'ass' , 'label': 'ASS'} + PGS = {'identifier': 'hdmv_pgs_subtitle', 'format': 'sup', 'extension': 'sup' , 'label': 'PGS'} + + UNKNOWN = {'identifier': 'unknown', 'format': None, 'extension': None, 'label': 'UNKNOWN'} + + + def identifier(self): + """Returns the codec identifier""" + return str(self.value['identifier']) + + def label(self): + """Returns the codec as string""" + return str(self.value['label']) + + def format(self): + """Returns the codec as single letter""" + return str(self.value['format']) + + def extension(self): + """Returns the corresponding extension""" + return int(self.value['extension']) + + @staticmethod + def identify(identifier: str): + clist = [c for c in TrackCodec if c.value['identifier'] == str(identifier)] + if clist: + return clist[0] + else: + return TrackCodec.UNKNOWN diff --git a/src/ffx/track_controller.py b/src/ffx/track_controller.py index 54b1c6c..620445d 100644 --- a/src/ffx/track_controller.py +++ b/src/ffx/track_controller.py @@ -29,7 +29,7 @@ class TrackController(): s = self.Session() track = Track(pattern_id = patId, track_type = int(trackDescriptor.getType().index()), - codec_name = str(trackDescriptor.getCodec()), + codec_name = str(trackDescriptor.getCodec().label()), index = int(trackDescriptor.getIndex()), source_index = int(trackDescriptor.getSourceIndex()), disposition_flags = int(TrackDisposition.toFlags(trackDescriptor.getDispositionSet())), @@ -68,7 +68,7 @@ class TrackController(): track.index = int(trackDescriptor.getIndex()) track.track_type = int(trackDescriptor.getType().index()) - track.codec_name = str(trackDescriptor.getCodec()) + track.codec_name = str(trackDescriptor.getCodec().identifier()) track.audio_layout = int(trackDescriptor.getAudioLayout().index()) track.disposition_flags = int(TrackDisposition.toFlags(trackDescriptor.getDispositionSet())) diff --git a/src/ffx/track_descriptor.py b/src/ffx/track_descriptor.py index a8b96cb..633897e 100644 --- a/src/ffx/track_descriptor.py +++ b/src/ffx/track_descriptor.py @@ -5,6 +5,7 @@ from .iso_language import IsoLanguage from .track_type import TrackType from .audio_layout import AudioLayout from .track_disposition import TrackDisposition +from .track_codec import TrackCodec from .helper import dictDiff, setDiff @@ -24,14 +25,14 @@ class TrackDescriptor: TAGS_KEY = "tags" TRACK_TYPE_KEY = "track_type" - CODEC_NAME_KEY = "codec_name" + CODEC_KEY = "codec_name" AUDIO_LAYOUT_KEY = "audio_layout" FFPROBE_INDEX_KEY = "index" FFPROBE_DISPOSITION_KEY = "disposition" FFPROBE_TAGS_KEY = "tags" FFPROBE_CODEC_TYPE_KEY = "codec_type" - FFPROBE_CODEC_NAME_KEY = "codec_name" + FFPROBE_CODEC_KEY = "codec_name" CODEC_PGS = 'hdmv_pgs_subtitle' @@ -110,14 +111,14 @@ class TrackDescriptor: else: self.__trackType = TrackType.UNKNOWN - if TrackDescriptor.CODEC_NAME_KEY in kwargs.keys(): - if type(kwargs[TrackDescriptor.CODEC_NAME_KEY]) is not str: + if TrackDescriptor.CODEC_KEY in kwargs.keys(): + if type(kwargs[TrackDescriptor.CODEC_KEY]) is not TrackCodec: raise TypeError( - f"TrackDesciptor.__init__(): Argument {TrackDescriptor.CODEC_NAME_KEY} is required to be of type str" + f"TrackDesciptor.__init__(): Argument {TrackDescriptor.CODEC_KEY} is required to be of type TrackCodec" ) - self.__codecName = kwargs[TrackDescriptor.CODEC_NAME_KEY] + self.__trackCodec = kwargs[TrackDescriptor.CODEC_KEY] else: - self.__codecName = '' + self.__trackCodec = TrackCodec.UNKNOWN if TrackDescriptor.TAGS_KEY in kwargs.keys(): if type(kwargs[TrackDescriptor.TAGS_KEY]) is not dict: @@ -214,7 +215,8 @@ class TrackDescriptor: kwargs[TrackDescriptor.SUB_INDEX_KEY] = subIndex kwargs[TrackDescriptor.TRACK_TYPE_KEY] = trackType - kwargs[TrackDescriptor.CODEC_NAME_KEY] = str(streamObj[TrackDescriptor.FFPROBE_CODEC_NAME_KEY]) + + kwargs[TrackDescriptor.CODEC_KEY] = TrackCodec.identify(streamObj[TrackDescriptor.FFPROBE_CODEC_KEY]) kwargs[TrackDescriptor.DISPOSITION_SET_KEY] = ( { @@ -272,9 +274,9 @@ class TrackDescriptor: def getType(self): return self.__trackType - - def getCodec(self): - return str(self.__codecName) + + def getCodec(self) -> TrackCodec: + return self.__trackCodec def getLanguage(self): if "language" in self.__trackTags.keys():