use -t on inputs so ffmpeg knows when to stop filters
+ better feedback in cmd mode
This commit is contained in:
parent
62ab09e3f3
commit
bcb8f27c2e
|
@ -7,6 +7,7 @@ from PyQt5 import QtCore
|
|||
import argparse
|
||||
import os
|
||||
import sys
|
||||
import time
|
||||
|
||||
import core
|
||||
from toolkit import LoadDefaultSettings
|
||||
|
@ -118,8 +119,27 @@ class Command(QtCore.QObject):
|
|||
self, input, output
|
||||
)
|
||||
self.worker.videoCreated.connect(self.videoCreated)
|
||||
self.lastProgressUpdate = time.time()
|
||||
self.worker.progressBarSetText.connect(self.progressBarSetText)
|
||||
self.createVideo.emit()
|
||||
|
||||
@QtCore.pyqtSlot(str)
|
||||
def progressBarSetText(self, value):
|
||||
if 'Export ' in value:
|
||||
# Don't duplicate completion/failure messages
|
||||
return
|
||||
if not value.startswith('Exporting') \
|
||||
and time.time() - self.lastProgressUpdate >= 0.05:
|
||||
# Show most messages very often
|
||||
print(value)
|
||||
elif time.time() - self.lastProgressUpdate >= 2.0:
|
||||
# Give user time to read ffmpeg's output during the export
|
||||
print('##### %s' % value)
|
||||
else:
|
||||
return
|
||||
self.lastProgressUpdate = time.time()
|
||||
|
||||
@QtCore.pyqtSlot()
|
||||
def videoCreated(self):
|
||||
quit(0)
|
||||
|
||||
|
|
|
@ -79,6 +79,11 @@ class Component(Component):
|
|||
if not arg.startswith('preset=') and '=' in arg:
|
||||
key, arg = arg.split('=', 1)
|
||||
if key == 'path':
|
||||
if '*%s' % os.path.splitext(arg)[1] \
|
||||
not in self.core.audioFormats:
|
||||
print("Not a supported audio format")
|
||||
quit(1)
|
||||
self.page.lineEdit_sound.setText(arg)
|
||||
return
|
||||
|
||||
super().command(arg)
|
||||
|
|
|
@ -116,6 +116,7 @@ class Component(Component):
|
|||
page = self.loadUi('video.ui')
|
||||
self.videoPath = ''
|
||||
self.badVideo = False
|
||||
self.badAudio = False
|
||||
self.x = 0
|
||||
self.y = 0
|
||||
self.loopVideo = False
|
||||
|
@ -161,22 +162,14 @@ class Component(Component):
|
|||
|
||||
if self.useAudio:
|
||||
props.append('audio')
|
||||
# test if an audio stream really exists
|
||||
audioTestCommand = [
|
||||
self.core.FFMPEG_BIN,
|
||||
'-i', self.videoPath,
|
||||
'-vn', '-f', 'null', '-'
|
||||
]
|
||||
try:
|
||||
checkOutput(audioTestCommand, stderr=subprocess.DEVNULL)
|
||||
except subprocess.CalledProcessError:
|
||||
self.badAudio = True
|
||||
self.testAudioStream()
|
||||
if self.badAudio:
|
||||
return ['error']
|
||||
|
||||
return props
|
||||
|
||||
def error(self):
|
||||
if hasattr(self, 'badAudio'):
|
||||
if self.badAudio:
|
||||
return "Could not identify an audio stream in this video."
|
||||
if not self.videoPath:
|
||||
return "There is no video selected."
|
||||
|
@ -185,6 +178,20 @@ class Component(Component):
|
|||
if self.badVideo:
|
||||
return "The video selected is corrupt!"
|
||||
|
||||
def testAudioStream(self):
|
||||
# test if an audio stream really exists
|
||||
audioTestCommand = [
|
||||
self.core.FFMPEG_BIN,
|
||||
'-i', self.videoPath,
|
||||
'-vn', '-f', 'null', '-'
|
||||
]
|
||||
try:
|
||||
checkOutput(audioTestCommand, stderr=subprocess.DEVNULL)
|
||||
except subprocess.CalledProcessError:
|
||||
self.badAudio = True
|
||||
else:
|
||||
self.badAudio = False
|
||||
|
||||
def audio(self):
|
||||
return (self.videoPath, {'map': '-v'})
|
||||
|
||||
|
@ -277,7 +284,7 @@ class Component(Component):
|
|||
if not arg.startswith('preset=') and '=' in arg:
|
||||
key, arg = arg.split('=', 1)
|
||||
if key == 'path' and os.path.exists(arg):
|
||||
if os.path.splitext(arg)[1] in self.core.videoFormats:
|
||||
if '*%s' % os.path.splitext(arg)[1] in self.core.videoFormats:
|
||||
self.page.lineEdit_video.setText(arg)
|
||||
self.page.spinBox_scale.setValue(100)
|
||||
self.page.checkBox_loop.setChecked(True)
|
||||
|
@ -285,10 +292,17 @@ class Component(Component):
|
|||
else:
|
||||
print("Not a supported video format")
|
||||
quit(1)
|
||||
elif arg == 'audio':
|
||||
if not self.page.lineEdit_video.text():
|
||||
print("'audio' option must follow a video selection")
|
||||
quit(1)
|
||||
self.page.checkBox_useAudio.setChecked(True)
|
||||
return
|
||||
super().command(arg)
|
||||
|
||||
def commandHelp(self):
|
||||
print('Load a video:\n path=/filepath/to/video.mp4')
|
||||
print('Using audio:\n path=/filepath/to/video.mp4 audio')
|
||||
|
||||
|
||||
def scale(scale, width, height, returntype=None):
|
||||
|
|
|
@ -464,10 +464,11 @@ class Core:
|
|||
except sp.CalledProcessError:
|
||||
return "avconv"
|
||||
|
||||
def createFfmpegCommand(self, inputFile, outputFile):
|
||||
def createFfmpegCommand(self, inputFile, outputFile, duration):
|
||||
'''
|
||||
Constructs the major ffmpeg command used to export the video
|
||||
'''
|
||||
duration = str(duration)
|
||||
|
||||
# Test if user has libfdk_aac
|
||||
encoders = toolkit.checkOutput(
|
||||
|
@ -516,10 +517,12 @@ class Core:
|
|||
),
|
||||
'-pix_fmt', 'rgba',
|
||||
'-r', self.settings.value('outputFrameRate'),
|
||||
'-t', duration,
|
||||
'-i', '-', # the video input comes from a pipe
|
||||
'-an', # the video input has no sound
|
||||
|
||||
# INPUT SOUND
|
||||
'-t', duration,
|
||||
'-i', inputFile
|
||||
]
|
||||
|
||||
|
@ -532,6 +535,7 @@ class Core:
|
|||
for streamNo, params in enumerate(extraAudio):
|
||||
extraInputFile, params = params
|
||||
ffmpegCommand.extend([
|
||||
'-t', duration,
|
||||
'-i', extraInputFile
|
||||
])
|
||||
if 'map' in params and params['map'] == '-v':
|
||||
|
@ -632,7 +636,7 @@ class Core:
|
|||
completeAudioArrayCopy[:len(completeAudioArray)] = completeAudioArray
|
||||
completeAudioArray = completeAudioArrayCopy
|
||||
|
||||
return completeAudioArray
|
||||
return (completeAudioArray, duration)
|
||||
|
||||
def newVideoWorker(self, loader, audioFile, outputPath):
|
||||
self.videoThread = QtCore.QThread(loader)
|
||||
|
|
11
src/main.py
11
src/main.py
|
@ -8,13 +8,13 @@ import video_thread
|
|||
|
||||
|
||||
if __name__ == "__main__":
|
||||
mode = 'gui'
|
||||
mode = 'GUI'
|
||||
if len(sys.argv) > 2:
|
||||
mode = 'cmd'
|
||||
mode = 'commandline'
|
||||
|
||||
elif len(sys.argv) == 2:
|
||||
if sys.argv[1].startswith('-'):
|
||||
mode = 'cmd'
|
||||
mode = 'commandline'
|
||||
else:
|
||||
# opening a project file with gui
|
||||
proj = sys.argv[1]
|
||||
|
@ -22,16 +22,17 @@ if __name__ == "__main__":
|
|||
# normal gui launch
|
||||
proj = None
|
||||
|
||||
print('Starting Audio Visualizer in %s mode' % mode)
|
||||
app = QtWidgets.QApplication(sys.argv)
|
||||
app.setApplicationName("audio-visualizer")
|
||||
# app.setOrganizationName("audio-visualizer")
|
||||
|
||||
if mode == 'cmd':
|
||||
if mode == 'commandline':
|
||||
from command import *
|
||||
|
||||
main = Command()
|
||||
|
||||
elif mode == 'gui':
|
||||
elif mode == 'GUI':
|
||||
from mainwindow import *
|
||||
import atexit
|
||||
import signal
|
||||
|
|
|
@ -31,7 +31,6 @@ class Worker(QtCore.QObject):
|
|||
progressBarSetText = pyqtSignal(str)
|
||||
encoding = pyqtSignal(bool)
|
||||
|
||||
|
||||
def __init__(self, parent, inputFile, outputFile, components):
|
||||
QtCore.QObject.__init__(self)
|
||||
self.core = parent.core
|
||||
|
@ -135,7 +134,9 @@ class Worker(QtCore.QObject):
|
|||
# =~=~=~=~=~=~=~=~=~=~=~=~=~=~=~=~=~=~=~==~=~=~=~=~=~=~=~=~=~=~=~=~=~
|
||||
|
||||
self.progressBarSetText.emit("Loading audio file...")
|
||||
self.completeAudioArray = self.core.readAudioFile(self.inputFile, self)
|
||||
self.completeAudioArray, duration = self.core.readAudioFile(
|
||||
self.inputFile, self
|
||||
)
|
||||
|
||||
self.progressBarUpdate.emit(0)
|
||||
self.progressBarSetText.emit("Starting components...")
|
||||
|
@ -144,7 +145,6 @@ class Worker(QtCore.QObject):
|
|||
for num, component in enumerate(reversed(self.components))
|
||||
]))
|
||||
self.staticComponents = {}
|
||||
numComps = len(self.components)
|
||||
for compNo, comp in enumerate(reversed(self.components)):
|
||||
comp.preFrameRender(
|
||||
worker=self,
|
||||
|
@ -194,7 +194,7 @@ class Worker(QtCore.QObject):
|
|||
self.staticComponents[compNo] = None
|
||||
|
||||
ffmpegCommand = self.core.createFfmpegCommand(
|
||||
self.inputFile, self.outputFile
|
||||
self.inputFile, self.outputFile, duration
|
||||
)
|
||||
print('###### FFMPEG COMMAND ######\n%s' % " ".join(ffmpegCommand))
|
||||
print('############################')
|
||||
|
|
Reference in New Issue