use -t on inputs so ffmpeg knows when to stop filters

+ better feedback in cmd mode
This commit is contained in:
tassaron 2017-07-15 13:13:53 -04:00
parent 62ab09e3f3
commit bcb8f27c2e
6 changed files with 67 additions and 23 deletions

View File

@ -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)

View File

@ -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)

View File

@ -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):

View File

@ -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)

View File

@ -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

View File

@ -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('############################')