From ec0abd190273b7b636c7085d7caed8220ab09172 Mon Sep 17 00:00:00 2001
From: tassaron
Date: Sun, 16 Jul 2017 14:06:11 -0400
Subject: apply complex filters to audio streams from components
tons of sound options could be given now, + installation using setup.py
---
src/components/sound.py | 23 ++++++++++++++-
src/components/sound.ui | 50 +++++++++++++++++++++++++++++++++
src/components/video.py | 16 ++++++++++-
src/components/video.ui | 75 ++++++++++++++++++++++++++++++++++++++++++++-----
4 files changed, 155 insertions(+), 9 deletions(-)
(limited to 'src/components')
diff --git a/src/components/sound.py b/src/components/sound.py
index 4a5714b..bd7d002 100644
--- a/src/components/sound.py
+++ b/src/components/sound.py
@@ -17,12 +17,18 @@ class Component(Component):
page.lineEdit_sound.textChanged.connect(self.update)
page.pushButton_sound.clicked.connect(self.pickSound)
+ page.checkBox_chorus.stateChanged.connect(self.update)
+ page.spinBox_delay.valueChanged.connect(self.update)
+ page.spinBox_volume.valueChanged.connect(self.update)
self.page = page
return page
def update(self):
self.sound = self.page.lineEdit_sound.text()
+ self.delay = self.page.spinBox_delay.value()
+ self.volume = self.page.spinBox_volume.value()
+ self.chorus = self.page.checkBox_chorus.isChecked()
super().update()
def previewRender(self, previewWorker):
@@ -46,7 +52,16 @@ class Component(Component):
return "The audio file selected no longer exists!"
def audio(self):
- return (self.sound, {})
+ params = {}
+ if self.delay != 0.0:
+ params['adelay'] = '=%s' % str(int(self.delay * 1000.00))
+ if self.chorus:
+ params['chorus'] = \
+ '=0.5:0.9:50|60|40:0.4|0.32|0.3:0.25|0.4|0.3:2|2.3|1.3'
+ if self.volume != 1.0:
+ params['volume'] = '=%s:replaygain_noclip=0' % str(self.volume)
+
+ return (self.sound, params)
def pickSound(self):
sndDir = self.settings.value("componentDir", os.path.expanduser("~"))
@@ -66,10 +81,16 @@ class Component(Component):
def loadPreset(self, pr, presetName=None):
super().loadPreset(pr, presetName)
self.page.lineEdit_sound.setText(pr['sound'])
+ self.page.checkBox_chorus.setChecked(pr['chorus'])
+ self.page.spinBox_delay.setValue(pr['delay'])
+ self.page.spinBox_volume.setValue(pr['volume'])
def savePreset(self):
return {
'sound': self.sound,
+ 'chorus': self.chorus,
+ 'delay': self.delay,
+ 'volume': self.volume,
}
def commandHelp(self):
diff --git a/src/components/sound.ui b/src/components/sound.ui
index 5fc00c1..4c11332 100644
--- a/src/components/sound.ui
+++ b/src/components/sound.ui
@@ -87,6 +87,29 @@
-
+
-
+
+
+ Volume
+
+
+
+ -
+
+
+ x
+
+
+ 10.000000000000000
+
+
+ 0.100000000000000
+
+
+ 1.000000000000000
+
+
+
-
@@ -100,6 +123,33 @@
+ -
+
+
+ Delay
+
+
+
+ -
+
+
+ s
+
+
+ 9999999.990000000223517
+
+
+ 0.500000000000000
+
+
+
+ -
+
+
+ Chorus
+
+
+
-
diff --git a/src/components/video.py b/src/components/video.py
index 0b93293..e1f182c 100644
--- a/src/components/video.py
+++ b/src/components/video.py
@@ -127,6 +127,7 @@ class Component(Component):
page.checkBox_distort.stateChanged.connect(self.update)
page.checkBox_useAudio.stateChanged.connect(self.update)
page.spinBox_scale.valueChanged.connect(self.update)
+ page.spinBox_volume.valueChanged.connect(self.update)
page.spinBox_x.valueChanged.connect(self.update)
page.spinBox_y.valueChanged.connect(self.update)
@@ -139,9 +140,17 @@ class Component(Component):
self.useAudio = self.page.checkBox_useAudio.isChecked()
self.distort = self.page.checkBox_distort.isChecked()
self.scale = self.page.spinBox_scale.value()
+ self.volume = self.page.spinBox_volume.value()
self.xPosition = self.page.spinBox_x.value()
self.yPosition = self.page.spinBox_y.value()
+ if self.useAudio:
+ self.page.label_volume.setEnabled(True)
+ self.page.spinBox_volume.setEnabled(True)
+ else:
+ self.page.label_volume.setEnabled(False)
+ self.page.spinBox_volume.setEnabled(False)
+
super().update()
def previewRender(self, previewWorker):
@@ -193,7 +202,10 @@ class Component(Component):
self.badAudio = False
def audio(self):
- return (self.videoPath, {'map': '-v'})
+ params = {}
+ if self.volume != 1.0:
+ params['volume'] = '=%s:replaygain_noclip=0' % str(self.volume)
+ return (self.videoPath, params)
def preFrameRender(self, **kwargs):
super().preFrameRender(**kwargs)
@@ -222,6 +234,7 @@ class Component(Component):
self.page.checkBox_useAudio.setChecked(pr['useAudio'])
self.page.checkBox_distort.setChecked(pr['distort'])
self.page.spinBox_scale.setValue(pr['scale'])
+ self.page.spinBox_volume.setValue(pr['volume'])
self.page.spinBox_x.setValue(pr['x'])
self.page.spinBox_y.setValue(pr['y'])
@@ -233,6 +246,7 @@ class Component(Component):
'useAudio': self.useAudio,
'distort': self.distort,
'scale': self.scale,
+ 'volume': self.volume,
'x': self.xPosition,
'y': self.yPosition,
}
diff --git a/src/components/video.ui b/src/components/video.ui
index 97b7d6f..08d15d3 100644
--- a/src/components/video.ui
+++ b/src/components/video.ui
@@ -10,6 +10,18 @@
197
+
+
+ 0
+ 0
+
+
+
+
+ 0
+ 197
+
+
Form
@@ -189,13 +201,6 @@
- -
-
-
- Use Audio
-
-
-
-
@@ -247,6 +252,62 @@
+ -
+
+
-
+
+
+ Use Audio
+
+
+
+ -
+
+
+ Volume
+
+
+
+ -
+
+
+
+ 0
+ 0
+
+
+
+ x
+
+
+ 0.000000000000000
+
+
+ 10.000000000000000
+
+
+ 0.100000000000000
+
+
+ 1.000000000000000
+
+
+
+ -
+
+
+ Qt::Horizontal
+
+
+
+ 40
+ 20
+
+
+
+
+
+
-
--
cgit v1.2.3
From aa464632c64725201dc7584ebf6bf2c3d06b47b6 Mon Sep 17 00:00:00 2001
From: tassaron
Date: Sun, 16 Jul 2017 23:13:00 -0400
Subject: new hotkey to preview the ffmpeg command
---
setup.py | 2 +-
src/components/video.py | 4 ++--
src/core.py | 6 +++++-
src/mainwindow.py | 19 ++++++++++++++++++-
4 files changed, 26 insertions(+), 5 deletions(-)
(limited to 'src/components')
diff --git a/setup.py b/setup.py
index 71dc51f..6ef688a 100644
--- a/setup.py
+++ b/setup.py
@@ -30,7 +30,7 @@ setup(
'Topic :: Multimedia :: Video :: Non-Linear Editor',
],
keywords=['visualizer', 'visualization', 'commandline video',
- 'video editor', 'ffmpeg', 'podcast']
+ 'video editor', 'ffmpeg', 'podcast'],
packages=[
'avpython',
'avpython.components'
diff --git a/src/components/video.py b/src/components/video.py
index e1f182c..9e3db30 100644
--- a/src/components/video.py
+++ b/src/components/video.py
@@ -45,7 +45,7 @@ class Video:
'-i', self.videoPath,
'-f', 'image2pipe',
'-pix_fmt', 'rgba',
- '-filter:v', 'scale=%s:%s' % scale(
+ '-filter_complex', '[0:v] scale=%s:%s' % scale(
self.scale, self.width, self.height, str),
'-vcodec', 'rawvideo', '-',
]
@@ -272,7 +272,7 @@ class Component(Component):
'-i', self.videoPath,
'-f', 'image2pipe',
'-pix_fmt', 'rgba',
- '-filter:v', 'scale=%s:%s' % scale(
+ '-filter_complex', '[0:v] scale=%s:%s' % scale(
self.scale, width, height, str),
'-vcodec', 'rawvideo', '-',
'-ss', '90',
diff --git a/src/core.py b/src/core.py
index 324b04f..a0a028b 100644
--- a/src/core.py
+++ b/src/core.py
@@ -541,6 +541,10 @@ class Core:
extraInputFile, params = params
ffmpegCommand.extend([
'-t', safeDuration,
+ # Tell ffmpeg about shorter clips (seemingly not needed)
+ # streamDuration = self.getAudioDuration(extraInputFile)
+ # if streamDuration > float(safeDuration)
+ # else "{0:.3f}".format(streamDuration),
'-i', extraInputFile
])
# Construct dataset of extra filters we'll need to add later
@@ -551,7 +555,7 @@ class Core:
ffmpegFilter, params[ffmpegFilter]
))
- # Start creating avfilters!
+ # Start creating avfilters! Popen-style, so don't use semicolons;
extraFilterCommand = []
if globalFilters <= 0:
diff --git a/src/mainwindow.py b/src/mainwindow.py
index 76ed179..ca8e697 100644
--- a/src/mainwindow.py
+++ b/src/mainwindow.py
@@ -305,7 +305,12 @@ class MainWindow(QtWidgets.QMainWindow):
QtWidgets.QShortcut("Ctrl+A", self.window, self.openSaveProjectDialog)
QtWidgets.QShortcut("Ctrl+O", self.window, self.openOpenProjectDialog)
QtWidgets.QShortcut("Ctrl+N", self.window, self.createNewProject)
- QtWidgets.QShortcut("Ctrl+Alt+Shift+R", self.window, self.drawPreview)
+ QtWidgets.QShortcut(
+ "Ctrl+Alt+Shift+R", self.window, self.drawPreview
+ )
+ QtWidgets.QShortcut(
+ "Ctrl+Alt+Shift+F", self.window, self.showFfmpegCommand
+ )
QtWidgets.QShortcut(
"Ctrl+T", self.window,
@@ -580,6 +585,18 @@ class MainWindow(QtWidgets.QMainWindow):
def showPreviewImage(self, image):
self.previewWindow.changePixmap(image)
+ def showFfmpegCommand(self):
+ from textwrap import wrap
+ command = self.core.createFfmpegCommand(
+ self.window.lineEdit_audioFile.text(),
+ self.window.lineEdit_outputFile.text(),
+ self.core.getAudioDuration(self.window.lineEdit_audioFile.text())
+ )
+ lines = wrap(" ".join(command), 49)
+ self.showMessage(
+ msg="Current FFmpeg command:\n\n %s" % " ".join(lines)
+ )
+
def insertComponent(self, index):
componentList = self.window.listWidget_componentList
stackedWidget = self.window.stackedWidget
--
cgit v1.2.3