From c1457b6dad4640b17679dd802e372bd46a13d2a5 Mon Sep 17 00:00:00 2001
From: tassaron
Date: Sat, 29 Jul 2017 13:08:28 -0400
Subject: starting work on Waveform component
split Video class out of Video component for reuse in Waveform
---
src/components/video.py | 198 +++++++++++++-----------------------------------
1 file changed, 51 insertions(+), 147 deletions(-)
(limited to 'src/components/video.py')
diff --git a/src/components/video.py b/src/components/video.py
index b2487c1..d3460ff 100644
--- a/src/components/video.py
+++ b/src/components/video.py
@@ -1,103 +1,13 @@
-from PIL import Image, ImageDraw
+from PIL import Image
from PyQt5 import QtGui, QtCore, QtWidgets
import os
import math
import subprocess
-import signal
-import threading
-from queue import PriorityQueue
from component import Component, ComponentError
from toolkit.frame import BlankFrame
-from toolkit.ffmpeg import testAudioStream
-from toolkit import openPipe, checkOutput
-
-
-class Video:
- '''Opens a pipe to ffmpeg and stores a buffer of raw video frames.'''
-
- # error from the thread used to fill the buffer
- threadError = None
-
- def __init__(self, **kwargs):
- mandatoryArgs = [
- 'ffmpeg', # path to ffmpeg, usually self.core.FFMPEG_BIN
- 'videoPath',
- 'width',
- 'height',
- 'scale', # percentage scale
- 'frameRate', # frames per second
- 'chunkSize', # number of bytes in one frame
- 'parent', # mainwindow object
- 'component', # component object
- ]
- for arg in mandatoryArgs:
- setattr(self, arg, kwargs[arg])
-
- self.frameNo = -1
- self.currentFrame = 'None'
- if 'loopVideo' in kwargs and kwargs['loopVideo']:
- self.loopValue = '-1'
- else:
- self.loopValue = '0'
- self.command = [
- self.ffmpeg,
- '-thread_queue_size', '512',
- '-r', str(self.frameRate),
- '-stream_loop', self.loopValue,
- '-i', self.videoPath,
- '-f', 'image2pipe',
- '-pix_fmt', 'rgba',
- '-filter_complex', '[0:v] scale=%s:%s' % scale(
- self.scale, self.width, self.height, str),
- '-vcodec', 'rawvideo', '-',
- ]
-
- self.frameBuffer = PriorityQueue()
- self.frameBuffer.maxsize = self.frameRate
- self.finishedFrames = {}
-
- self.thread = threading.Thread(
- target=self.fillBuffer,
- name='Video Frame-Fetcher'
- )
- self.thread.daemon = True
- self.thread.start()
-
- def frame(self, num):
- while True:
- if num in self.finishedFrames:
- image = self.finishedFrames.pop(num)
- return finalizeFrame(
- self.component, image, self.width, self.height)
-
- i, image = self.frameBuffer.get()
- self.finishedFrames[i] = image
- self.frameBuffer.task_done()
-
- def fillBuffer(self):
- self.pipe = openPipe(
- self.command, stdin=subprocess.DEVNULL, stdout=subprocess.PIPE,
- stderr=subprocess.DEVNULL, bufsize=10**8
- )
- while True:
- if self.parent.canceled:
- break
- self.frameNo += 1
-
- # If we run out of frames, use the last good frame and loop.
- try:
- if len(self.currentFrame) == 0:
- self.frameBuffer.put((self.frameNo-1, self.lastFrame))
- continue
- except AttributeError:
- Video.threadError = ComponentError(self.component, 'video')
- break
-
- self.currentFrame = self.pipe.stdout.read(self.chunkSize)
- if len(self.currentFrame) != 0:
- self.frameBuffer.put((self.frameNo, self.currentFrame))
- self.lastFrame = self.currentFrame
+from toolkit.ffmpeg import testAudioStream, FfmpegVideo
+from toolkit import openPipe, closePipe, checkOutput, scale
class Component(Component):
@@ -182,22 +92,21 @@ class Component(Component):
def preFrameRender(self, **kwargs):
super().preFrameRender(**kwargs)
self.updateChunksize()
- self.video = Video(
- ffmpeg=self.core.FFMPEG_BIN, videoPath=self.videoPath,
+ self.video = FfmpegVideo(
+ inputPath=self.videoPath, filter_=self.makeFfmpegFilter(),
width=self.width, height=self.height, chunkSize=self.chunkSize,
frameRate=int(self.settings.value("outputFrameRate")),
parent=self.parent, loopVideo=self.loopVideo,
- component=self, scale=self.scale
+ component=self
) if os.path.exists(self.videoPath) else None
def frameRender(self, frameNo):
- if Video.threadError is not None:
- raise Video.threadError
- return self.video.frame(frameNo)
+ if FfmpegVideo.threadError is not None:
+ raise FfmpegVideo.threadError
+ return self.finalizeFrame(self.video.frame(frameNo))
def postFrameRender(self):
- self.video.pipe.stdout.close()
- self.video.pipe.send_signal(signal.SIGINT)
+ closePipe(self.video.pipe)
def pickVideo(self):
imgDir = self.settings.value("componentDir", os.path.expanduser("~"))
@@ -220,23 +129,30 @@ class Component(Component):
'-i', self.videoPath,
'-f', 'image2pipe',
'-pix_fmt', 'rgba',
- '-filter_complex', '[0:v] scale=%s:%s' % scale(
- self.scale, width, height, str),
+ ]
+ command.extend(self.makeFfmpegFilter())
+ command.extend([
'-vcodec', 'rawvideo', '-',
'-ss', '90',
- '-vframes', '1',
- ]
+ '-frames:v', '1',
+ ])
pipe = openPipe(
command, stdin=subprocess.DEVNULL, stdout=subprocess.PIPE,
stderr=subprocess.DEVNULL, bufsize=10**8
)
byteFrame = pipe.stdout.read(self.chunkSize)
- pipe.stdout.close()
- pipe.send_signal(signal.SIGINT)
+ closePipe(pipe)
- frame = finalizeFrame(self, byteFrame, width, height)
+ frame = self.finalizeFrame(byteFrame)
return frame
+ def makeFfmpegFilter(self):
+ return [
+ '-filter_complex',
+ '[0:v] scale=%s:%s' % scale(
+ self.scale, self.width, self.height, str),
+ ]
+
def updateChunksize(self):
if self.scale != 100 and not self.distort:
width, height = scale(self.scale, self.width, self.height, int)
@@ -268,44 +184,32 @@ class Component(Component):
print('Load a video:\n path=/filepath/to/video.mp4')
print('Using audio:\n path=/filepath/to/video.mp4 audio')
+ def finalizeFrame(self, imageData):
+ try:
+ if self.distort:
+ image = Image.frombytes(
+ 'RGBA',
+ (self.width, self.height),
+ imageData)
+ else:
+ image = Image.frombytes(
+ 'RGBA',
+ scale(self.scale, self.width, self.height, int),
+ imageData)
+
+ except ValueError:
+ print(
+ '### BAD VIDEO SELECTED ###\n'
+ 'Video will not export with these settings'
+ )
+ self.badVideo = True
+ return BlankFrame(self.width, self.height)
-def scale(scale, width, height, returntype=None):
- width = (float(width) / 100.0) * float(scale)
- height = (float(height) / 100.0) * float(scale)
- if returntype == str:
- return (str(math.ceil(width)), str(math.ceil(height)))
- elif returntype == int:
- return (math.ceil(width), math.ceil(height))
- else:
- return (width, height)
-
-
-def finalizeFrame(self, imageData, width, height):
- try:
- if self.distort:
- image = Image.frombytes(
- 'RGBA',
- (width, height),
- imageData)
+ if self.scale != 100 \
+ or self.xPosition != 0 or self.yPosition != 0:
+ frame = BlankFrame(self.width, self.height)
+ frame.paste(image, box=(self.xPosition, self.yPosition))
else:
- image = Image.frombytes(
- 'RGBA',
- scale(self.scale, width, height, int),
- imageData)
-
- except ValueError:
- print(
- '### BAD VIDEO SELECTED ###\n'
- 'Video will not export with these settings'
- )
- self.badVideo = True
- return BlankFrame(width, height)
-
- if self.scale != 100 \
- or self.xPosition != 0 or self.yPosition != 0:
- frame = BlankFrame(width, height)
- frame.paste(image, box=(self.xPosition, self.yPosition))
- else:
- frame = image
- self.badVideo = False
- return frame
+ frame = image
+ self.badVideo = False
+ return frame
--
cgit v1.2.3
From 1297af61c9ce00b6dd76f8ec690baedf5bf887c7 Mon Sep 17 00:00:00 2001
From: tassaron
Date: Sat, 29 Jul 2017 20:27:46 -0400
Subject: waveform component is working, preview is glitchy
---
src/components/original.py | 3 +
src/components/video.py | 10 ++--
src/components/waveform.py | 134 +++++++++++++++++++++++++++++++--------------
src/components/waveform.ui | 95 +++++++++++++++++++++++++++++++-
src/toolkit/common.py | 21 -------
src/toolkit/ffmpeg.py | 30 ++++++++--
src/toolkit/frame.py | 12 ++++
src/video_thread.py | 38 +++++++++----
8 files changed, 256 insertions(+), 87 deletions(-)
(limited to 'src/components/video.py')
diff --git a/src/components/original.py b/src/components/original.py
index 3d1a574..621af6f 100644
--- a/src/components/original.py
+++ b/src/components/original.py
@@ -18,6 +18,9 @@ class Component(Component):
def names(*args):
return ['Original Audio Visualization']
+ def properties(self):
+ return ['pcm']
+
def widget(self, *args):
self.visColor = (255, 255, 255)
self.scale = 20
diff --git a/src/components/video.py b/src/components/video.py
index d3460ff..6cd16e5 100644
--- a/src/components/video.py
+++ b/src/components/video.py
@@ -4,10 +4,10 @@ import os
import math
import subprocess
-from component import Component, ComponentError
-from toolkit.frame import BlankFrame
-from toolkit.ffmpeg import testAudioStream, FfmpegVideo
-from toolkit import openPipe, closePipe, checkOutput, scale
+from component import Component
+from toolkit.frame import BlankFrame, scale
+from toolkit.ffmpeg import openPipe, closePipe, testAudioStream, FfmpegVideo
+from toolkit import checkOutput
class Component(Component):
@@ -132,7 +132,7 @@ class Component(Component):
]
command.extend(self.makeFfmpegFilter())
command.extend([
- '-vcodec', 'rawvideo', '-',
+ '-codec:v', 'rawvideo', '-',
'-ss', '90',
'-frames:v', '1',
])
diff --git a/src/components/waveform.py b/src/components/waveform.py
index 487a3bb..375b3fc 100644
--- a/src/components/waveform.py
+++ b/src/components/waveform.py
@@ -5,10 +5,10 @@ import os
import math
import subprocess
-from component import Component, ComponentError
-from toolkit.frame import BlankFrame
-from toolkit import openPipe, checkOutput, rgbFromString
-from toolkit.ffmpeg import FfmpegVideo
+from component import Component
+from toolkit.frame import BlankFrame, scale
+from toolkit import checkOutput, rgbFromString, pickColor
+from toolkit.ffmpeg import openPipe, closePipe, getAudioDuration, FfmpegVideo
class Component(Component):
@@ -21,17 +21,27 @@ class Component(Component):
self.page.lineEdit_color.setText('%s,%s,%s' % self.color)
btnStyle = "QPushButton { background-color : %s; outline: none; }" \
- % QColor(*self.color1).name()
- self.page.lineEdit_color.setStylesheet(btnStyle)
+ % QColor(*self.color).name()
+ self.page.pushButton_color.setStyleSheet(btnStyle)
self.page.pushButton_color.clicked.connect(lambda: self.pickColor())
+ self.page.spinBox_scale.valueChanged.connect(self.updateChunksize)
+
+ if hasattr(self.parent, 'window'):
+ self.parent.window.lineEdit_audioFile.textChanged.connect(
+ self.update
+ )
self.trackWidgets(
{
'mode': self.page.comboBox_mode,
+ 'amplitude': self.page.comboBox_amplitude,
'x': self.page.spinBox_x,
'y': self.page.spinBox_y,
'mirror': self.page.checkBox_mirror,
'scale': self.page.spinBox_scale,
+ 'opacity': self.page.spinBox_opacity,
+ 'compress': self.page.checkBox_compress,
+ 'mono': self.page.checkBox_mono,
}
)
@@ -42,6 +52,26 @@ class Component(Component):
self.page.pushButton_color.setStyleSheet(btnStyle)
super().update()
+ def loadPreset(self, pr, *args):
+ super().loadPreset(pr, *args)
+
+ self.page.lineEdit_color.setText('%s,%s,%s' % pr['color'])
+ btnStyle = "QPushButton { background-color : %s; outline: none; }" \
+ % QColor(*pr['color']).name()
+ self.page.pushButton_color.setStyleSheet(btnStyle)
+
+ def savePreset(self):
+ saveValueStore = super().savePreset()
+ saveValueStore['color'] = self.color
+ return saveValueStore
+
+ def pickColor(self):
+ RGBstring, btnStyle = pickColor()
+ if not RGBstring:
+ return
+ self.page.lineEdit_color.setText(RGBstring)
+ self.page.pushButton_color.setStyleSheet(btnStyle)
+
def previewRender(self):
self.updateChunksize()
frame = self.getPreviewFrame(self.width, self.height)
@@ -53,10 +83,11 @@ class Component(Component):
def preFrameRender(self, **kwargs):
super().preFrameRender(**kwargs)
self.updateChunksize()
+ w, h = scale(self.scale, self.width, self.height, str)
self.video = FfmpegVideo(
inputPath=self.audioFile,
- filter_=makeFfmpegFilter(),
- width=self.width, height=self.height,
+ filter_=self.makeFfmpegFilter(),
+ width=w, height=h,
chunkSize=self.chunkSize,
frameRate=int(self.settings.value("outputFrameRate")),
parent=self.parent, component=self,
@@ -65,7 +96,7 @@ class Component(Component):
def frameRender(self, frameNo):
if FfmpegVideo.threadError is not None:
raise FfmpegVideo.threadError
- return finalizeFrame(self.video.frame(frameNo))
+ return self.finalizeFrame(self.video.frame(frameNo))
def postFrameRender(self):
closePipe(self.video.pipe)
@@ -74,18 +105,25 @@ class Component(Component):
inputFile = self.parent.window.lineEdit_audioFile.text()
if not inputFile or not os.path.exists(inputFile):
return
+ duration = getAudioDuration(inputFile)
+ if not duration:
+ return
+ startPt = duration / 3
command = [
self.core.FFMPEG_BIN,
'-thread_queue_size', '512',
+ '-r', self.settings.value("outputFrameRate"),
+ '-ss', "{0:.3f}".format(startPt),
'-i', inputFile,
'-f', 'image2pipe',
'-pix_fmt', 'rgba',
]
- command.extend(self.makeFfmpegFilter())
+ command.extend(self.makeFfmpegFilter(preview=True, startPt=startPt))
command.extend([
- '-vcodec', 'rawvideo', '-',
- '-ss', '90',
+ '-an',
+ '-s:v', '%sx%s' % scale(self.scale, self.width, self.height, str),
+ '-codec:v', 'rawvideo', '-',
'-frames:v', '1',
])
pipe = openPipe(
@@ -95,45 +133,57 @@ class Component(Component):
byteFrame = pipe.stdout.read(self.chunkSize)
closePipe(pipe)
- frame = finalizeFrame(self, byteFrame, width, height)
+ frame = self.finalizeFrame(byteFrame)
return frame
- def makeFfmpegFilter(self):
+ def makeFfmpegFilter(self, preview=False, startPt=0):
w, h = scale(self.scale, self.width, self.height, str)
+ if self.amplitude == 0:
+ amplitude = 'lin'
+ elif self.amplitude == 1:
+ amplitude = 'log'
+ elif self.amplitude == 2:
+ amplitude = 'sqrt'
+ elif self.amplitude == 3:
+ amplitude = 'cbrt'
+ hexcolor = QColor(*self.color).name()
+ opacity = "{0:.1f}".format(self.opacity / 100)
+
return [
'-filter_complex',
- '[0:a] showwaves=s=%sx%s:mode=%s,format=rgba [v]' % (
- w, h, self.mode,
+ '[0:a] %s%s'
+ 'showwaves=r=30:s=%sx%s:mode=%s:colors=%s@%s:scale=%s%s%s [v1]; '
+ '[v1] scale=%s:%s%s [v]' % (
+ 'compand=gain=2,' if self.compress else '',
+ 'aformat=channel_layouts=mono,' if self.mono else '',
+ self.settings.value("outputWidth"),
+ self.settings.value("outputHeight"),
+ str(self.page.comboBox_mode.currentText()).lower(),
+ hexcolor, opacity, amplitude,
+ ', drawbox=x=(iw-w)/2:y=(ih-h)/2:w=iw:h=4:color=%s@%s' % (
+ hexcolor, opacity
+ ) if self.mode < 2 else '',
+ ', hflip' if self.mirror else'',
+ w, h,
+ ', trim=duration=%s' % "{0:.3f}".format(startPt + 1) if preview else '',
),
'-map', '[v]',
- '-map', '0:a',
]
def updateChunksize(self):
- if self.scale != 100:
- width, height = scale(self.scale, self.width, self.height, int)
- else:
- width, height = self.width, self.height
+ width, height = scale(self.scale, self.width, self.height, int)
self.chunkSize = 4 * width * height
-
-def scale(scale, width, height, returntype=None):
- width = (float(width) / 100.0) * float(scale)
- height = (float(height) / 100.0) * float(scale)
- if returntype == str:
- return (str(math.ceil(width)), str(math.ceil(height)))
- elif returntype == int:
- return (math.ceil(width), math.ceil(height))
- else:
- return (width, height)
-
-
-def finalizeFrame(self, imageData, width, height):
- # frombytes goes here
- if self.scale != 100 \
- or self.x != 0 or self.y != 0:
- frame = BlankFrame(width, height)
- frame.paste(image, box=(self.x, self.y))
- else:
- frame = image
- return frame
+ def finalizeFrame(self, imageData):
+ image = Image.frombytes(
+ 'RGBA',
+ scale(self.scale, self.width, self.height, int),
+ imageData
+ )
+ if self.scale != 100 \
+ or self.x != 0 or self.y != 0:
+ frame = BlankFrame(self.width, self.height)
+ frame.paste(image, box=(self.x, self.y))
+ else:
+ frame = image
+ return frame
diff --git a/src/components/waveform.ui b/src/components/waveform.ui
index 5d62150..0e40380 100644
--- a/src/components/waveform.ui
+++ b/src/components/waveform.ui
@@ -226,9 +226,31 @@
-
-
+
- Mirror
+ Opacity
+
+
+ Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter
+
+
+
+ -
+
+
+ QAbstractSpinBox::UpDownArrows
+
+
+ %
+
+
+ 10
+
+
+ 400
+
+
+ 100
@@ -263,6 +285,75 @@
+ -
+
+
-
+
+
+ Compress
+
+
+
+ -
+
+
+ Mono
+
+
+
+ -
+
+
+ Mirror
+
+
+
+ -
+
+
+ Qt::Horizontal
+
+
+
+ 40
+ 20
+
+
+
+
+ -
+
+
+ Amplitude
+
+
+
+ -
+
+
-
+
+ Linear
+
+
+ -
+
+ Logarithmic
+
+
+ -
+
+ Square root
+
+
+ -
+
+ Cubic root
+
+
+
+
+
+
-
diff --git a/src/toolkit/common.py b/src/toolkit/common.py
index 128ed08..5d424e0 100644
--- a/src/toolkit/common.py
+++ b/src/toolkit/common.py
@@ -6,22 +6,9 @@ import string
import os
import sys
import subprocess
-import signal
-import math
from collections import OrderedDict
-def scale(scale, width, height, returntype=None):
- width = (float(width) / 100.0) * float(scale)
- height = (float(height) / 100.0) * float(scale)
- if returntype == str:
- return (str(math.ceil(width)), str(math.ceil(height)))
- elif returntype == int:
- return (math.ceil(width), math.ceil(height))
- else:
- return (width, height)
-
-
def badName(name):
'''Returns whether a name contains non-alphanumeric chars'''
return any([letter in string.punctuation for letter in name])
@@ -69,14 +56,6 @@ def checkOutput(commandList, **kwargs):
return subprocess.check_output(commandList, **kwargs)
-@pipeWrapper
-def openPipe(commandList, **kwargs):
- return subprocess.Popen(commandList, **kwargs)
-
-def closePipe(pipe):
- pipe.stdout.close()
- pipe.send_signal(signal.SIGINT)
-
def disableWhenEncoding(func):
def decorator(self, *args, **kwargs):
if self.encoding:
diff --git a/src/toolkit/ffmpeg.py b/src/toolkit/ffmpeg.py
index fea9d4e..e37282f 100644
--- a/src/toolkit/ffmpeg.py
+++ b/src/toolkit/ffmpeg.py
@@ -6,10 +6,12 @@ import sys
import os
import subprocess
import threading
+import signal
from queue import PriorityQueue
import core
-from toolkit.common import checkOutput, openPipe
+from toolkit.common import checkOutput, pipeWrapper
+from component import ComponentError
class FfmpegVideo:
@@ -60,7 +62,8 @@ class FfmpegVideo:
kwargs['filter_']
)
self.command.extend([
- '-vcodec', 'rawvideo', '-',
+ '-s:v', '%sx%s' % (self.width, self.height),
+ '-codec:v', 'rawvideo', '-',
])
self.frameBuffer = PriorityQueue()
@@ -85,9 +88,11 @@ class FfmpegVideo:
self.frameBuffer.task_done()
def fillBuffer(self):
+ import sys
+ print(self.command)
self.pipe = openPipe(
self.command, stdin=subprocess.DEVNULL, stdout=subprocess.PIPE,
- stderr=subprocess.DEVNULL, bufsize=10**8
+ stderr=sys.__stdout__, bufsize=10**8
)
while True:
if self.parent.canceled:
@@ -100,7 +105,7 @@ class FfmpegVideo:
self.frameBuffer.put((self.frameNo-1, self.lastFrame))
continue
except AttributeError:
- Video.threadError = ComponentError(self.component, 'video')
+ FfmpegVideo.threadError = ComponentError(self.component, 'video')
break
self.currentFrame = self.pipe.stdout.read(self.chunkSize)
@@ -109,6 +114,16 @@ class FfmpegVideo:
self.lastFrame = self.currentFrame
+@pipeWrapper
+def openPipe(commandList, **kwargs):
+ return subprocess.Popen(commandList, **kwargs)
+
+
+def closePipe(pipe):
+ pipe.stdout.close()
+ pipe.send_signal(signal.SIGINT)
+
+
def findFfmpeg():
if getattr(sys, 'frozen', False):
# The application is frozen
@@ -347,7 +362,12 @@ def getAudioDuration(filename):
except subprocess.CalledProcessError as ex:
fileInfo = ex.output
- info = fileInfo.decode("utf-8").split('\n')
+ try:
+ info = fileInfo.decode("utf-8").split('\n')
+ except UnicodeDecodeError as e:
+ print('Unicode error:', str(e))
+ return False
+
for line in info:
if 'Duration' in line:
d = line.split(',')[0]
diff --git a/src/toolkit/frame.py b/src/toolkit/frame.py
index b66e037..f42d4c9 100644
--- a/src/toolkit/frame.py
+++ b/src/toolkit/frame.py
@@ -6,6 +6,7 @@ from PIL import Image
from PIL.ImageQt import ImageQt
import sys
import os
+import math
import core
@@ -41,6 +42,17 @@ class PaintColor(QtGui.QColor):
super().__init__(b, g, r, a)
+def scale(scale, width, height, returntype=None):
+ width = (float(width) / 100.0) * float(scale)
+ height = (float(height) / 100.0) * float(scale)
+ if returntype == str:
+ return (str(math.ceil(width)), str(math.ceil(height)))
+ elif returntype == int:
+ return (math.ceil(width), math.ceil(height))
+ else:
+ return (width, height)
+
+
def defaultSize(framefunc):
'''Makes width/height arguments optional'''
def decorator(*args):
diff --git a/src/video_thread.py b/src/video_thread.py
index f27ec21..5963def 100644
--- a/src/video_thread.py
+++ b/src/video_thread.py
@@ -19,9 +19,11 @@ import time
import signal
from component import ComponentError
-from toolkit import openPipe
-from toolkit.ffmpeg import readAudioFile, createFfmpegCommand
from toolkit.frame import Checkerboard
+from toolkit.ffmpeg import (
+ openPipe, readAudioFile,
+ getAudioDuration, createFfmpegCommand
+)
class Worker(QtCore.QObject):
@@ -132,15 +134,24 @@ class Worker(QtCore.QObject):
# =~=~=~=~=~=~=~=~=~=~=~=~=~=~=~=~=~=~=~==~=~=~=~=~=~=~=~=~=~=~=~=~=~
# READ AUDIO, INITIALIZE COMPONENTS, OPEN A PIPE TO FFMPEG
# =~=~=~=~=~=~=~=~=~=~=~=~=~=~=~=~=~=~=~==~=~=~=~=~=~=~=~=~=~=~=~=~=~
-
- self.progressBarSetText.emit("Loading audio file...")
- audioFileTraits = readAudioFile(
- self.inputFile, self
- )
- if audioFileTraits is None:
- self.cancelExport()
- return
- self.completeAudioArray, duration = audioFileTraits
+ if any([
+ True if 'pcm' in comp.properties() else False
+ for comp in self.components
+ ]):
+ self.progressBarSetText.emit("Loading audio file...")
+ audioFileTraits = readAudioFile(
+ self.inputFile, self
+ )
+ if audioFileTraits is None:
+ self.cancelExport()
+ return
+ self.completeAudioArray, duration = audioFileTraits
+ else:
+ duration = getAudioDuration(self.inputFile)
+ class FakeList:
+ def __len__(self):
+ return int((duration * 44100) + 44100) - 1470
+ self.completeAudioArray = FakeList()
self.progressBarUpdate.emit(0)
self.progressBarSetText.emit("Starting components...")
@@ -284,7 +295,10 @@ class Worker(QtCore.QObject):
numpy.seterr(all='print')
- self.out_pipe.stdin.close()
+ try:
+ self.out_pipe.stdin.close()
+ except BrokenPipeError:
+ print('Broken pipe to ffmpeg!')
if self.out_pipe.stderr is not None:
print(self.out_pipe.stderr.read())
self.out_pipe.stderr.close()
--
cgit v1.2.3
From 5784cdbcf87556b61519782cd1fc27065ffbc631 Mon Sep 17 00:00:00 2001
From: tassaron
Date: Tue, 1 Aug 2017 21:57:36 -0400
Subject: x/y pixel values update to match output resolution
---
src/component.py | 39 ++++++++++++++++++++++++++++++++++++---
src/components/color.py | 3 +++
src/components/image.py | 3 +++
src/components/original.py | 2 ++
src/components/spectrum.py | 3 +++
src/components/text.py | 19 +++++++++++--------
src/components/video.py | 3 +++
src/components/waveform.py | 3 +++
src/mainwindow.py | 5 ++++-
9 files changed, 68 insertions(+), 12 deletions(-)
(limited to 'src/components/video.py')
diff --git a/src/component.py b/src/component.py
index d47aeae..5dfe2ab 100644
--- a/src/component.py
+++ b/src/component.py
@@ -6,6 +6,7 @@ from PyQt5 import uic, QtCore, QtWidgets
from PyQt5.QtGui import QColor
import os
import sys
+import math
import time
from toolkit.frame import BlankFrame
@@ -176,7 +177,9 @@ class Component(QtCore.QObject, metaclass=ComponentMetaclass):
self._presetNames = {}
self._commandArgs = {}
self._colorWidgets = {}
+ self._colorFuncs = {}
self._relativeWidgets = {}
+ self._relativeValues = {}
self._lockedProperties = None
self._lockedError = None
@@ -291,14 +294,44 @@ class Component(QtCore.QObject, metaclass=ComponentMetaclass):
'''
for attr, widget in self._trackedWidgets.items():
if attr in self._colorWidgets:
+ # Color Widgets: text stored as tuple & update the button color
rgbTuple = rgbFromString(widget.text())
- setattr(self, attr, rgbTuple)
btnStyle = (
"QPushButton { background-color : %s; outline: none; }"
- % QColor(*rgbTuple).name()
- )
+ % QColor(*rgbTuple).name())
self._colorWidgets[attr].setStyleSheet(btnStyle)
+ setattr(self, attr, rgbTuple)
+
+ elif attr in self._relativeWidgets:
+ # Relative widgets: number scales to fit export resolution
+ if self._relativeWidgets[attr] == 'x':
+ dimension = self.width
+ else:
+ dimension = self.height
+ try:
+ oldUserValue = getattr(self, attr)
+ except AttributeError:
+ oldUserValue = self._trackedWidgets[attr].value()
+ newUserValue = self._trackedWidgets[attr].value()
+ newRelativeVal = newUserValue / dimension
+
+ if attr in self._relativeValues:
+ if oldUserValue == newUserValue:
+ oldRelativeVal = self._relativeValues[attr]
+ if oldRelativeVal != newRelativeVal:
+ # Float changed without pixel value changing, which
+ # means the pixel value needs to be updated
+ self._trackedWidgets[attr].blockSignals(True)
+ self._trackedWidgets[attr].setValue(
+ math.ceil(dimension * oldRelativeVal))
+ self._trackedWidgets[attr].blockSignals(False)
+ if oldUserValue != newUserValue \
+ or attr not in self._relativeValues:
+ self._relativeValues[attr] = newRelativeVal
+ setattr(self, attr, self._trackedWidgets[attr].value())
+
else:
+ # Normal tracked widget
setattr(self, attr, getWidgetValue(widget))
if not self.core.openingProject:
diff --git a/src/components/color.py b/src/components/color.py
index d6fffc6..703caca 100644
--- a/src/components/color.py
+++ b/src/components/color.py
@@ -60,6 +60,9 @@ class Component(Component):
}, colorWidgets={
'color1': self.page.pushButton_color1,
'color2': self.page.pushButton_color2,
+ }, relativeWidgets={
+ 'x': 'x',
+ 'y': 'y',
},
)
diff --git a/src/components/image.py b/src/components/image.py
index a96f127..2ffa5a1 100644
--- a/src/components/image.py
+++ b/src/components/image.py
@@ -28,6 +28,9 @@ class Component(Component):
'imagePath': 'image',
'xPosition': 'x',
'yPosition': 'y',
+ }, relativeWidgets={
+ 'xPosition': 'x',
+ 'yPosition': 'y',
},
)
diff --git a/src/components/original.py b/src/components/original.py
index 950ac7b..67e3239 100644
--- a/src/components/original.py
+++ b/src/components/original.py
@@ -40,6 +40,8 @@ class Component(Component):
'y': self.page.spinBox_y,
}, colorWidgets={
'visColor': self.page.pushButton_visColor,
+ }, relativeWidgets={
+ 'y': 'y',
})
def previewRender(self):
diff --git a/src/components/spectrum.py b/src/components/spectrum.py
index 8ab8404..2cc641d 100644
--- a/src/components/spectrum.py
+++ b/src/components/spectrum.py
@@ -49,6 +49,9 @@ class Component(Component):
'compress': self.page.checkBox_compress,
'mono': self.page.checkBox_mono,
'hue': self.page.spinBox_hue,
+ }, relativeWidgets={
+ 'x': 'x',
+ 'y': 'y',
}
)
for widget in self._trackedWidgets.values():
diff --git a/src/components/text.py b/src/components/text.py
index 1fe3467..0f87038 100644
--- a/src/components/text.py
+++ b/src/components/text.py
@@ -17,15 +17,12 @@ class Component(Component):
def widget(self, *args):
super().widget(*args)
- height = int(self.settings.value('outputHeight'))
- width = int(self.settings.value('outputWidth'))
+ # height = int(self.settings.value('outputHeight'))
+ # width = int(self.settings.value('outputWidth'))
self.textColor = (255, 255, 255)
self.title = 'Text'
self.alignment = 1
- self.fontSize = height / 13.5
- fm = QtGui.QFontMetrics(self.titleFont)
- self.xPosition = width / 2 - fm.width(self.title)/2
- self.yPosition = height / 2 * 1.036
+ self.fontSize = self.height / 13.5
self.page.comboBox_textAlign.addItem("Left")
self.page.comboBox_textAlign.addItem("Middle")
@@ -35,8 +32,11 @@ class Component(Component):
self.page.lineEdit_title.setText(self.title)
self.page.comboBox_textAlign.setCurrentIndex(int(self.alignment))
self.page.spinBox_fontSize.setValue(int(self.fontSize))
- self.page.spinBox_xTextAlign.setValue(int(self.xPosition))
- self.page.spinBox_yTextAlign.setValue(int(self.yPosition))
+
+ fm = QtGui.QFontMetrics(self.titleFont)
+ self.page.spinBox_xTextAlign.setValue(
+ self.width / 2 - fm.width(self.title)/2)
+ self.page.spinBox_yTextAlign.setValue(self.height / 2 * 1.036)
self.page.fontComboBox_titleFont.currentFontChanged.connect(
self.update
@@ -50,6 +50,9 @@ class Component(Component):
'yPosition': self.page.spinBox_yTextAlign,
}, colorWidgets={
'textColor': self.page.pushButton_textColor,
+ }, relativeWidgets={
+ 'xPosition': 'x',
+ 'yPosition': 'y',
})
def update(self):
diff --git a/src/components/video.py b/src/components/video.py
index 6cd16e5..3569d17 100644
--- a/src/components/video.py
+++ b/src/components/video.py
@@ -38,6 +38,9 @@ class Component(Component):
'loopVideo': 'loop',
'xPosition': 'x',
'yPosition': 'y',
+ }, relativeWidgets={
+ 'xPosition': 'x',
+ 'yPosition': 'y',
}
)
diff --git a/src/components/waveform.py b/src/components/waveform.py
index 9c3cf86..a25116b 100644
--- a/src/components/waveform.py
+++ b/src/components/waveform.py
@@ -41,6 +41,9 @@ class Component(Component):
'mono': self.page.checkBox_mono,
}, colorWidgets={
'color': self.page.pushButton_color,
+ }, relativeWidgets={
+ 'x': 'x',
+ 'y': 'y',
}
)
diff --git a/src/mainwindow.py b/src/mainwindow.py
index d9e95e2..1c8806d 100644
--- a/src/mainwindow.py
+++ b/src/mainwindow.py
@@ -644,9 +644,12 @@ class MainWindow(QtWidgets.QMainWindow):
def updateResolution(self):
resIndex = int(self.window.comboBox_resolution.currentIndex())
res = Core.resolutions[resIndex].split('x')
+ changed = res[0] != self.settings.value("outputWidth")
self.settings.setValue('outputWidth', res[0])
self.settings.setValue('outputHeight', res[1])
- self.drawPreview()
+ if changed:
+ for i in range(len(self.core.selectedComponents)):
+ self.core.updateComponent(i)
def drawPreview(self, force=False, **kwargs):
'''Use autosave keyword arg to force saving or not saving if needed'''
--
cgit v1.2.3
From 6611492b30a7daf7bdbe77f6e12f9d322bdd90c1 Mon Sep 17 00:00:00 2001
From: tassaron
Date: Thu, 3 Aug 2017 00:44:46 -0400
Subject: relative gradients & last good frame used for preview errors
---
src/components/color.py | 5 +++++
src/components/spectrum.py | 15 ++++++++++-----
src/components/text.py | 2 --
src/components/video.py | 15 ++++-----------
src/components/waveform.py | 15 ++++++++++-----
5 files changed, 29 insertions(+), 23 deletions(-)
(limited to 'src/components/video.py')
diff --git a/src/components/color.py b/src/components/color.py
index 2b100d9..f5d618e 100644
--- a/src/components/color.py
+++ b/src/components/color.py
@@ -65,6 +65,11 @@ class Component(Component):
'y': 'y',
'sizeWidth': 'x',
'sizeHeight': 'y',
+ 'RG_start': 'x',
+ 'LG_start': 'x',
+ 'RG_end': 'x',
+ 'LG_end': 'x',
+ 'RG_centre': 'x',
},
)
diff --git a/src/components/spectrum.py b/src/components/spectrum.py
index 2cc641d..9a0c59a 100644
--- a/src/components/spectrum.py
+++ b/src/components/spectrum.py
@@ -20,6 +20,7 @@ class Component(Component):
def widget(self, *args):
self.previewFrame = None
super().widget(*args)
+ self._image = BlankFrame(self.width, self.height)
self.chunkSize = 4 * self.width * self.height
self.changedOptions = True
@@ -268,11 +269,15 @@ class Component(Component):
return changed
def finalizeFrame(self, imageData):
- image = Image.frombytes(
- 'RGBA',
- scale(self.scale, self.width, self.height, int),
- imageData
- )
+ try:
+ image = Image.frombytes(
+ 'RGBA',
+ scale(self.scale, self.width, self.height, int),
+ imageData
+ )
+ self._image = image
+ except ValueError:
+ image = self._image
if self.scale != 100 \
or self.x != 0 or self.y != 0:
frame = BlankFrame(self.width, self.height)
diff --git a/src/components/text.py b/src/components/text.py
index be4de4a..2a5d433 100644
--- a/src/components/text.py
+++ b/src/components/text.py
@@ -17,8 +17,6 @@ class Component(Component):
def widget(self, *args):
super().widget(*args)
- # height = int(self.settings.value('outputHeight'))
- # width = int(self.settings.value('outputWidth'))
self.textColor = (255, 255, 255)
self.title = 'Text'
self.alignment = 1
diff --git a/src/components/video.py b/src/components/video.py
index 3569d17..2cd67c6 100644
--- a/src/components/video.py
+++ b/src/components/video.py
@@ -16,12 +16,12 @@ class Component(Component):
def widget(self, *args):
self.videoPath = ''
- self.badVideo = False
self.badAudio = False
self.x = 0
self.y = 0
self.loopVideo = False
super().widget(*args)
+ self._image = BlankFrame(self.width, self.height)
self.page.pushButton_video.clicked.connect(self.pickVideo)
self.trackWidgets(
{
@@ -70,8 +70,6 @@ class Component(Component):
if not self.videoPath:
self.lockError("There is no video selected.")
- elif self.badVideo:
- self.lockError("Could not identify an audio stream in this video.")
elif not os.path.exists(self.videoPath):
self.lockError("The video selected does not exist!")
elif os.path.realpath(self.videoPath) == os.path.realpath(outputFile):
@@ -199,14 +197,10 @@ class Component(Component):
'RGBA',
scale(self.scale, self.width, self.height, int),
imageData)
-
+ self._image = image
except ValueError:
- print(
- '### BAD VIDEO SELECTED ###\n'
- 'Video will not export with these settings'
- )
- self.badVideo = True
- return BlankFrame(self.width, self.height)
+ # use last good frame
+ image = self._image
if self.scale != 100 \
or self.xPosition != 0 or self.yPosition != 0:
@@ -214,5 +208,4 @@ class Component(Component):
frame.paste(image, box=(self.xPosition, self.yPosition))
else:
frame = image
- self.badVideo = False
return frame
diff --git a/src/components/waveform.py b/src/components/waveform.py
index a25116b..526e6fb 100644
--- a/src/components/waveform.py
+++ b/src/components/waveform.py
@@ -19,6 +19,7 @@ class Component(Component):
def widget(self, *args):
super().widget(*args)
+ self._image = BlankFrame(self.width, self.height)
self.page.lineEdit_color.setText('255,255,255')
@@ -178,11 +179,15 @@ class Component(Component):
self.chunkSize = 4 * width * height
def finalizeFrame(self, imageData):
- image = Image.frombytes(
- 'RGBA',
- scale(self.scale, self.width, self.height, int),
- imageData
- )
+ try:
+ image = Image.frombytes(
+ 'RGBA',
+ scale(self.scale, self.width, self.height, int),
+ imageData
+ )
+ self._image = image
+ except ValueError:
+ image = self._image
if self.scale != 100 \
or self.x != 0 or self.y != 0:
frame = BlankFrame(self.width, self.height)
--
cgit v1.2.3
From 219e846984bb10e9674432fa7aeac4157635c743 Mon Sep 17 00:00:00 2001
From: tassaron
Date: Thu, 3 Aug 2017 12:16:57 -0400
Subject: relativeWidgets might as well be a list
---
src/component.py | 5 +---
src/components/color.py | 63 +++++++++++++++++++++-------------------------
src/components/image.py | 36 ++++++++++++--------------
src/components/original.py | 6 ++---
src/components/spectrum.py | 47 ++++++++++++++++------------------
src/components/text.py | 8 +++---
src/components/video.py | 37 +++++++++++++--------------
src/components/waveform.py | 35 ++++++++++++--------------
8 files changed, 106 insertions(+), 131 deletions(-)
(limited to 'src/components/video.py')
diff --git a/src/component.py b/src/component.py
index 5dfe2ab..c5bc44b 100644
--- a/src/component.py
+++ b/src/component.py
@@ -304,10 +304,7 @@ class Component(QtCore.QObject, metaclass=ComponentMetaclass):
elif attr in self._relativeWidgets:
# Relative widgets: number scales to fit export resolution
- if self._relativeWidgets[attr] == 'x':
- dimension = self.width
- else:
- dimension = self.height
+ dimension = self.width
try:
oldUserValue = getattr(self, attr)
except AttributeError:
diff --git a/src/components/color.py b/src/components/color.py
index f5d618e..5d1233e 100644
--- a/src/components/color.py
+++ b/src/components/color.py
@@ -37,41 +37,34 @@ class Component(Component):
self.page.comboBox_fill.addItem(label)
self.page.comboBox_fill.setCurrentIndex(0)
- self.trackWidgets(
- {
- 'x': self.page.spinBox_x,
- 'y': self.page.spinBox_y,
- 'sizeWidth': self.page.spinBox_width,
- 'sizeHeight': self.page.spinBox_height,
- 'trans': self.page.checkBox_trans,
- 'spread': self.page.comboBox_spread,
- 'stretch': self.page.checkBox_stretch,
- 'RG_start': self.page.spinBox_radialGradient_start,
- 'LG_start': self.page.spinBox_linearGradient_start,
- 'RG_end': self.page.spinBox_radialGradient_end,
- 'LG_end': self.page.spinBox_linearGradient_end,
- 'RG_centre': self.page.spinBox_radialGradient_spread,
- 'fillType': self.page.comboBox_fill,
- 'color1': self.page.lineEdit_color1,
- 'color2': self.page.lineEdit_color2,
- }, presetNames={
- 'sizeWidth': 'width',
- 'sizeHeight': 'height',
- }, colorWidgets={
- 'color1': self.page.pushButton_color1,
- 'color2': self.page.pushButton_color2,
- }, relativeWidgets={
- 'x': 'x',
- 'y': 'y',
- 'sizeWidth': 'x',
- 'sizeHeight': 'y',
- 'RG_start': 'x',
- 'LG_start': 'x',
- 'RG_end': 'x',
- 'LG_end': 'x',
- 'RG_centre': 'x',
- },
- )
+ self.trackWidgets({
+ 'x': self.page.spinBox_x,
+ 'y': self.page.spinBox_y,
+ 'sizeWidth': self.page.spinBox_width,
+ 'sizeHeight': self.page.spinBox_height,
+ 'trans': self.page.checkBox_trans,
+ 'spread': self.page.comboBox_spread,
+ 'stretch': self.page.checkBox_stretch,
+ 'RG_start': self.page.spinBox_radialGradient_start,
+ 'LG_start': self.page.spinBox_linearGradient_start,
+ 'RG_end': self.page.spinBox_radialGradient_end,
+ 'LG_end': self.page.spinBox_linearGradient_end,
+ 'RG_centre': self.page.spinBox_radialGradient_spread,
+ 'fillType': self.page.comboBox_fill,
+ 'color1': self.page.lineEdit_color1,
+ 'color2': self.page.lineEdit_color2,
+ }, presetNames={
+ 'sizeWidth': 'width',
+ 'sizeHeight': 'height',
+ }, colorWidgets={
+ 'color1': self.page.pushButton_color1,
+ 'color2': self.page.pushButton_color2,
+ }, relativeWidgets=[
+ 'x', 'y',
+ 'sizeWidth', 'sizeHeight',
+ 'LG_start', 'LG_end',
+ 'RG_start', 'RG_end', 'RG_centre',
+ ])
def update(self):
fillType = self.page.comboBox_fill.currentIndex()
diff --git a/src/components/image.py b/src/components/image.py
index 2ffa5a1..19c4796 100644
--- a/src/components/image.py
+++ b/src/components/image.py
@@ -13,26 +13,22 @@ class Component(Component):
def widget(self, *args):
super().widget(*args)
self.page.pushButton_image.clicked.connect(self.pickImage)
- self.trackWidgets(
- {
- 'imagePath': self.page.lineEdit_image,
- 'scale': self.page.spinBox_scale,
- 'rotate': self.page.spinBox_rotate,
- 'color': self.page.spinBox_color,
- 'xPosition': self.page.spinBox_x,
- 'yPosition': self.page.spinBox_y,
- 'stretched': self.page.checkBox_stretch,
- 'mirror': self.page.checkBox_mirror,
- },
- presetNames={
- 'imagePath': 'image',
- 'xPosition': 'x',
- 'yPosition': 'y',
- }, relativeWidgets={
- 'xPosition': 'x',
- 'yPosition': 'y',
- },
- )
+ self.trackWidgets({
+ 'imagePath': self.page.lineEdit_image,
+ 'scale': self.page.spinBox_scale,
+ 'rotate': self.page.spinBox_rotate,
+ 'color': self.page.spinBox_color,
+ 'xPosition': self.page.spinBox_x,
+ 'yPosition': self.page.spinBox_y,
+ 'stretched': self.page.checkBox_stretch,
+ }, presetNames={
+ 'mirror': self.page.checkBox_mirror,
+ 'imagePath': 'image',
+ 'xPosition': 'x',
+ 'yPosition': 'y',
+ }, relativeWidgets=[
+ 'xPosition', 'yPosition',
+ ])
def previewRender(self):
return self.drawFrame(self.width, self.height)
diff --git a/src/components/original.py b/src/components/original.py
index 67e3239..f886374 100644
--- a/src/components/original.py
+++ b/src/components/original.py
@@ -40,9 +40,9 @@ class Component(Component):
'y': self.page.spinBox_y,
}, colorWidgets={
'visColor': self.page.pushButton_visColor,
- }, relativeWidgets={
- 'y': 'y',
- })
+ }, relativeWidgets=[
+ 'y',
+ ])
def previewRender(self):
spectrum = numpy.fromfunction(
diff --git a/src/components/spectrum.py b/src/components/spectrum.py
index 9a0c59a..666e20a 100644
--- a/src/components/spectrum.py
+++ b/src/components/spectrum.py
@@ -30,31 +30,28 @@ class Component(Component):
self.update
)
- self.trackWidgets(
- {
- 'filterType': self.page.comboBox_filterType,
- 'window': self.page.comboBox_window,
- 'mode': self.page.comboBox_mode,
- 'amplitude': self.page.comboBox_amplitude0,
- 'amplitude1': self.page.comboBox_amplitude1,
- 'amplitude2': self.page.comboBox_amplitude2,
- 'display': self.page.comboBox_display,
- 'zoom': self.page.spinBox_zoom,
- 'tc': self.page.spinBox_tc,
- 'x': self.page.spinBox_x,
- 'y': self.page.spinBox_y,
- 'mirror': self.page.checkBox_mirror,
- 'draw': self.page.checkBox_draw,
- 'scale': self.page.spinBox_scale,
- 'color': self.page.comboBox_color,
- 'compress': self.page.checkBox_compress,
- 'mono': self.page.checkBox_mono,
- 'hue': self.page.spinBox_hue,
- }, relativeWidgets={
- 'x': 'x',
- 'y': 'y',
- }
- )
+ self.trackWidgets({
+ 'filterType': self.page.comboBox_filterType,
+ 'window': self.page.comboBox_window,
+ 'mode': self.page.comboBox_mode,
+ 'amplitude': self.page.comboBox_amplitude0,
+ 'amplitude1': self.page.comboBox_amplitude1,
+ 'amplitude2': self.page.comboBox_amplitude2,
+ 'display': self.page.comboBox_display,
+ 'zoom': self.page.spinBox_zoom,
+ 'tc': self.page.spinBox_tc,
+ 'x': self.page.spinBox_x,
+ 'y': self.page.spinBox_y,
+ 'mirror': self.page.checkBox_mirror,
+ 'draw': self.page.checkBox_draw,
+ 'scale': self.page.spinBox_scale,
+ 'color': self.page.comboBox_color,
+ 'compress': self.page.checkBox_compress,
+ 'mono': self.page.checkBox_mono,
+ 'hue': self.page.spinBox_hue,
+ }, relativeWidgets=[
+ 'x', 'y',
+ ])
for widget in self._trackedWidgets.values():
connectWidget(widget, lambda: self.changed())
diff --git a/src/components/text.py b/src/components/text.py
index 2a5d433..b7c244e 100644
--- a/src/components/text.py
+++ b/src/components/text.py
@@ -48,11 +48,9 @@ class Component(Component):
'yPosition': self.page.spinBox_yTextAlign,
}, colorWidgets={
'textColor': self.page.pushButton_textColor,
- }, relativeWidgets={
- 'xPosition': 'x',
- 'yPosition': 'y',
- 'fontSize': 'y',
- })
+ }, relativeWidgets=[
+ 'xPosition', 'yPosition', 'fontSize',
+ ])
def update(self):
self.titleFont = self.page.fontComboBox_titleFont.currentFont()
diff --git a/src/components/video.py b/src/components/video.py
index 2cd67c6..b6bdd52 100644
--- a/src/components/video.py
+++ b/src/components/video.py
@@ -23,26 +23,23 @@ class Component(Component):
super().widget(*args)
self._image = BlankFrame(self.width, self.height)
self.page.pushButton_video.clicked.connect(self.pickVideo)
- self.trackWidgets(
- {
- 'videoPath': self.page.lineEdit_video,
- 'loopVideo': self.page.checkBox_loop,
- 'useAudio': self.page.checkBox_useAudio,
- 'distort': self.page.checkBox_distort,
- 'scale': self.page.spinBox_scale,
- 'volume': self.page.spinBox_volume,
- 'xPosition': self.page.spinBox_x,
- 'yPosition': self.page.spinBox_y,
- }, presetNames={
- 'videoPath': 'video',
- 'loopVideo': 'loop',
- 'xPosition': 'x',
- 'yPosition': 'y',
- }, relativeWidgets={
- 'xPosition': 'x',
- 'yPosition': 'y',
- }
- )
+ self.trackWidgets({
+ 'videoPath': self.page.lineEdit_video,
+ 'loopVideo': self.page.checkBox_loop,
+ 'useAudio': self.page.checkBox_useAudio,
+ 'distort': self.page.checkBox_distort,
+ 'scale': self.page.spinBox_scale,
+ 'volume': self.page.spinBox_volume,
+ 'xPosition': self.page.spinBox_x,
+ 'yPosition': self.page.spinBox_y,
+ }, presetNames={
+ 'videoPath': 'video',
+ 'loopVideo': 'loop',
+ 'xPosition': 'x',
+ 'yPosition': 'y',
+ }, relativeWidgets=[
+ 'xPosition', 'yPosition',
+ ])
def update(self):
if self.page.checkBox_useAudio.isChecked():
diff --git a/src/components/waveform.py b/src/components/waveform.py
index 526e6fb..71cbcac 100644
--- a/src/components/waveform.py
+++ b/src/components/waveform.py
@@ -28,25 +28,22 @@ class Component(Component):
self.update
)
- self.trackWidgets(
- {
- 'color': self.page.lineEdit_color,
- 'mode': self.page.comboBox_mode,
- 'amplitude': self.page.comboBox_amplitude,
- 'x': self.page.spinBox_x,
- 'y': self.page.spinBox_y,
- 'mirror': self.page.checkBox_mirror,
- 'scale': self.page.spinBox_scale,
- 'opacity': self.page.spinBox_opacity,
- 'compress': self.page.checkBox_compress,
- 'mono': self.page.checkBox_mono,
- }, colorWidgets={
- 'color': self.page.pushButton_color,
- }, relativeWidgets={
- 'x': 'x',
- 'y': 'y',
- }
- )
+ self.trackWidgets({
+ 'color': self.page.lineEdit_color,
+ 'mode': self.page.comboBox_mode,
+ 'amplitude': self.page.comboBox_amplitude,
+ 'x': self.page.spinBox_x,
+ 'y': self.page.spinBox_y,
+ 'mirror': self.page.checkBox_mirror,
+ 'scale': self.page.spinBox_scale,
+ 'opacity': self.page.spinBox_opacity,
+ 'compress': self.page.checkBox_compress,
+ 'mono': self.page.checkBox_mono,
+ }, colorWidgets={
+ 'color': self.page.pushButton_color,
+ }, relativeWidgets=[
+ 'x', 'y',
+ ])
def previewRender(self):
self.updateChunksize()
--
cgit v1.2.3