Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Sickbeard-mp4-automator merge #54

Open
wants to merge 10 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
128 changes: 79 additions & 49 deletions converter/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -50,6 +50,11 @@ def parse_options(self, opt, twopass=None):
"""
Parse format/codec options and prepare raw ffmpeg option list.
"""
format_options = None
audio_options = []
video_options = []
subtitle_options = []

if not isinstance(opt, dict):
raise ConverterError('Invalid output specification')

Expand All @@ -64,66 +69,91 @@ def parse_options(self, opt, twopass=None):
if format_options is None:
raise ConverterError('Unknown container format error')

if 'audio' not in opt and 'video' not in opt:
raise ConverterError('Neither audio nor video streams requested')
if 'audio' not in opt and 'video' not in opt and 'subtitle' not in opt:
raise ConverterError('Neither audio nor video nor subtitle streams requested')

# audio options
if 'audio' not in opt or twopass == 1:
opt_audio = {'codec': None}
else:
opt_audio = opt['audio']
if not isinstance(opt_audio, dict) or 'codec' not in opt_audio:
if 'audio' not in opt:
opt['audio'] = {'codec': None}

if 'subtitle' not in opt:
opt['subtitle'] = {'codec': None}

# Audio
y = opt['audio']

# Creates the new nested dictionary to preserve backwards compatability
try:
first = list(y.values())[0]
if not isinstance(first, dict):
y = {0: y}
except IndexError:
pass

for n in y:
x = y[n]

if not isinstance(x, dict) or 'codec' not in x:
raise ConverterError('Invalid audio codec specification')

c = opt_audio['codec']
if c not in self.audio_codecs:
raise ConverterError('Requested unknown audio codec ' + str(c))
if 'path' in x and 'source' not in x:
raise ConverterError('Cannot specify audio path without FFMPEG source number')

audio_options = self.audio_codecs[c]().parse_options(opt_audio)
if audio_options is None:
raise ConverterError('Unknown audio codec error')
if 'source' in x and 'path' not in x:
raise ConverterError('Cannot specify alternate input source without a path')

# video options
if 'video' not in opt:
opt_video = {'codec': None}
else:
opt_video = opt['video']
if not isinstance(opt_video, dict) or 'codec' not in opt_video:
raise ConverterError('Invalid video codec specification')
c = x['codec']
if c not in self.audio_codecs:
raise ConverterError('Requested unknown audio codec ' + str(c))

c = opt_video['codec']
if c not in self.video_codecs:
raise ConverterError('Requested unknown video codec ' + str(c))
audio_options.extend(self.audio_codecs[c]().parse_options(x, n))
if audio_options is None:
raise ConverterError('Unknown audio codec error')

video_options = self.video_codecs[c]().parse_options(opt_video)
if video_options is None:
raise ConverterError('Unknown video codec error')
# Subtitle
y = opt['subtitle']

if 'subtitle' not in opt:
opt_subtitle = {'codec': None}
else:
opt_subtitle = opt['subtitle']
if not isinstance(opt_subtitle, dict) or 'codec' not in opt_subtitle:
# Creates the new nested dictionary to preserve backwards compatability
try:
first = list(y.values())[0]
if not isinstance(first, dict):
y = {0: y}
except IndexError:
pass

for n in y:
x = y[n]
if not isinstance(x, dict) or 'codec' not in x:
raise ConverterError('Invalid subtitle codec specification')

c = opt_subtitle['codec']
if c not in self.subtitle_codecs:
raise ConverterError('Requested unknown subtitle codec ' + str(c))
if 'path' in x and 'source' not in x:
raise ConverterError('Cannot specify subtitle path without FFMPEG source number')

subtitle_options = self.subtitle_codecs[c]().parse_options(opt_subtitle)
if subtitle_options is None:
raise ConverterError('Unknown subtitle codec error')
if 'source' in x and 'path' not in x:
raise ConverterError('Cannot specify alternate input source without a path')

c = x['codec']
if c not in self.subtitle_codecs:
raise ConverterError('Requested unknown subtitle codec ' + str(c))

subtitle_options.extend(self.subtitle_codecs[c]().parse_options(x, n))
if subtitle_options is None:
raise ConverterError('Unknown subtitle codec error')

if 'video' in opt:
x = opt['video']
if not isinstance(x, dict) or 'codec' not in x:
raise ConverterError('Invalid video codec specification')

if 'map' in opt:
m = opt['map']
if not type(m) == int:
raise ConverterError('map needs to be int')
else:
format_options.extend(['-map', str(m)])
c = x['codec']
if c not in self.video_codecs:
raise ConverterError('Requested unknown video codec ' + str(c))

video_options = self.video_codecs[c]().parse_options(x)
if video_options is None:
raise ConverterError('Unknown video codec error')

# aggregate all options
optlist = audio_options + video_options + subtitle_options + format_options
optlist = video_options + audio_options + subtitle_options + format_options

if twopass == 1:
optlist.extend(['-pass', '1'])
Expand All @@ -132,7 +162,7 @@ def parse_options(self, opt, twopass=None):

return optlist

def convert(self, infile, outfile, options, twopass=False, timeout=10):
def convert(self, infile, outfile, options, twopass=False, timeout=10, preopts=None, postopts=None):
"""
Convert media file (infile) according to specified options, and
save it to outfile. For two-pass encoding, specify the pass (1 or 2)
Expand Down Expand Up @@ -200,17 +230,17 @@ def convert(self, infile, outfile, options, twopass=False, timeout=10):
if twopass:
optlist1 = self.parse_options(options, 1)
for timecode in self.ffmpeg.convert(infile, outfile, optlist1,
timeout=timeout):
timeout=timeout, preopts=preopts, postopts=postopts):
yield int((50.0 * timecode) / info.format.duration)

optlist2 = self.parse_options(options, 2)
for timecode in self.ffmpeg.convert(infile, outfile, optlist2,
timeout=timeout):
timeout=timeout, preopts=preopts, postopts=postopts):
yield int(50.0 + (50.0 * timecode) / info.format.duration)
else:
optlist = self.parse_options(options, twopass)
for timecode in self.ffmpeg.convert(infile, outfile, optlist,
timeout=timeout):
timeout=timeout, preopts=preopts, postopts=postopts):
yield int((100.0 * timecode) / info.format.duration)

def probe(self, fname, posters_as_video=True):
Expand Down
Loading