diff --git a/bin/ffx.py b/bin/ffx.py index c66056b..aa2be95 100755 --- a/bin/ffx.py +++ b/bin/ffx.py @@ -138,29 +138,31 @@ def getStreamDescriptor(filename): for subStream in streamData: - if not 'disposition' in subStream.keys(): - subStream['disposition'] = {} - if not 'default' in subStream['disposition'].keys(): - subStream['disposition']['default'] = 0 - if not 'forced' in subStream['disposition'].keys(): - subStream['disposition']['forced'] = 0 - if not 'tags' in subStream.keys(): - subStream['tags'] = {} - if not 'language' in subStream['tags'].keys(): - subStream['tags']['language'] = 'undefined' - if not 'title' in subStream['tags'].keys(): - subStream['tags']['title'] = 'undefined' - - if subStream['codec_type'] == STREAM_TYPE_AUDIO: - if 'channel_layout' in subStream.keys(): - subStream['audio_layout'] = subStream['channel_layout'] - elif subStream['channels'] == 6: - subStream['audio_layout'] = STREAM_LAYOUT_6CH - else: - subStream['audio_layout'] = 'undefined' - - descriptor[subStream['codec_type']].append(subStream) - descriptor[subStream['codec_type']][-1]['sub_index'] = len(descriptor[subStream['codec_type']]) - 1 + if subStream['codec_type'] in ['video', 'audio', 'subtitle']: + + if not 'disposition' in subStream.keys(): + subStream['disposition'] = {} + if not 'default' in subStream['disposition'].keys(): + subStream['disposition']['default'] = 0 + if not 'forced' in subStream['disposition'].keys(): + subStream['disposition']['forced'] = 0 + if not 'tags' in subStream.keys(): + subStream['tags'] = {} + if not 'language' in subStream['tags'].keys(): + subStream['tags']['language'] = 'undefined' + if not 'title' in subStream['tags'].keys(): + subStream['tags']['title'] = 'undefined' + + if subStream['codec_type'] == STREAM_TYPE_AUDIO: + if 'channel_layout' in subStream.keys(): + subStream['audio_layout'] = subStream['channel_layout'] + elif subStream['channels'] == 6: + subStream['audio_layout'] = STREAM_LAYOUT_6CH + else: + subStream['audio_layout'] = 'undefined' + + descriptor[subStream['codec_type']].append(subStream) + descriptor[subStream['codec_type']][-1]['sub_index'] = len(descriptor[subStream['codec_type']]) - 1 return descriptor @@ -366,6 +368,7 @@ def streams(filename): @click.pass_context @click.argument('paths', nargs=-1) +@click.option('-l', '--label', type=str, default='', help='Label to be used as filename prefix') @click.option('-sd', '--subtitle-directory', type=str, default='', help='Load subtitles from here') @click.option('-sp', '--subtitle-prefix', type=str, default='', help='Subtitle filename prefix') @@ -376,12 +379,33 @@ def streams(filename): def unmux(ctx, + label, paths, subtitle_directory, subtitle_prefix, output_directory, dry_run): - pass + + existingSourcePaths = [p for p in paths if os.path.isfile(p)] + click.echo(f"\nUnmuxing {len(existingSourcePaths)} files") + + for sourcePath in existingSourcePaths: + + sd = getStreamDescriptor(sourcePath) + + print(f"\nFile {sourcePath}\n") + + for v in sd['video']: + + if v['codec_name'] == 'h264': + + commandSequence = ['ffmpeg', '-i', sourcePath, '-map', '0:v:0', '-c', 'copy', '-f', 'h264'] + executeProcess() + + for a in sd['audio']: + print(f"A: {a}\n") + for s in sd['subtitle']: + print(f"S: {s}\n") @@ -544,6 +568,9 @@ def convert(ctx, for sourcePath in existingSourcePaths: + ### + ### + # Separate basedir, basename and extension for current source file sourceDirectory = os.path.dirname(sourcePath) sourceFilename = os.path.basename(sourcePath) @@ -601,6 +628,8 @@ def convert(ctx, else: targetFilenameTokens = [sourceFileBasename] + ### + ### # Load source stream descriptor try: diff --git a/bin/ffx/filename_controller.py b/bin/ffx/filename_controller.py new file mode 100644 index 0000000..f70c221 --- /dev/null +++ b/bin/ffx/filename_controller.py @@ -0,0 +1,71 @@ +import os, re, click + +class FilenameController(): + + FILE_EXTENSIONS = ['mkv', 'mp4', 'avi', 'flv', 'webm'] + + SEASON_EPISODE_INDICATOR_MATCH = '[sS]([0-9]+)[eE]([0-9]+)' + EPISODE_INDICATOR_MATCH = '[eE]([0-9]+)' + + def ___init__(self, sourcePath, ): + + + # Separate basedir, basename and extension for current source file + self.__sourceDirectory = os.path.dirname(sourcePath) + self.__sourceFilename = os.path.basename(sourcePath) + sourcePathTokens = self.__sourceFilename.split('.') + + if sourcePathTokens[-1] in FilenameController.FILE_EXTENSIONS: + self.__sourceFileBasename = '.'.join(sourcePathTokens[:-1]) + self.__sourceFilenameExtension = sourcePathTokens[-1] + else: + self.__sourceFileBasename = self.__sourceFilename + self.__sourceFilenameExtension = '' + + + # Determine season and episode if present in current filename + season_digits = 2 + episode_digits = 2 + index_digits = 3 + + se_match = re.compile(FilenameController.SEASON_EPISODE_INDICATOR_MATCH) + e_match = re.compile(FilenameController.EPISODE_INDICATOR_MATCH) + + se_result = se_match.search(self.__sourceFilename) + e_result = e_match.search(self.__sourceFilename) + + self.__season = -1 + self.__episode = -1 + file_index = 0 + + if se_result is not None: + self.__season = int(se_result.group(1)) + self.__episode = int(se_result.group(2)) + elif e_result is not None: + self.__episode = int(e_result.group(1)) + else: + file_index += 1 + + + + matchingFileSubtitleDescriptors = sorted([d for d in availableFileSubtitleDescriptors if d['season'] == season and d['episode'] == episode], key=lambda d: d['stream']) if availableFileSubtitleDescriptors else [] + + print(f"season={season} episode={episode} file={file_index}") + + + # Assemble target filename tokens + targetFilenameTokens = [] + targetFilenameExtension = DEFAULT_FILE_EXTENSION + + if label: + targetFilenameTokens = [label] + + if season > -1 and episode > -1: + targetFilenameTokens += [f"S{season:0{season_digits}d}E{episode:0{episode_digits}d}"] + elif episode > -1: + targetFilenameTokens += [f"E{episode:0{episode_digits}d}"] + else: + targetFilenameTokens += [f"{file_index:0{index_digits}d}"] + + else: + targetFilenameTokens = [sourceFileBasename]