made ffmpeg arguments customizable, added support for different frame formats

This commit is contained in:
k4yt3x 2019-03-30 14:02:05 -04:00
parent 78ae2e7ed2
commit d9a19d823e

View File

@ -4,7 +4,7 @@
Name: FFMPEG Class Name: FFMPEG Class
Author: K4YT3X Author: K4YT3X
Date Created: Feb 24, 2018 Date Created: Feb 24, 2018
Last Modified: March 19, 2019 Last Modified: March 30, 2019
Description: This class handles all FFMPEG related Description: This class handles all FFMPEG related
operations. operations.
@ -22,13 +22,9 @@ class Ffmpeg:
and inserting audio tracks to videos. and inserting audio tracks to videos.
""" """
def __init__(self, ffmpeg_settings): def __init__(self, ffmpeg_settings, image_format):
self.ffmpeg_settings = ffmpeg_settings self.ffmpeg_settings = ffmpeg_settings
self._parse_settings()
def _parse_settings(self):
""" Parse ffmpeg settings
"""
self.ffmpeg_path = self.ffmpeg_settings['ffmpeg_path'] self.ffmpeg_path = self.ffmpeg_settings['ffmpeg_path']
# add a forward slash to directory if not present # add a forward slash to directory if not present
# otherwise there will be a format error # otherwise there will be a format error
@ -36,8 +32,8 @@ class Ffmpeg:
self.ffmpeg_path = '{}\\'.format(self.ffmpeg_path) self.ffmpeg_path = '{}\\'.format(self.ffmpeg_path)
self.ffmpeg_binary = '{}ffmpeg.exe'.format(self.ffmpeg_path) self.ffmpeg_binary = '{}ffmpeg.exe'.format(self.ffmpeg_path)
self.ffmpeg_hwaccel = self.ffmpeg_settings['ffmpeg_hwaccel'] self.ffmpeg_probe_binary = '{}ffprobe.exe'.format(self.ffmpeg_path)
self.extra_arguments = self.ffmpeg_settings['extra_arguments'] self.image_format = image_format
def get_video_info(self, input_video): def get_video_info(self, input_video):
""" Gets input video information """ Gets input video information
@ -51,8 +47,11 @@ class Ffmpeg:
Returns: Returns:
dictionary -- JSON text of input video information dictionary -- JSON text of input video information
""" """
# this execution command needs to be hard-coded
# since video2x only strictly recignizes this one format
execute = [ execute = [
'{}ffprobe.exe'.format(self.ffmpeg_path), self.ffmpeg_probe_binary,
'-v', '-v',
'quiet', 'quiet',
'-print_format', '-print_format',
@ -80,14 +79,10 @@ class Ffmpeg:
execute = [ execute = [
self.ffmpeg_binary, self.ffmpeg_binary,
'-i', '-i',
'{}'.format(input_video), input_video,
'{}\\extracted_%0d.png'.format(extracted_frames), '{}\\extracted_%0d.{}'.format(extracted_frames, self.image_format)
'-y'
] ]
execute += self.extra_arguments self._execute(execute=execute, phase='video_to_frames')
Avalon.debug_info('Executing: {}'.format(' '.join(execute)))
subprocess.run(execute, shell=True, check=True)
def convert_video(self, framerate, resolution, upscaled_frames): def convert_video(self, framerate, resolution, upscaled_frames):
"""Converts images into videos """Converts images into videos
@ -104,25 +99,13 @@ class Ffmpeg:
self.ffmpeg_binary, self.ffmpeg_binary,
'-r', '-r',
str(framerate), str(framerate),
'-f',
'image2',
'-s', '-s',
resolution, resolution,
'-i', '-i',
'{}\\extracted_%d.png'.format(upscaled_frames), '{}\\extracted_%d.{}'.format(upscaled_frames, self.image_format),
'-vcodec', '{}\\no_audio.mp4'.format(upscaled_frames)
'libx264',
'-crf',
'25',
'-pix_fmt',
'yuv420p',
'{}\\no_audio.mp4'.format(upscaled_frames),
'-y'
] ]
execute += self.extra_arguments self._execute(execute=execute, phase='frames_to_video')
Avalon.debug_info('Executing: {}'.format(' '.join(execute)))
subprocess.run(execute, shell=True, check=True)
def migrate_audio_tracks_subtitles(self, input_video, output_video, upscaled_frames): def migrate_audio_tracks_subtitles(self, input_video, output_video, upscaled_frames):
""" Migrates audio tracks and subtitles from input video to output video """ Migrates audio tracks and subtitles from input video to output video
@ -137,19 +120,28 @@ class Ffmpeg:
'-i', '-i',
'{}\\no_audio.mp4'.format(upscaled_frames), '{}\\no_audio.mp4'.format(upscaled_frames),
'-i', '-i',
'{}'.format(input_video), input_video,
'-map', output_video
'0:v:0?',
'-map',
'1?',
'-c',
'copy',
'-map',
'-1:v?',
'{}'.format(output_video),
'-y'
] ]
execute += self.extra_arguments self._execute(execute=execute, phase='migrating_tracks')
Avalon.debug_info('Executing: {}'.format(' '.join(execute))) def _execute(self, execute, phase):
subprocess.run(execute, shell=True, check=True)
for key in self.ffmpeg_settings[phase].keys():
value = self.ffmpeg_settings[phase][key]
# null or None means that leave this option out (keep default)
if value is None or value is False:
continue
else:
execute.append(key)
# true means key is an option
if value is True:
continue
execute.append(str(value))
Avalon.debug_info('Executing: {}'.format(execute))
return subprocess.run(execute, shell=True, check=True).returncode