• Deleted leftover development debugging output.
• Added code to resize frame inputs to the size of the smallest video segment where applicable (closes #23). Still need to add resizing for differently sized video inputs.
1 parent 923c1e9 commit a03a17fe8eb10a7c795e979314c40fffd4ab0afc
Nigel Stanger authored on 20 Sep 2016
Showing 3 changed files
View
58
process_podcast.py
cnf["num"], cnf["times"])
return segments
 
 
def process_frame_segments(args, segments):
def smallest_video_dimensions(args, segments):
"""Compute the smallest frame dimensions across all video inputs."""
fn = "smallest_video_dimensions"
width = 2048
height = 1536
for s in segments:
if isinstance(s, FrameSegment):
continue
command = FFprobeCommand([s.input_file])
globals.log.debug("{fn}(): {cmd}".format(fn=fn, cmd=command))
w, h = command.get_entries(find_list=["width", "height"])
if (w * h) < (width * height):
width, height = w, h
return width, height
 
 
def process_frame_segments(args, segments, width, height):
"""Post-process frame segments to set frame images, etc."""
fn = "process_frame_segments"
globals.log.info("Processing frames...")
frame_segments = [s for s in segments if isinstance(s, FrameSegment)]
if (f.segment_number > 0):
prev = segments[f.segment_number - 1]
globals.log.debug(
"{fn}(): prev = {p}".format(fn=fn, p=prev))
prev.generate_temp_file(args.output)
prev.generate_temp_file(args.output, width=width,
height=height)
f.use_frame(
prev.generate_frame(f.frame_number, args.output))
prev.generate_frame(f.frame_number, args.output,
width=width, height=height))
else:
globals.log.error(
"frame segment {s} is attempting to use the last "
"frame of a non-existent previous "
# Frame segments whose frame comes from a PDF file.
else:
_, suffix = os.path.splitext(f.input_file)
if (suffix.lower() == ".pdf"):
f.use_frame(f.generate_temp_file(args.output))
f.use_frame(f.generate_temp_file(args.output, width=width,
height=height))
else:
globals.log.error(
'unexpected input file type "{s}" for frame segment '
"{f}".format(s=suffix, f=f.segment_number))
if (audio_duration != video_duration):
globals.log.warning("total video duration ({v}s) doesn't match "
"total audio duration "
"({a}s)".format(v=video_duration, a=audio_duration))
process_frame_segments(args, segments)
width, height = smallest_video_dimensions(args, video_segments)
globals.log.debug("{fn}(): width = {w}, height = "
"{h}".format(fn=fn, w=width, h=height))
process_frame_segments(args, segments, width, height)
globals.log.debug("{fn}(): input files = "
"{i}".format(fn=fn, i=Segment.input_files()))
View
20
segment.py
t=self._TYPE, o=os.path.splitext(output)[0],
n=self.segment_number),
suffix])
def generate_temp_file(self, output):
def generate_temp_file(self, output, width=0, height=0):
"""Compile the segment from the original source file(s)."""
# Note: width and height are currently ignored for segments
# in general. This may (or may not) need to change if there
# are multiple inputs of different dimensions.
fn = "generate_temp_file"
self._temp_file = self.generate_temp_filename(output)
command = FFmpegCommand(
input_options=self._input_options + ["-codec", "copy"],
raise SegmentException(
"Can't get last frame of {s} because it has no temporary "
"file".format(s=self))
def generate_frame(self, frame_number, output):
def generate_frame(self, frame_number, output, width=2048, height=1536):
"""Create a JPEG file from the specified frame of the segment."""
# Note: width and height are currently ignored for video
# segments. This will need to change if there are multiple
# video inputs of different dimensions.
fn = "generate_frame"
temp_frame = self.generate_temp_filename(output, suffix="jpg")
if (frame_number == -1):
frame_number = self.get_last_frame_number()
i=self.punch_in,
o=self.punch_out,
fn=self.frame_number))
def generate_temp_file(self, output):
def generate_temp_file(self, output, width=2048, height=1536):
"""Compile the segment from the original source file(s)."""
fn = "generate_temp_file"
self._temp_file = self.generate_temp_filename(output, suffix="jpg")
command = ConvertCommand(
input_options=["{f}[{n}]".format(f=self.input_file,
n=self.frame_number)],
output_options=["{f}".format(f=self._temp_file)])
input_options=["{f}[{n}]".format(
f=self.input_file, n=self.frame_number)],
output_options=["{f}".format(f=self._temp_file)],
width=width, height=height)
globals.log.debug("{cls}.{fn}(): {cmd}".format(
cls=self.__class__.__name__, fn=fn, cmd=command))
if (command.run() == 0):
self._temp_files_list.append(self._temp_file)
View
8
shell_command.py
class ConvertCommand(ShellCommand):
"""An ImageMagick convert command."""
_executable = distutils.spawn.find_executable("convert")
_base_options = ["-density", "600",
"-size", "2048x1536",
"xc:dimgrey", "null:", # dark grey background
"("]
def __init__(self, input_options=[], output_options=[]):
def __init__(self, input_options=[], output_options=[], width=2048, height=1536):
super(ConvertCommand, self).__init__(input_options, output_options)
self._base_options = (["-size", "{w}x{h}".format(w=width, h=height)] +
self._base_options)
self.append_input_options(
["-resize", "2048x1536",
["-resize", "{w}x{h}".format(w=width, h=height),
"-background", "white",
"-alpha", "remove",
"-type", "truecolor", # force RGB (this and next line)
"-define", "colorspace:auto-grayscale=off"])
# Re-fetch if the file's changed since we last looked.
modified = os.path.getmtime(self.input_options[-1])
if (not self.entries) or (modified > self.last_modified):
js = json.loads(self.get_output())
print js
self.entries = {"format": js["format"], "stream": js["streams"][0]}
return [self.entries[section][f] for f in find_list]