|
|
@ -11,10 +11,13 @@ from ffx.tmdb_controller import TmdbController
|
|
|
|
|
|
|
|
|
|
|
|
from ffx.database import databaseContext
|
|
|
|
from ffx.database import databaseContext
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
from ffx.track_descriptor import TrackDescriptor
|
|
|
|
from ffx.track_type import TrackType
|
|
|
|
from ffx.track_type import TrackType
|
|
|
|
from ffx.video_encoder import VideoEncoder
|
|
|
|
from ffx.video_encoder import VideoEncoder
|
|
|
|
from ffx.track_disposition import TrackDisposition
|
|
|
|
from ffx.track_disposition import TrackDisposition
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
from ffx.process import executeProcess
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
VERSION='0.1.2'
|
|
|
|
VERSION='0.1.2'
|
|
|
|
|
|
|
|
|
|
|
@ -60,53 +63,95 @@ def inspect(ctx, filename):
|
|
|
|
app = FfxApp(ctx.obj)
|
|
|
|
app = FfxApp(ctx.obj)
|
|
|
|
app.run()
|
|
|
|
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 []
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
commandTokens = FfxController.COMMAND_TOKENS + ['-i', sourcePath]
|
|
|
|
|
|
|
|
trackType = trackDescriptor.getType()
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
targetPathBase = os.path.join(targetDirectory, targetPrefix) if targetDirectory else targetPrefix
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
commandTokens += ['-map',
|
|
|
|
|
|
|
|
f"0:{trackType.indicator()}:{trackDescriptor.getSubIndex()}",
|
|
|
|
|
|
|
|
'-c',
|
|
|
|
|
|
|
|
'copy']
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
if 'format' in CODEC_LOOKUP_TABLE[trackCodec].keys():
|
|
|
|
|
|
|
|
commandTokens += ['-f', CODEC_LOOKUP_TABLE[trackCodec]['format']]
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
commandTokens += [f"{targetPathBase}.{CODEC_LOOKUP_TABLE[trackCodec]['extension']}"]
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
return commandTokens
|
|
|
|
|
|
|
|
|
|
|
|
# @ffx.command()
|
|
|
|
|
|
|
|
# @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')
|
|
|
|
|
|
|
|
#
|
|
|
|
|
|
|
|
# @click.option("-o", "--output-directory", type=str, default='')
|
|
|
|
|
|
|
|
#
|
|
|
|
|
|
|
|
# @click.option("--dry-run", is_flag=True, default=False)
|
|
|
|
|
|
|
|
#
|
|
|
|
|
|
|
|
#
|
|
|
|
|
|
|
|
# def unmux(ctx,
|
|
|
|
|
|
|
|
# label,
|
|
|
|
|
|
|
|
# paths,
|
|
|
|
|
|
|
|
# subtitle_directory,
|
|
|
|
|
|
|
|
# subtitle_prefix,
|
|
|
|
|
|
|
|
# output_directory,
|
|
|
|
|
|
|
|
# dry_run):
|
|
|
|
|
|
|
|
#
|
|
|
|
|
|
|
|
# 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")
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
@ffx.command()
|
|
|
|
|
|
|
|
@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("-o", "--output-directory", type=str, default='')
|
|
|
|
|
|
|
|
@click.option("-s", "--subtitles-only", is_flag=True, default=False)
|
|
|
|
|
|
|
|
@click.option("--dry-run", is_flag=True, default=False)
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
def unmux(ctx,
|
|
|
|
|
|
|
|
paths,
|
|
|
|
|
|
|
|
label,
|
|
|
|
|
|
|
|
output_directory,
|
|
|
|
|
|
|
|
subtitles_only,
|
|
|
|
|
|
|
|
dry_run):
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
existingSourcePaths = [p for p in paths if os.path.isfile(p)]
|
|
|
|
|
|
|
|
click.echo(f"\nUnmuxing {len(existingSourcePaths)} files")
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
for sourcePath in existingSourcePaths:
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
fp = FileProperties(ctx.obj, sourcePath)
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
print(f"\nFile {sourcePath}\n")
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
try:
|
|
|
|
|
|
|
|
sourceMediaDescriptor = fp.getMediaDescriptor()
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
for trackDescriptor in sourceMediaDescriptor.getAllTrackDescriptors():
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
if trackDescriptor.getType() == TrackType.SUBTITLE or not subtitles_only:
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
season = fp.getSeason()
|
|
|
|
|
|
|
|
episode = fp.getEpisode()
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
targetLabel = label if label else fp.getFileBasename()
|
|
|
|
|
|
|
|
targetIndicator = f"_S{season}E{episode}" if label and season != -1 and episode != -1 else ''
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
# SEASON_EPISODE_STREAM_LANGUAGE_MATCH = '[sS]([0-9]+)[eE]([0-9]+)_([0-9]+)_([a-z]{3})'
|
|
|
|
|
|
|
|
targetPrefix = f"{targetLabel}{targetIndicator}_{trackDescriptor.getIndex()}_{trackDescriptor.getLanguage().threeLetter()}"
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
unmuxSequence = getUnmuxSequence(trackDescriptor, sourcePath, targetPrefix, targetDirectory = output_directory)
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
if unmuxSequence:
|
|
|
|
|
|
|
|
if not dry_run:
|
|
|
|
|
|
|
|
click.echo(f"Executing unmuxing sequence: {' '.join(unmuxSequence)}")
|
|
|
|
|
|
|
|
out, err, rc = executeProcess(unmuxSequence)
|
|
|
|
|
|
|
|
if rc:
|
|
|
|
|
|
|
|
click.echo(f"Unmuxing of stream {trackDescriptor.getIndex()} failed with error ({rc}) {err}")
|
|
|
|
|
|
|
|
else:
|
|
|
|
|
|
|
|
click.echo(f"Skipping stream with unknown codec {trackDescriptor.getCodec()}")
|
|
|
|
|
|
|
|
except Exception as ex:
|
|
|
|
|
|
|
|
click.echo(f"Skipping File {sourcePath} ({ex})")
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
@ffx.command()
|
|
|
|
@ffx.command()
|
|
|
|
@click.pass_context
|
|
|
|
@click.pass_context
|
|
|
|