separated creation of ffmpeg command
for future use to sllow editing the command before starting the export
This commit is contained in:
parent
f6fbc8d242
commit
4c3920e630
|
@ -27,6 +27,13 @@ class Component(QtCore.QObject):
|
|||
# change this number to identify new versions of a component
|
||||
return 1
|
||||
|
||||
def properties(self):
|
||||
'''
|
||||
Return a list of properties to signify if your component is
|
||||
non-animated ('static') or returns sound ('audio').
|
||||
'''
|
||||
return []
|
||||
|
||||
def cancel(self):
|
||||
# please stop any lengthy process in response to this variable
|
||||
self.canceled = True
|
||||
|
@ -57,9 +64,6 @@ class Component(QtCore.QObject):
|
|||
self.progressBarSetText = signal to set progress bar text
|
||||
Use the latter two signals to update the MainWindow if needed
|
||||
for a long initialization procedure (i.e., for a visualizer)
|
||||
|
||||
Return a list of properties to signify if your component is
|
||||
non-animated ('static') or returns sound ('audio').
|
||||
'''
|
||||
for var, value in kwargs.items():
|
||||
exec('self.%s = value' % var)
|
||||
|
|
|
@ -117,8 +117,7 @@ class Component(Component):
|
|||
height = int(previewWorker.core.settings.value('outputHeight'))
|
||||
return self.drawFrame(width, height)
|
||||
|
||||
def preFrameRender(self, **kwargs):
|
||||
super().preFrameRender(**kwargs)
|
||||
def properties(self):
|
||||
return ['static']
|
||||
|
||||
def frameRender(self, layerNo, frameNo):
|
||||
|
|
|
@ -46,8 +46,7 @@ class Component(Component):
|
|||
height = int(previewWorker.core.settings.value('outputHeight'))
|
||||
return self.drawFrame(width, height)
|
||||
|
||||
def preFrameRender(self, **kwargs):
|
||||
super().preFrameRender(**kwargs)
|
||||
def properties(self):
|
||||
return ['static']
|
||||
|
||||
def frameRender(self, layerNo, frameNo):
|
||||
|
|
|
@ -31,7 +31,9 @@ class Component(Component):
|
|||
return self.frameRender(self.compPos, 0)
|
||||
|
||||
def preFrameRender(self, **kwargs):
|
||||
# super().preFrameRender(**kwargs)
|
||||
pass
|
||||
|
||||
def properties(self):
|
||||
return ['static', 'audio']
|
||||
|
||||
def audio(self):
|
||||
|
|
|
@ -119,8 +119,7 @@ class Component(Component):
|
|||
height = int(previewWorker.core.settings.value('outputHeight'))
|
||||
return self.addText(width, height)
|
||||
|
||||
def preFrameRender(self, **kwargs):
|
||||
super().preFrameRender(**kwargs)
|
||||
def properties(self):
|
||||
return ['static']
|
||||
|
||||
def frameRender(self, layerNo, frameNo):
|
||||
|
|
93
src/core.py
93
src/core.py
|
@ -460,6 +460,99 @@ class Core:
|
|||
except sp.CalledProcessError:
|
||||
return "avconv"
|
||||
|
||||
def createFfmpegCommand(self, inputFile, outputFile):
|
||||
'''
|
||||
Constructs the major ffmpeg command used to export the video
|
||||
'''
|
||||
|
||||
# Test if user has libfdk_aac
|
||||
encoders = toolkit.checkOutput(
|
||||
"%s -encoders -hide_banner" % self.FFMPEG_BIN, shell=True
|
||||
)
|
||||
encoders = encoders.decode("utf-8")
|
||||
|
||||
acodec = self.settings.value('outputAudioCodec')
|
||||
|
||||
options = self.encoder_options
|
||||
containerName = self.settings.value('outputContainer')
|
||||
vcodec = self.settings.value('outputVideoCodec')
|
||||
vbitrate = str(self.settings.value('outputVideoBitrate'))+'k'
|
||||
acodec = self.settings.value('outputAudioCodec')
|
||||
abitrate = str(self.settings.value('outputAudioBitrate'))+'k'
|
||||
|
||||
for cont in options['containers']:
|
||||
if cont['name'] == containerName:
|
||||
container = cont['container']
|
||||
break
|
||||
|
||||
vencoders = options['video-codecs'][vcodec]
|
||||
aencoders = options['audio-codecs'][acodec]
|
||||
|
||||
for encoder in vencoders:
|
||||
if encoder in encoders:
|
||||
vencoder = encoder
|
||||
break
|
||||
|
||||
for encoder in aencoders:
|
||||
if encoder in encoders:
|
||||
aencoder = encoder
|
||||
break
|
||||
|
||||
ffmpegCommand = [
|
||||
self.FFMPEG_BIN,
|
||||
'-thread_queue_size', '512',
|
||||
'-y', # overwrite the output file if it already exists.
|
||||
|
||||
# INPUT VIDEO
|
||||
'-f', 'rawvideo',
|
||||
'-vcodec', 'rawvideo',
|
||||
'-s', '%sx%s' % (
|
||||
self.settings.value('outputWidth'),
|
||||
self.settings.value('outputHeight'),
|
||||
),
|
||||
'-pix_fmt', 'rgba',
|
||||
'-r', self.settings.value('outputFrameRate'),
|
||||
'-i', '-', # the video input comes from a pipe
|
||||
'-an', # the video input has no sound
|
||||
|
||||
# INPUT SOUND
|
||||
'-i', inputFile
|
||||
]
|
||||
|
||||
extraAudio = [
|
||||
comp.audio() for comp in self.selectedComponents
|
||||
if 'audio' in comp.properties()
|
||||
]
|
||||
if extraAudio:
|
||||
for extraInputFile in extraAudio:
|
||||
ffmpegCommand.extend([
|
||||
'-i', extraInputFile
|
||||
])
|
||||
ffmpegCommand.extend([
|
||||
'-filter_complex',
|
||||
'amix=inputs=%s:duration=longest:dropout_transition=3' % str(
|
||||
len(extraAudio) + 1
|
||||
)
|
||||
])
|
||||
|
||||
ffmpegCommand.extend([
|
||||
# OUTPUT
|
||||
'-vcodec', vencoder,
|
||||
'-acodec', aencoder,
|
||||
'-b:v', vbitrate,
|
||||
'-b:a', abitrate,
|
||||
'-pix_fmt', self.settings.value('outputVideoFormat'),
|
||||
'-preset', self.settings.value('outputPreset'),
|
||||
'-f', container
|
||||
])
|
||||
|
||||
if acodec == 'aac':
|
||||
ffmpegCommand.append('-strict')
|
||||
ffmpegCommand.append('-2')
|
||||
|
||||
ffmpegCommand.append(outputFile)
|
||||
return ffmpegCommand
|
||||
|
||||
def readAudioFile(self, filename, parent):
|
||||
command = [self.FFMPEG_BIN, '-i', filename]
|
||||
|
||||
|
|
|
@ -33,8 +33,8 @@ class Worker(QtCore.QObject):
|
|||
|
||||
def __init__(self, parent=None):
|
||||
QtCore.QObject.__init__(self)
|
||||
self.core = core.Core()
|
||||
self.core.settings = parent.settings
|
||||
self.core = parent.core
|
||||
self.settings = parent.core.settings
|
||||
self.modules = parent.core.modules
|
||||
self.parent = parent
|
||||
parent.videoTask.connect(self.createVideo)
|
||||
|
@ -114,8 +114,8 @@ class Worker(QtCore.QObject):
|
|||
self.components = components
|
||||
self.outputFile = outputFile
|
||||
self.extraAudio = []
|
||||
self.width = int(self.core.settings.value('outputWidth'))
|
||||
self.height = int(self.core.settings.value('outputHeight'))
|
||||
self.width = int(self.settings.value('outputWidth'))
|
||||
self.height = int(self.settings.value('outputHeight'))
|
||||
|
||||
self.compositeQueue = Queue()
|
||||
self.compositeQueue.maxsize = 20
|
||||
|
@ -128,7 +128,7 @@ class Worker(QtCore.QObject):
|
|||
self.progressBarUpdate.emit(progressBarValue)
|
||||
|
||||
# =~=~=~=~=~=~=~=~=~=~=~=~=~=~=~=~=~=~=~==~=~=~=~=~=~=~=~=~=~=~=~=~=~
|
||||
# READ AUDIO AND INITIALIZE COMPONENTS
|
||||
# READ AUDIO, INITIALIZE COMPONENTS, OPEN A PIPE TO FFMPEG
|
||||
# =~=~=~=~=~=~=~=~=~=~=~=~=~=~=~=~=~=~=~==~=~=~=~=~=~=~=~=~=~=~=~=~=~
|
||||
|
||||
self.progressBarSetText.emit("Loading audio file...")
|
||||
|
@ -143,8 +143,7 @@ class Worker(QtCore.QObject):
|
|||
self.staticComponents = {}
|
||||
numComps = len(self.components)
|
||||
for compNo, comp in enumerate(self.components):
|
||||
properties = None
|
||||
properties = comp.preFrameRender(
|
||||
comp.preFrameRender(
|
||||
worker=self,
|
||||
completeAudioArray=self.completeAudioArray,
|
||||
sampleSize=self.sampleSize,
|
||||
|
@ -152,101 +151,12 @@ class Worker(QtCore.QObject):
|
|||
progressBarSetText=self.progressBarSetText
|
||||
)
|
||||
|
||||
if properties:
|
||||
if 'static' in properties:
|
||||
self.staticComponents[compNo] = \
|
||||
comp.frameRender(compNo, 0).copy()
|
||||
if 'audio' in properties:
|
||||
self.extraAudio.append(comp.audio())
|
||||
if 'static' in comp.properties():
|
||||
self.staticComponents[compNo] = \
|
||||
comp.frameRender(compNo, 0).copy()
|
||||
|
||||
# =~=~=~=~=~=~=~=~=~=~=~=~=~=~=~=~=~=~=~==~=~=~=~=~=~=~=~=~=~=~=~=~=~
|
||||
# DEDUCE ENCODERS
|
||||
# =~=~=~=~=~=~=~=~=~=~=~=~=~=~=~=~=~=~=~==~=~=~=~=~=~=~=~=~=~=~=~=~=~
|
||||
|
||||
# test if user has libfdk_aac
|
||||
encoders = checkOutput(
|
||||
"%s -encoders -hide_banner" % self.core.FFMPEG_BIN, shell=True
|
||||
)
|
||||
encoders = encoders.decode("utf-8")
|
||||
|
||||
acodec = self.core.settings.value('outputAudioCodec')
|
||||
|
||||
options = self.core.encoder_options
|
||||
containerName = self.core.settings.value('outputContainer')
|
||||
vcodec = self.core.settings.value('outputVideoCodec')
|
||||
vbitrate = str(self.core.settings.value('outputVideoBitrate'))+'k'
|
||||
acodec = self.core.settings.value('outputAudioCodec')
|
||||
abitrate = str(self.core.settings.value('outputAudioBitrate'))+'k'
|
||||
|
||||
for cont in options['containers']:
|
||||
if cont['name'] == containerName:
|
||||
container = cont['container']
|
||||
break
|
||||
|
||||
vencoders = options['video-codecs'][vcodec]
|
||||
aencoders = options['audio-codecs'][acodec]
|
||||
|
||||
for encoder in vencoders:
|
||||
if encoder in encoders:
|
||||
vencoder = encoder
|
||||
break
|
||||
|
||||
for encoder in aencoders:
|
||||
if encoder in encoders:
|
||||
aencoder = encoder
|
||||
break
|
||||
|
||||
# =~=~=~=~=~=~=~=~=~=~=~=~=~=~=~=~=~=~=~==~=~=~=~=~=~=~=~=~=~=~=~=~=~
|
||||
# CREATE PIPE TO FFMPEG
|
||||
# =~=~=~=~=~=~=~=~=~=~=~=~=~=~=~=~=~=~=~==~=~=~=~=~=~=~=~=~=~=~=~=~=~
|
||||
|
||||
ffmpegCommand = [
|
||||
self.core.FFMPEG_BIN,
|
||||
'-thread_queue_size', '512',
|
||||
'-y', # overwrite the output file if it already exists.
|
||||
|
||||
# INPUT VIDEO
|
||||
'-f', 'rawvideo',
|
||||
'-vcodec', 'rawvideo',
|
||||
'-s', str(self.width)+'x'+str(self.height), # size of one frame
|
||||
'-pix_fmt', 'rgba',
|
||||
'-r', self.core.settings.value('outputFrameRate'),
|
||||
'-i', '-', # the video input comes from a pipe
|
||||
'-an', # the video input has no sound
|
||||
|
||||
# INPUT SOUND
|
||||
'-i', inputFile
|
||||
]
|
||||
|
||||
if self.extraAudio:
|
||||
for extraInputFile in self.extraAudio:
|
||||
ffmpegCommand.extend([
|
||||
'-i', extraInputFile
|
||||
])
|
||||
ffmpegCommand.extend([
|
||||
'-filter_complex',
|
||||
'amix=inputs=%s:duration=longest:dropout_transition=3' % str(
|
||||
len(self.extraAudio) + 1
|
||||
)
|
||||
])
|
||||
|
||||
ffmpegCommand.extend([
|
||||
# OUTPUT
|
||||
'-vcodec', vencoder,
|
||||
'-acodec', aencoder,
|
||||
'-b:v', vbitrate,
|
||||
'-b:a', abitrate,
|
||||
'-pix_fmt', self.core.settings.value('outputVideoFormat'),
|
||||
'-preset', self.core.settings.value('outputPreset'),
|
||||
'-f', container
|
||||
])
|
||||
ffmpegCommand = self.core.createFfmpegCommand(inputFile, outputFile)
|
||||
print(ffmpegCommand)
|
||||
|
||||
if acodec == 'aac':
|
||||
ffmpegCommand.append('-strict')
|
||||
ffmpegCommand.append('-2')
|
||||
|
||||
ffmpegCommand.append(outputFile)
|
||||
self.out_pipe = openPipe(
|
||||
ffmpegCommand, stdin=sp.PIPE, stdout=sys.stdout, stderr=sys.stdout
|
||||
)
|
||||
|
|
Reference in New Issue