Merge branch 'component-backgrounds' of github.com:IamDH4/audio-visualizer-python into feature-newgui

This commit is contained in:
DH4 2017-06-06 02:07:13 -05:00
commit 4920fcc034
16 changed files with 1094 additions and 245 deletions

Binary file not shown.

Before

Width:  |  Height:  |  Size: 14 KiB

BIN
background.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.6 KiB

View File

@ -8,6 +8,13 @@ class Component:
# change this number to identify new versions of a component # change this number to identify new versions of a component
return 1 return 1
def cancel(self):
# make sure your component responds to these variables in frameRender()
self.canceled = True
def reset(self):
self.canceled = False
def preFrameRender(self, **kwargs): def preFrameRender(self, **kwargs):
for var, value in kwargs.items(): for var, value in kwargs.items():
exec('self.%s = value' % var) exec('self.%s = value' % var)
@ -66,4 +73,10 @@ class Component:
def savePreset(self): def savePreset(self):
return {} return {}
def cancel(self):
self.canceled = True
def reset(self):
self.canceled = False
''' '''

87
components/color.py Normal file
View File

@ -0,0 +1,87 @@
from PIL import Image, ImageDraw
from PyQt4 import uic, QtGui, QtCore
from PyQt4.QtGui import QColor
import os
from . import __base__
class Component(__base__.Component):
'''Color'''
def widget(self, parent):
self.parent = parent
page = uic.loadUi(os.path.join(os.path.dirname(os.path.realpath(__file__)), 'color.ui'))
self.color1 = (0,0,0)
self.color2 = (133,133,133)
self.x = 0
self.y = 0
page.lineEdit_color1.setText('%s,%s,%s' % self.color1)
page.lineEdit_color2.setText('%s,%s,%s' % self.color2)
page.pushButton_color1.clicked.connect(lambda: self.pickColor(1))
btnStyle = "QPushButton { background-color : %s; outline: none; }" % QColor(*self.color1).name()
page.pushButton_color1.setStyleSheet(btnStyle)
page.pushButton_color2.clicked.connect(lambda: self.pickColor(2))
btnStyle = "QPushButton { background-color : %s; outline: none; }" % QColor(*self.color2).name()
page.pushButton_color2.setStyleSheet(btnStyle)
# disable color #2 until non-default 'fill' option gets changed
page.lineEdit_color2.setDisabled(True)
page.pushButton_color2.setDisabled(True)
page.spinBox_x.setValue(self.x)
page.spinBox_x.setValue(self.y)
page.lineEdit_color1.textChanged.connect(self.update)
page.lineEdit_color2.textChanged.connect(self.update)
page.spinBox_x.valueChanged.connect(self.update)
page.spinBox_y.valueChanged.connect(self.update)
self.page = page
return page
def update(self):
self.color1 = self.RGBFromString(self.page.lineEdit_color1.text())
self.color2 = self.RGBFromString(self.page.lineEdit_color2.text())
self.x = self.page.spinBox_x.value()
self.y = self.page.spinBox_y.value()
self.parent.drawPreview()
def previewRender(self, previewWorker):
width = int(previewWorker.core.settings.value('outputWidth'))
height = int(previewWorker.core.settings.value('outputHeight'))
return self.drawFrame(width, height)
def preFrameRender(self, **kwargs):
super().preFrameRender(**kwargs)
return ['static']
def frameRender(self, moduleNo, arrayNo, frameNo):
width = int(self.worker.core.settings.value('outputWidth'))
height = int(self.worker.core.settings.value('outputHeight'))
return self.drawFrame(width, height)
def drawFrame(self, width, height):
r,g,b = self.color1
return Image.new("RGBA", (width, height), (r, g, b, 255))
def loadPreset(self, pr):
self.page.lineEdit_color1.setText('%s,%s,%s' % pr['color1'])
self.page.lineEdit_color2.setText('%s,%s,%s' % pr['color2'])
btnStyle = "QPushButton { background-color : %s; outline: none; }" % QColor(*pr['color1']).name()
self.page.pushButton_color1.setStyleSheet(btnStyle)
btnStyle = "QPushButton { background-color : %s; outline: none; }" % QColor(*pr['color2']).name()
self.page.pushButton_color2.setStyleSheet(btnStyle)
def savePreset(self):
return {
'color1' : self.color1,
'color2' : self.color2,
}
def pickColor(self, num):
RGBstring, btnStyle = super().pickColor()
if not RGBstring:
return
if num == 1:
self.page.lineEdit_color1.setText(RGBstring)
self.page.pushButton_color1.setStyleSheet(btnStyle)
else:
self.page.lineEdit_color2.setText(RGBstring)
self.page.pushButton_color2.setStyleSheet(btnStyle)

306
components/color.ui Normal file
View File

@ -0,0 +1,306 @@
<?xml version="1.0" encoding="UTF-8"?>
<ui version="4.0">
<class>Form</class>
<widget class="QWidget" name="Form">
<property name="geometry">
<rect>
<x>0</x>
<y>0</y>
<width>586</width>
<height>197</height>
</rect>
</property>
<property name="windowTitle">
<string>Form</string>
</property>
<layout class="QVBoxLayout" name="verticalLayout_2">
<item>
<layout class="QVBoxLayout" name="verticalLayout">
<property name="leftMargin">
<number>4</number>
</property>
<item>
<layout class="QHBoxLayout" name="horizontalLayout_8">
<item>
<widget class="QLabel" name="label_textColor">
<property name="sizePolicy">
<sizepolicy hsizetype="Fixed" vsizetype="Preferred">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="minimumSize">
<size>
<width>31</width>
<height>0</height>
</size>
</property>
<property name="text">
<string>Color #1</string>
</property>
</widget>
</item>
<item>
<widget class="QPushButton" name="pushButton_color1">
<property name="maximumSize">
<size>
<width>32</width>
<height>32</height>
</size>
</property>
<property name="text">
<string/>
</property>
<property name="MaximumSize" stdset="0">
<size>
<width>32</width>
<height>32</height>
</size>
</property>
</widget>
</item>
<item>
<widget class="QLineEdit" name="lineEdit_color1">
<property name="sizePolicy">
<sizepolicy hsizetype="Fixed" vsizetype="Fixed">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="minimumSize">
<size>
<width>1</width>
<height>0</height>
</size>
</property>
<property name="maxLength">
<number>12</number>
</property>
</widget>
</item>
<item>
<spacer name="horizontalSpacer_9">
<property name="orientation">
<enum>Qt::Horizontal</enum>
</property>
<property name="sizeType">
<enum>QSizePolicy::Fixed</enum>
</property>
<property name="sizeHint" stdset="0">
<size>
<width>5</width>
<height>20</height>
</size>
</property>
</spacer>
</item>
<item>
<widget class="QLabel" name="label_textColor_2">
<property name="sizePolicy">
<sizepolicy hsizetype="Fixed" vsizetype="Preferred">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="minimumSize">
<size>
<width>31</width>
<height>0</height>
</size>
</property>
<property name="text">
<string>Color #2</string>
</property>
</widget>
</item>
<item>
<widget class="QPushButton" name="pushButton_color2">
<property name="maximumSize">
<size>
<width>32</width>
<height>32</height>
</size>
</property>
<property name="text">
<string/>
</property>
<property name="MaximumSize" stdset="0">
<size>
<width>32</width>
<height>32</height>
</size>
</property>
</widget>
</item>
<item>
<widget class="QLineEdit" name="lineEdit_color2">
<property name="sizePolicy">
<sizepolicy hsizetype="Minimum" vsizetype="Fixed">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="minimumSize">
<size>
<width>1</width>
<height>0</height>
</size>
</property>
<property name="maxLength">
<number>12</number>
</property>
</widget>
</item>
</layout>
</item>
<item>
<layout class="QHBoxLayout" name="horizontalLayout_7">
<property name="leftMargin">
<number>0</number>
</property>
<item>
<widget class="QLabel" name="label_textLayout">
<property name="sizePolicy">
<sizepolicy hsizetype="Fixed" vsizetype="Preferred">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="text">
<string>Fill </string>
</property>
</widget>
</item>
<item>
<widget class="QComboBox" name="comboBox_fill"/>
</item>
<item>
<spacer name="horizontalSpacer_6">
<property name="orientation">
<enum>Qt::Horizontal</enum>
</property>
<property name="sizeType">
<enum>QSizePolicy::Fixed</enum>
</property>
<property name="sizeHint" stdset="0">
<size>
<width>5</width>
<height>20</height>
</size>
</property>
</spacer>
</item>
<item>
<widget class="QLabel" name="label_xTitleAlign">
<property name="sizePolicy">
<sizepolicy hsizetype="Fixed" vsizetype="Preferred">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="text">
<string>X</string>
</property>
</widget>
</item>
<item>
<widget class="QSpinBox" name="spinBox_x">
<property name="sizePolicy">
<sizepolicy hsizetype="Fixed" vsizetype="Fixed">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="maximumSize">
<size>
<width>80</width>
<height>16777215</height>
</size>
</property>
<property name="baseSize">
<size>
<width>0</width>
<height>0</height>
</size>
</property>
<property name="minimum">
<number>0</number>
</property>
<property name="maximum">
<number>999999999</number>
</property>
<property name="value">
<number>0</number>
</property>
</widget>
</item>
<item>
<spacer name="horizontalSpacer_7">
<property name="orientation">
<enum>Qt::Horizontal</enum>
</property>
<property name="sizeType">
<enum>QSizePolicy::Fixed</enum>
</property>
<property name="sizeHint" stdset="0">
<size>
<width>5</width>
<height>20</height>
</size>
</property>
</spacer>
</item>
<item>
<widget class="QLabel" name="label_yTitleAlign">
<property name="sizePolicy">
<sizepolicy hsizetype="Fixed" vsizetype="Preferred">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="text">
<string>Y</string>
</property>
</widget>
</item>
<item>
<widget class="QSpinBox" name="spinBox_y">
<property name="sizePolicy">
<sizepolicy hsizetype="Fixed" vsizetype="Fixed">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="maximumSize">
<size>
<width>80</width>
<height>16777215</height>
</size>
</property>
<property name="maximum">
<number>999999999</number>
</property>
</widget>
</item>
</layout>
</item>
</layout>
</item>
<item>
<spacer name="verticalSpacer">
<property name="orientation">
<enum>Qt::Vertical</enum>
</property>
<property name="sizeHint" stdset="0">
<size>
<width>20</width>
<height>40</height>
</size>
</property>
</spacer>
</item>
</layout>
</widget>
<resources/>
<connections/>
</ui>

64
components/image.py Normal file
View File

@ -0,0 +1,64 @@
from PIL import Image, ImageDraw
from PyQt4 import uic, QtGui, QtCore
import os
from . import __base__
class Component(__base__.Component):
'''Image'''
def widget(self, parent):
self.parent = parent
self.settings = parent.settings
page = uic.loadUi(os.path.join(os.path.dirname(os.path.realpath(__file__)), 'image.ui'))
self.imagePath = ''
self.x = 0
self.y = 0
page.lineEdit_image.textChanged.connect(self.update)
page.pushButton_image.clicked.connect(self.pickImage)
self.page = page
return page
def update(self):
self.imagePath = self.page.lineEdit_image.text()
self.parent.drawPreview()
def previewRender(self, previewWorker):
width = int(previewWorker.core.settings.value('outputWidth'))
height = int(previewWorker.core.settings.value('outputHeight'))
return self.drawFrame(width, height)
def preFrameRender(self, **kwargs):
super().preFrameRender(**kwargs)
return ['static']
def frameRender(self, moduleNo, arrayNo, frameNo):
width = int(self.worker.core.settings.value('outputWidth'))
height = int(self.worker.core.settings.value('outputHeight'))
return self.drawFrame(width, height)
def drawFrame(self, width, height):
frame = Image.new("RGBA", (width, height), (0,0,0,0))
if self.imagePath and os.path.exists(self.imagePath):
image = Image.open(self.imagePath)
if image.size != (width, height):
image = image.resize((width, height), Image.ANTIALIAS)
frame.paste(image)
return frame
def loadPreset(self, pr):
self.page.lineEdit_image.setText(pr['image'])
def savePreset(self):
return {
'image' : self.imagePath,
}
def pickImage(self):
imgDir = self.settings.value("backgroundDir", os.path.expanduser("~"))
filename = QtGui.QFileDialog.getOpenFileName(self.page,
"Choose Image", imgDir, "Image Files (*.jpg *.png)")
if filename:
self.settings.setValue("backgroundDir", os.path.dirname(filename))
self.page.lineEdit_image.setText(filename)
self.update()

197
components/image.ui Normal file
View File

@ -0,0 +1,197 @@
<?xml version="1.0" encoding="UTF-8"?>
<ui version="4.0">
<class>Form</class>
<widget class="QWidget" name="Form">
<property name="geometry">
<rect>
<x>0</x>
<y>0</y>
<width>586</width>
<height>197</height>
</rect>
</property>
<property name="windowTitle">
<string>Form</string>
</property>
<layout class="QVBoxLayout" name="verticalLayout_2">
<item>
<layout class="QVBoxLayout" name="verticalLayout">
<property name="leftMargin">
<number>4</number>
</property>
<item>
<layout class="QHBoxLayout" name="horizontalLayout_8">
<item>
<widget class="QLabel" name="label_textColor">
<property name="sizePolicy">
<sizepolicy hsizetype="Fixed" vsizetype="Preferred">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="minimumSize">
<size>
<width>31</width>
<height>0</height>
</size>
</property>
<property name="text">
<string>Image</string>
</property>
</widget>
</item>
<item>
<widget class="QLineEdit" name="lineEdit_image">
<property name="minimumSize">
<size>
<width>1</width>
<height>0</height>
</size>
</property>
</widget>
</item>
<item>
<widget class="QPushButton" name="pushButton_image">
<property name="sizePolicy">
<sizepolicy hsizetype="Fixed" vsizetype="Fixed">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="minimumSize">
<size>
<width>1</width>
<height>0</height>
</size>
</property>
<property name="maximumSize">
<size>
<width>32</width>
<height>32</height>
</size>
</property>
<property name="text">
<string>...</string>
</property>
<property name="MaximumSize" stdset="0">
<size>
<width>32</width>
<height>32</height>
</size>
</property>
</widget>
</item>
<item>
<spacer name="horizontalSpacer_9">
<property name="orientation">
<enum>Qt::Horizontal</enum>
</property>
<property name="sizeType">
<enum>QSizePolicy::Fixed</enum>
</property>
<property name="sizeHint" stdset="0">
<size>
<width>5</width>
<height>20</height>
</size>
</property>
</spacer>
</item>
<item>
<widget class="QLabel" name="label_xTitleAlign">
<property name="sizePolicy">
<sizepolicy hsizetype="Fixed" vsizetype="Preferred">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="text">
<string>X</string>
</property>
</widget>
</item>
<item>
<widget class="QSpinBox" name="spinBox_x">
<property name="sizePolicy">
<sizepolicy hsizetype="Fixed" vsizetype="Fixed">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="maximumSize">
<size>
<width>80</width>
<height>16777215</height>
</size>
</property>
<property name="maximum">
<number>999999999</number>
</property>
</widget>
</item>
<item>
<widget class="QLabel" name="label_yTitleAlign">
<property name="sizePolicy">
<sizepolicy hsizetype="Fixed" vsizetype="Preferred">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="text">
<string>Y</string>
</property>
</widget>
</item>
<item>
<widget class="QSpinBox" name="spinBox_y">
<property name="sizePolicy">
<sizepolicy hsizetype="Fixed" vsizetype="Fixed">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="maximumSize">
<size>
<width>80</width>
<height>16777215</height>
</size>
</property>
<property name="baseSize">
<size>
<width>0</width>
<height>0</height>
</size>
</property>
<property name="minimum">
<number>0</number>
</property>
<property name="maximum">
<number>999999999</number>
</property>
<property name="value">
<number>0</number>
</property>
</widget>
</item>
</layout>
</item>
</layout>
</item>
<item>
<spacer name="verticalSpacer">
<property name="orientation">
<enum>Qt::Vertical</enum>
</property>
<property name="sizeHint" stdset="0">
<size>
<width>20</width>
<height>40</height>
</size>
</property>
</spacer>
</item>
</layout>
</widget>
<resources/>
<connections/>
</ui>

View File

@ -58,6 +58,8 @@ class Component(__base__.Component):
self.smoothConstantUp = 0.8 self.smoothConstantUp = 0.8
self.lastSpectrum = None self.lastSpectrum = None
self.spectrumArray = {} self.spectrumArray = {}
self.width = int(self.worker.core.settings.value('outputWidth'))
self.height = int(self.worker.core.settings.value('outputHeight'))
for i in range(0, len(self.completeAudioArray), self.sampleSize): for i in range(0, len(self.completeAudioArray), self.sampleSize):
if self.canceled: if self.canceled:
@ -73,11 +75,8 @@ class Component(__base__.Component):
self.progressBarSetText.emit(pStr) self.progressBarSetText.emit(pStr)
self.progressBarUpdate.emit(int(progress)) self.progressBarUpdate.emit(int(progress))
def frameRender(self, moduleNo, arrayNo, frameNo):
def frameRender(self, moduleNo, frameNo): return self.drawBars(self.width, self.height, self.spectrumArray[arrayNo], self.visColor, self.layout)
width = int(self.worker.core.settings.value('outputWidth'))
height = int(self.worker.core.settings.value('outputHeight'))
return self.drawBars(width, height, self.spectrumArray[frameNo], self.visColor, self.layout)
def pickColor(self): def pickColor(self):
RGBstring, btnStyle = super().pickColor() RGBstring, btnStyle = super().pickColor()
@ -154,12 +153,3 @@ class Component(__base__.Component):
return im return im
def cancel(self):
self.canceled = True
def reset(self):
self.canceled = False

View File

@ -18,7 +18,6 @@ class Component(__base__.Component):
self.parent = parent self.parent = parent
self.textColor = (255,255,255) self.textColor = (255,255,255)
self.title = 'Text' self.title = 'Text'
self.titleFont = None
self.alignment = 1 self.alignment = 1
self.fontSize = height / 13.5 self.fontSize = height / 13.5
self.xPosition = width / 2 self.xPosition = width / 2
@ -35,8 +34,6 @@ class Component(__base__.Component):
page.pushButton_textColor.setStyleSheet(btnStyle) page.pushButton_textColor.setStyleSheet(btnStyle)
page.lineEdit_title.setText(self.title) page.lineEdit_title.setText(self.title)
#if self.titleFont:
# page.fontComboBox_titleFont.setCurrentFont(QFont(self.titleFont))
page.comboBox_textAlign.setCurrentIndex(int(self.alignment)) page.comboBox_textAlign.setCurrentIndex(int(self.alignment))
page.spinBox_fontSize.setValue(int(self.fontSize)) page.spinBox_fontSize.setValue(int(self.fontSize))
page.spinBox_xTextAlign.setValue(int(self.xPosition)) page.spinBox_xTextAlign.setValue(int(self.xPosition))
@ -109,7 +106,7 @@ class Component(__base__.Component):
super().preFrameRender(**kwargs) super().preFrameRender(**kwargs)
return ['static'] return ['static']
def frameRender(self, moduleNo, frameNo): def frameRender(self, moduleNo, arrayNo, frameNo):
width = int(self.worker.core.settings.value('outputWidth')) width = int(self.worker.core.settings.value('outputWidth'))
height = int(self.worker.core.settings.value('outputHeight')) height = int(self.worker.core.settings.value('outputHeight'))
return self.addText(width, height) return self.addText(width, height)
@ -142,9 +139,3 @@ class Component(__base__.Component):
return return
self.page.lineEdit_textColor.setText(RGBstring) self.page.lineEdit_textColor.setText(RGBstring)
self.page.pushButton_textColor.setStyleSheet(btnStyle) self.page.pushButton_textColor.setStyleSheet(btnStyle)
def cancel(self):
self.canceled = True
def reset(self):
self.canceled = False

141
components/video.py Normal file
View File

@ -0,0 +1,141 @@
from PIL import Image, ImageDraw
from PyQt4 import uic, QtGui, QtCore
import os, subprocess, threading
from queue import PriorityQueue
from . import __base__
class Video:
'''Video Component Frame-Fetcher'''
def __init__(self, ffmpeg, videoPath, width, height, frameRate, chunkSize, parent, loopVideo):
self.parent = parent
self.chunkSize = chunkSize
self.size = (width, height)
self.frameNo = -1
self.currentFrame = 'None'
if loopVideo:
self.loopValue = '-1'
else:
self.loopValue = '0'
self.command = [
ffmpeg,
'-thread_queue_size', '512',
'-r', frameRate,
'-stream_loop', self.loopValue,
'-i', videoPath,
'-f', 'image2pipe',
'-pix_fmt', 'rgba',
'-filter:v', 'scale='+str(width)+':'+str(height),
'-vcodec', 'rawvideo', '-',
]
self.frameBuffer = PriorityQueue()
self.frameBuffer.maxsize = int(frameRate)
self.finishedFrames = {}
self.thread = threading.Thread(target=self.fillBuffer, name=self.__doc__)
self.thread.daemon = True
self.thread.start()
def frame(self, num):
while True:
if num in self.finishedFrames:
image = self.finishedFrames.pop(num)
return Image.frombytes('RGBA', self.size, image)
i, image = self.frameBuffer.get()
self.finishedFrames[i] = image
self.frameBuffer.task_done()
def fillBuffer(self):
self.pipe = subprocess.Popen(self.command, 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.
if len(self.currentFrame) == 0:
self.frameBuffer.put((self.frameNo-1, self.lastFrame))
continue
self.currentFrame = self.pipe.stdout.read(self.chunkSize)
#print('creating frame #%s' % str(self.frameNo))
if len(self.currentFrame) != 0:
self.frameBuffer.put((self.frameNo, self.currentFrame))
self.lastFrame = self.currentFrame
class Component(__base__.Component):
'''Video'''
def widget(self, parent):
self.parent = parent
self.settings = parent.settings
page = uic.loadUi(os.path.join(os.path.dirname(os.path.realpath(__file__)), 'video.ui'))
self.videoPath = ''
self.x = 0
self.y = 0
self.loopVideo = False
page.lineEdit_video.textChanged.connect(self.update)
page.pushButton_video.clicked.connect(self.pickVideo)
page.checkBox_loop.stateChanged.connect(self.update)
self.page = page
return page
def update(self):
self.videoPath = self.page.lineEdit_video.text()
self.loopVideo = self.page.checkBox_loop.isChecked()
self.parent.drawPreview()
def previewRender(self, previewWorker):
width = int(previewWorker.core.settings.value('outputWidth'))
height = int(previewWorker.core.settings.value('outputHeight'))
self.chunkSize = 4*width*height
return self.getPreviewFrame(width, height)
def preFrameRender(self, **kwargs):
super().preFrameRender(**kwargs)
width = int(self.worker.core.settings.value('outputWidth'))
height = int(self.worker.core.settings.value('outputHeight'))
self.chunkSize = 4*width*height
self.video = Video(self.parent.core.FFMPEG_BIN, self.videoPath,
width, height, self.settings.value("outputFrameRate"),
self.chunkSize, self.parent, self.loopVideo)
def frameRender(self, moduleNo, arrayNo, frameNo):
return self.video.frame(frameNo)
def loadPreset(self, pr):
self.page.lineEdit_video.setText(pr['video'])
def savePreset(self):
return {
'video' : self.videoPath,
}
def pickVideo(self):
imgDir = self.settings.value("backgroundDir", os.path.expanduser("~"))
filename = QtGui.QFileDialog.getOpenFileName(self.page,
"Choose Video", imgDir, "Video Files (*.mp4 *.mov)")
if filename:
self.settings.setValue("backgroundDir", os.path.dirname(filename))
self.page.lineEdit_video.setText(filename)
self.update()
def getPreviewFrame(self, width, height):
command = [
self.parent.core.FFMPEG_BIN,
'-thread_queue_size', '512',
'-i', self.videoPath,
'-f', 'image2pipe',
'-pix_fmt', 'rgba',
'-filter:v', 'scale='+str(width)+':'+str(height),
'-vcodec', 'rawvideo', '-',
'-ss', '90',
'-vframes', '1',
]
pipe = subprocess.Popen(command, stdout=subprocess.PIPE, stderr=subprocess.DEVNULL, bufsize=10**8)
byteFrame = pipe.stdout.read(self.chunkSize)
image = Image.frombytes('RGBA', (width, height), byteFrame)
pipe.stdout.close()
pipe.kill()
return image

224
components/video.ui Normal file
View File

@ -0,0 +1,224 @@
<?xml version="1.0" encoding="UTF-8"?>
<ui version="4.0">
<class>Form</class>
<widget class="QWidget" name="Form">
<property name="geometry">
<rect>
<x>0</x>
<y>0</y>
<width>586</width>
<height>197</height>
</rect>
</property>
<property name="windowTitle">
<string>Form</string>
</property>
<layout class="QVBoxLayout" name="verticalLayout_2">
<item>
<layout class="QVBoxLayout" name="verticalLayout">
<property name="leftMargin">
<number>4</number>
</property>
<item>
<layout class="QHBoxLayout" name="horizontalLayout_8">
<item>
<widget class="QLabel" name="label_textColor">
<property name="sizePolicy">
<sizepolicy hsizetype="Fixed" vsizetype="Preferred">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="minimumSize">
<size>
<width>31</width>
<height>0</height>
</size>
</property>
<property name="text">
<string>Video</string>
</property>
</widget>
</item>
<item>
<widget class="QLineEdit" name="lineEdit_video">
<property name="minimumSize">
<size>
<width>1</width>
<height>0</height>
</size>
</property>
</widget>
</item>
<item>
<widget class="QPushButton" name="pushButton_video">
<property name="sizePolicy">
<sizepolicy hsizetype="Fixed" vsizetype="Fixed">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="minimumSize">
<size>
<width>1</width>
<height>0</height>
</size>
</property>
<property name="maximumSize">
<size>
<width>32</width>
<height>32</height>
</size>
</property>
<property name="text">
<string>...</string>
</property>
<property name="MaximumSize" stdset="0">
<size>
<width>32</width>
<height>32</height>
</size>
</property>
</widget>
</item>
<item>
<spacer name="horizontalSpacer_9">
<property name="orientation">
<enum>Qt::Horizontal</enum>
</property>
<property name="sizeType">
<enum>QSizePolicy::Fixed</enum>
</property>
<property name="sizeHint" stdset="0">
<size>
<width>5</width>
<height>20</height>
</size>
</property>
</spacer>
</item>
<item>
<widget class="QLabel" name="label_xTitleAlign">
<property name="sizePolicy">
<sizepolicy hsizetype="Fixed" vsizetype="Preferred">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="text">
<string>X</string>
</property>
</widget>
</item>
<item>
<widget class="QSpinBox" name="spinBox_x_2">
<property name="sizePolicy">
<sizepolicy hsizetype="Fixed" vsizetype="Fixed">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="maximumSize">
<size>
<width>80</width>
<height>16777215</height>
</size>
</property>
<property name="maximum">
<number>999999999</number>
</property>
</widget>
</item>
<item>
<widget class="QLabel" name="label_yTitleAlign">
<property name="sizePolicy">
<sizepolicy hsizetype="Fixed" vsizetype="Preferred">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="text">
<string>Y</string>
</property>
</widget>
</item>
<item>
<widget class="QSpinBox" name="spinBox_y">
<property name="sizePolicy">
<sizepolicy hsizetype="Fixed" vsizetype="Fixed">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="maximumSize">
<size>
<width>80</width>
<height>16777215</height>
</size>
</property>
<property name="baseSize">
<size>
<width>0</width>
<height>0</height>
</size>
</property>
<property name="minimum">
<number>0</number>
</property>
<property name="maximum">
<number>999999999</number>
</property>
<property name="value">
<number>0</number>
</property>
</widget>
</item>
</layout>
</item>
</layout>
</item>
<item>
<layout class="QHBoxLayout" name="horizontalLayout_9">
<item>
<widget class="QCheckBox" name="checkBox_loop">
<property name="text">
<string>Loop</string>
</property>
</widget>
</item>
<item>
<spacer name="horizontalSpacer_10">
<property name="orientation">
<enum>Qt::Horizontal</enum>
</property>
<property name="sizeType">
<enum>QSizePolicy::Fixed</enum>
</property>
<property name="sizeHint" stdset="0">
<size>
<width>5</width>
<height>20</height>
</size>
</property>
</spacer>
</item>
</layout>
</item>
<item>
<spacer name="verticalSpacer">
<property name="orientation">
<enum>Qt::Vertical</enum>
</property>
<property name="sizeHint" stdset="0">
<size>
<width>20</width>
<height>40</height>
</size>
</property>
</spacer>
</item>
</layout>
</widget>
<resources/>
<connections/>
</ui>

62
core.py
View File

@ -13,11 +13,10 @@ from collections import OrderedDict
class Core(): class Core():
def __init__(self): def __init__(self):
self.lastBackgroundImage = ""
self._image = None
self.FFMPEG_BIN = self.findFfmpeg() self.FFMPEG_BIN = self.findFfmpeg()
self.tempDir = None self.tempDir = os.path.join(tempfile.gettempdir(), 'audio-visualizer-python-data')
if not os.path.exists(self.tempDir):
os.makedirs(self.tempDir)
atexit.register(self.deleteTempDir) atexit.register(self.deleteTempDir)
def findFfmpeg(self): def findFfmpeg(self):
@ -31,31 +30,6 @@ class Core():
except: except:
return "avconv" return "avconv"
def parseBaseImage(self, backgroundImage, preview=False):
''' determines if the base image is a single frame or list of frames '''
if backgroundImage == "":
return ['']
else:
_, bgExt = os.path.splitext(backgroundImage)
if not bgExt == '.mp4':
return [backgroundImage]
else:
return self.getVideoFrames(backgroundImage, preview)
def drawBaseImage(self, backgroundFile):
if backgroundFile == '':
im = Image.new("RGB", (int(self.settings.value('outputWidth')), int(self.settings.value('outputHeight'))), "black")
else:
im = Image.open(backgroundFile)
if self._image == None or not self.lastBackgroundImage == backgroundFile:
self.lastBackgroundImage = backgroundFile
# resize if necessary
if not im.size == (int(self.settings.value('outputWidth')), int(self.settings.value('outputHeight'))):
im = im.resize((int(self.settings.value('outputWidth')), int(self.settings.value('outputHeight'))), Image.ANTIALIAS)
return im
def readAudioFile(self, filename, parent): def readAudioFile(self, filename, parent):
command = [ self.FFMPEG_BIN, command = [ self.FFMPEG_BIN,
'-i', filename] '-i', filename]
@ -121,30 +95,10 @@ class Core():
return completeAudioArray return completeAudioArray
def deleteTempDir(self): def deleteTempDir(self):
if self.tempDir and os.path.exists(self.tempDir): try:
rmtree(self.tempDir) rmtree(self.tempDir)
except FileNotFoundError:
def getVideoFrames(self, videoPath, firstOnly=False): pass
self.tempDir = os.path.join(tempfile.gettempdir(), 'audio-visualizer-python-data')
# recreate the temporary directory so it is empty
self.deleteTempDir()
os.mkdir(self.tempDir)
if firstOnly:
filename = 'preview%s.jpg' % os.path.basename(videoPath).split('.', 1)[0]
options = '-ss 10 -vframes 1'
else:
filename = '$frame%05d.jpg'
options = ''
sp.call( \
'%s -i "%s" -y %s "%s"' % ( \
self.FFMPEG_BIN,
videoPath,
options,
os.path.join(self.tempDir, filename)
),
shell=True
)
return sorted([os.path.join(self.tempDir, f) for f in os.listdir(self.tempDir)])
def cancel(self): def cancel(self):
self.canceled = True self.canceled = True
@ -153,6 +107,6 @@ class Core():
self.canceled = False self.canceled = False
@staticmethod @staticmethod
def sortedStringDict(dictionary): def stringOrderedDict(dictionary):
sorted_ = OrderedDict(sorted(dictionary.items(), key=lambda t: t[0])) sorted_ = OrderedDict(sorted(dictionary.items(), key=lambda t: t[0]))
return repr(sorted_) return repr(sorted_)

67
main.py
View File

@ -1,4 +1,4 @@
import sys, io, os, shutil, atexit, string, signal, filecmp import sys, io, os, shutil, atexit, string, signal, filecmp, time
from os.path import expanduser from os.path import expanduser
from queue import Queue from queue import Queue
from importlib import import_module from importlib import import_module
@ -133,9 +133,9 @@ class PreviewWindow(QtGui.QLabel):
class Main(QtCore.QObject): class Main(QtCore.QObject):
newTask = QtCore.pyqtSignal(str, list) newTask = QtCore.pyqtSignal(list)
processTask = QtCore.pyqtSignal() processTask = QtCore.pyqtSignal()
videoTask = QtCore.pyqtSignal(str, str, str, list) videoTask = QtCore.pyqtSignal(str, str, list)
def __init__(self, window): def __init__(self, window):
QtCore.QObject.__init__(self) QtCore.QObject.__init__(self)
@ -145,6 +145,7 @@ class Main(QtCore.QObject):
self.core = core.Core() self.core = core.Core()
self.pages = [] self.pages = []
self.selectedComponents = [] self.selectedComponents = []
self.lastAutosave = time.time()
# create data directory, load/create settings # create data directory, load/create settings
self.dataDir = QDesktopServices.storageLocation(QDesktopServices.DataLocation) self.dataDir = QDesktopServices.storageLocation(QDesktopServices.DataLocation)
@ -172,14 +173,13 @@ class Main(QtCore.QObject):
# begin decorating the window and connecting events # begin decorating the window and connecting events
window.toolButton_selectAudioFile.clicked.connect(self.openInputFileDialog) window.toolButton_selectAudioFile.clicked.connect(self.openInputFileDialog)
window.toolButton_selectBackground.clicked.connect(self.openBackgroundFileDialog)
window.toolButton_selectOutputFile.clicked.connect(self.openOutputFileDialog) window.toolButton_selectOutputFile.clicked.connect(self.openOutputFileDialog)
window.progressBar_createVideo.setValue(0) window.progressBar_createVideo.setValue(0)
window.pushButton_createVideo.clicked.connect(self.createAudioVisualisation) window.pushButton_createVideo.clicked.connect(self.createAudioVisualisation)
window.pushButton_Cancel.clicked.connect(self.stopVideo) window.pushButton_Cancel.clicked.connect(self.stopVideo)
window.setWindowTitle("Audio Visualizer") window.setWindowTitle("Audio Visualizer")
self.previewWindow = PreviewWindow(self, os.path.join(os.path.dirname(os.path.realpath(__file__)), "background.jpg")) self.previewWindow = PreviewWindow(self, os.path.join(os.path.dirname(os.path.realpath(__file__)), "background.png"))
window.verticalLayout_previewWrapper.addWidget(self.previewWindow) window.verticalLayout_previewWrapper.addWidget(self.previewWindow)
self.modules = self.findComponents() self.modules = self.findComponents()
@ -236,15 +236,17 @@ class Main(QtCore.QObject):
self.autosave() self.autosave()
def autosave(self): def autosave(self):
if os.path.exists(self.autosavePath): if time.time() - self.lastAutosave >= 1.0:
os.remove(self.autosavePath) if os.path.exists(self.autosavePath):
self.createProjectFile(self.autosavePath) os.remove(self.autosavePath)
self.createProjectFile(self.autosavePath)
self.lastAutosave = time.time()
def openInputFileDialog(self): def openInputFileDialog(self):
inputDir = self.settings.value("inputDir", expanduser("~")) inputDir = self.settings.value("inputDir", expanduser("~"))
fileName = QtGui.QFileDialog.getOpenFileName(self.window, fileName = QtGui.QFileDialog.getOpenFileName(self.window,
"Open Music File", inputDir, "Music Files (*.mp3 *.wav *.ogg *.flac)"); "Open Music File", inputDir, "Music Files (*.mp3 *.wav *.ogg *.fla *.aac)");
if not fileName == "": if not fileName == "":
self.settings.setValue("inputDir", os.path.dirname(fileName)) self.settings.setValue("inputDir", os.path.dirname(fileName))
@ -254,23 +256,12 @@ class Main(QtCore.QObject):
outputDir = self.settings.value("outputDir", expanduser("~")) outputDir = self.settings.value("outputDir", expanduser("~"))
fileName = QtGui.QFileDialog.getSaveFileName(self.window, fileName = QtGui.QFileDialog.getSaveFileName(self.window,
"Set Output Video File", outputDir, "Video Files (*.mkv)"); "Set Output Video File", outputDir, "Video Files (*.mp4 *.mov *.mkv *.avi *.webm *.flv)");
if not fileName == "": if not fileName == "":
self.settings.setValue("outputDir", os.path.dirname(fileName)) self.settings.setValue("outputDir", os.path.dirname(fileName))
self.window.lineEdit_outputFile.setText(fileName) self.window.lineEdit_outputFile.setText(fileName)
def openBackgroundFileDialog(self):
backgroundDir = self.settings.value("backgroundDir", expanduser("~"))
fileName = QtGui.QFileDialog.getOpenFileName(self.window,
"Open Background Image", backgroundDir, "Image Files (*.jpg *.png);; Video Files (*.mp4)");
if not fileName == "":
self.settings.setValue("backgroundDir", os.path.dirname(fileName))
self.window.lineEdit_background.setText(fileName)
self.drawPreview()
def stopVideo(self): def stopVideo(self):
print('stop') print('stop')
self.videoWorker.cancel() self.videoWorker.cancel()
@ -291,8 +282,7 @@ class Main(QtCore.QObject):
self.videoWorker.imageCreated.connect(self.showPreviewImage) self.videoWorker.imageCreated.connect(self.showPreviewImage)
self.videoWorker.encoding.connect(self.changeEncodingStatus) self.videoWorker.encoding.connect(self.changeEncodingStatus)
self.videoThread.start() self.videoThread.start()
self.videoTask.emit(self.window.lineEdit_background.text(), self.videoTask.emit(self.window.lineEdit_audioFile.text(),
self.window.lineEdit_audioFile.text(),
self.window.lineEdit_outputFile.text(), self.window.lineEdit_outputFile.text(),
self.selectedComponents) self.selectedComponents)
else: else:
@ -323,10 +313,6 @@ class Main(QtCore.QObject):
self.window.pushButton_savePreset.setEnabled(False) self.window.pushButton_savePreset.setEnabled(False)
self.window.pushButton_openProject.setEnabled(False) self.window.pushButton_openProject.setEnabled(False)
self.window.listWidget_componentList.setEnabled(False) self.window.listWidget_componentList.setEnabled(False)
self.window.label_background.setEnabled(False)
self.window.lineEdit_background.setEnabled(False)
self.window.toolButton_selectBackground.setEnabled(False)
else: else:
self.window.pushButton_createVideo.setEnabled(True) self.window.pushButton_createVideo.setEnabled(True)
self.window.pushButton_Cancel.setEnabled(False) self.window.pushButton_Cancel.setEnabled(False)
@ -349,12 +335,6 @@ class Main(QtCore.QObject):
self.window.pushButton_openProject.setEnabled(True) self.window.pushButton_openProject.setEnabled(True)
self.window.listWidget_componentList.setEnabled(True) self.window.listWidget_componentList.setEnabled(True)
self.window.label_background.setEnabled(True)
self.window.lineEdit_background.setEnabled(True)
self.window.toolButton_selectBackground.setEnabled(True)
def progressBarSetText(self, value): def progressBarSetText(self, value):
self.window.progressBar_createVideo.setFormat(value) self.window.progressBar_createVideo.setFormat(value)
@ -370,7 +350,7 @@ class Main(QtCore.QObject):
self.drawPreview() self.drawPreview()
def drawPreview(self): def drawPreview(self):
self.newTask.emit(self.window.lineEdit_background.text(), self.selectedComponents) self.newTask.emit(self.selectedComponents)
# self.processTask.emit() # self.processTask.emit()
self.autosave() self.autosave()
@ -381,7 +361,7 @@ class Main(QtCore.QObject):
def findComponents(): def findComponents():
srcPath = os.path.join(os.path.dirname(os.path.realpath(__file__)), 'components') srcPath = os.path.join(os.path.dirname(os.path.realpath(__file__)), 'components')
if os.path.exists(srcPath): if os.path.exists(srcPath):
for f in os.listdir(srcPath): for f in sorted(os.listdir(srcPath)):
name, ext = os.path.splitext(f) name, ext = os.path.splitext(f)
if name.startswith("__"): if name.startswith("__"):
continue continue
@ -446,7 +426,7 @@ class Main(QtCore.QObject):
def moveComponentDown(self): def moveComponentDown(self):
row = self.window.listWidget_componentList.currentRow() row = self.window.listWidget_componentList.currentRow()
if row < len(self.pages) + 1: if row != -1 and row < len(self.pages)+1:
module = self.selectedComponents[row] module = self.selectedComponents[row]
self.selectedComponents.pop(row) self.selectedComponents.pop(row)
self.selectedComponents.insert(row + 1,module) self.selectedComponents.insert(row + 1,module)
@ -507,7 +487,7 @@ class Main(QtCore.QObject):
if self.window.comboBox_openPreset.itemText(i) == filename: if self.window.comboBox_openPreset.itemText(i) == filename:
self.window.comboBox_openPreset.removeItem(i) self.window.comboBox_openPreset.removeItem(i)
with open(filepath, 'w') as f: with open(filepath, 'w') as f:
f.write(core.Core.sortedStringDict(saveValueStore)) f.write(core.Core.stringOrderedDict(saveValueStore))
self.window.comboBox_openPreset.addItem(filename) self.window.comboBox_openPreset.addItem(filename)
self.window.comboBox_openPreset.setCurrentIndex(self.window.comboBox_openPreset.count()-1) self.window.comboBox_openPreset.setCurrentIndex(self.window.comboBox_openPreset.count()-1)
@ -550,12 +530,13 @@ class Main(QtCore.QObject):
if not filepath.endswith(".avp"): if not filepath.endswith(".avp"):
filepath += '.avp' filepath += '.avp'
with open(filepath, 'w') as f: with open(filepath, 'w') as f:
print('creating %s' % filepath)
f.write('[Components]\n') f.write('[Components]\n')
for comp in self.selectedComponents: for comp in self.selectedComponents:
saveValueStore = comp.savePreset() saveValueStore = comp.savePreset()
f.write('%s\n' % str(comp)) f.write('%s\n' % str(comp))
f.write('%s\n' % str(comp.version())) f.write('%s\n' % str(comp.version()))
f.write('%s\n' % core.Core.sortedStringDict(saveValueStore)) f.write('%s\n' % core.Core.stringOrderedDict(saveValueStore))
if filepath != self.autosavePath: if filepath != self.autosavePath:
self.settings.setValue("projectDir", os.path.dirname(filepath)) self.settings.setValue("projectDir", os.path.dirname(filepath))
self.settings.setValue("currentProject", filepath) self.settings.setValue("currentProject", filepath)
@ -604,14 +585,18 @@ class Main(QtCore.QObject):
saveValueStore = dict(eval(line)) saveValueStore = dict(eval(line))
self.selectedComponents[-1].loadPreset(saveValueStore) self.selectedComponents[-1].loadPreset(saveValueStore)
i = 0 i = 0
except: except (IndexError, ValueError, KeyError, NameError, SyntaxError, AttributeError, TypeError) as e:
self.clear() self.clear()
self.showMessage("Project file '%s' is corrupted." % filepath) typ, value, _ = sys.exc_info()
msg = '%s: %s' % (typ.__name__, value)
self.showMessage("Project file '%s' is corrupted." % filepath, False,
QtGui.QMessageBox.Warning, msg)
def showMessage(self, string, showCancel=False, icon=QtGui.QMessageBox.Information): def showMessage(self, string, showCancel=False, icon=QtGui.QMessageBox.Information, detail=None):
msg = QtGui.QMessageBox() msg = QtGui.QMessageBox()
msg.setIcon(icon) msg.setIcon(icon)
msg.setText(string) msg.setText(string)
msg.setDetailedText(detail)
if showCancel: if showCancel:
msg.setStandardButtons(QtGui.QMessageBox.Ok | QtGui.QMessageBox.Cancel) msg.setStandardButtons(QtGui.QMessageBox.Ok | QtGui.QMessageBox.Cancel)
else: else:

View File

@ -6,8 +6,8 @@
<rect> <rect>
<x>0</x> <x>0</x>
<y>0</y> <y>0</y>
<width>1008</width> <width>1028</width>
<height>575</height> <height>592</height>
</rect> </rect>
</property> </property>
<property name="sizePolicy"> <property name="sizePolicy">
@ -421,73 +421,6 @@
</item> </item>
</layout> </layout>
</item> </item>
<item>
<layout class="QHBoxLayout" name="horizontalLayout_5">
<item>
<widget class="QLabel" name="label_background">
<property name="sizePolicy">
<sizepolicy hsizetype="Fixed" vsizetype="Preferred">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="minimumSize">
<size>
<width>85</width>
<height>0</height>
</size>
</property>
<property name="text">
<string>Background</string>
</property>
<property name="alignment">
<set>Qt::AlignLeading|Qt::AlignLeft|Qt::AlignVCenter</set>
</property>
</widget>
</item>
<item>
<widget class="QLineEdit" name="lineEdit_background">
<property name="sizePolicy">
<sizepolicy hsizetype="Minimum" vsizetype="Fixed">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="minimumSize">
<size>
<width>0</width>
<height>28</height>
</size>
</property>
<property name="maximumSize">
<size>
<width>16777215</width>
<height>28</height>
</size>
</property>
</widget>
</item>
<item>
<widget class="QToolButton" name="toolButton_selectBackground">
<property name="minimumSize">
<size>
<width>0</width>
<height>28</height>
</size>
</property>
<property name="maximumSize">
<size>
<width>16777215</width>
<height>28</height>
</size>
</property>
<property name="text">
<string>...</string>
</property>
</widget>
</item>
</layout>
</item>
<item> <item>
<layout class="QVBoxLayout" name="verticalLayout_11"> <layout class="QVBoxLayout" name="verticalLayout_11">
<item> <item>
@ -621,7 +554,6 @@
</layout> </layout>
<zorder></zorder> <zorder></zorder>
<zorder></zorder> <zorder></zorder>
<zorder></zorder>
</widget> </widget>
<widget class="QWidget" name="tab_encoderSettings"> <widget class="QWidget" name="tab_encoderSettings">
<attribute name="title"> <attribute name="title">

View File

@ -22,10 +22,9 @@ class Worker(QtCore.QObject):
@pyqtSlot(str, list) @pyqtSlot(str, list)
def createPreviewImage(self, backgroundImage, components): def createPreviewImage(self, components):
# print('worker thread id: {}'.format(QtCore.QThread.currentThreadId())) # print('worker thread id: {}'.format(QtCore.QThread.currentThreadId()))
dic = { dic = {
"backgroundImage": backgroundImage,
"components": components, "components": components,
} }
self.queue.put(dic) self.queue.put(dic)
@ -40,25 +39,14 @@ class Worker(QtCore.QObject):
except Empty: except Empty:
continue continue
bgImage = self.core.parseBaseImage(\
nextPreviewInformation["backgroundImage"],
preview=True
)
if bgImage == []:
bgImage = ''
else:
bgImage = bgImage[0]
im = self.core.drawBaseImage(bgImage)
width = int(self.core.settings.value('outputWidth')) width = int(self.core.settings.value('outputWidth'))
height = int(self.core.settings.value('outputHeight')) height = int(self.core.settings.value('outputHeight'))
frame = Image.new("RGBA", (width, height),(0,0,0,255)) frame = Image.new("RGBA", (width, height),(0,0,0,0))
frame.paste(im)
components = nextPreviewInformation["components"] components = nextPreviewInformation["components"]
for component in reversed(components): for component in reversed(components):
newFrame = Image.alpha_composite(frame,component.previewRender(self)) #newFrame = Image.alpha_composite(frame,)
frame = Image.alpha_composite(frame,newFrame) frame = Image.alpha_composite(frame,component.previewRender(self))
self._image = ImageQt(frame) self._image = ImageQt(frame)
self.imageCreated.emit(QtGui.QImage(self._image)) self.imageCreated.emit(QtGui.QImage(self._image))

View File

@ -37,19 +37,19 @@ class Worker(QtCore.QObject):
def renderNode(self): def renderNode(self):
while not self.stopped: while not self.stopped:
i = self.compositeQueue.get() i = self.compositeQueue.get()
frame = None
if self.imBackground is not None:
frame = self.imBackground
else:
frame = self.getBackgroundAtIndex(i[1])
for compNo, comp in reversed(list(enumerate(self.components))): for compNo, comp in reversed(list(enumerate(self.components))):
if compNo in self.staticComponents and self.staticComponents[compNo] != None: if compNo in self.staticComponents and self.staticComponents[compNo] != None:
frame = Image.alpha_composite(frame, self.staticComponents[compNo]) if frame is None:
frame = self.staticComponents[compNo]
else:
frame = Image.alpha_composite(frame, self.staticComponents[compNo])
else: else:
frame = Image.alpha_composite(frame, comp.frameRender(compNo, i[0])) if frame is None:
frame = comp.frameRender(compNo, i[0], i[1])
# frame.paste(compFrame, mask=compFrame) else:
frame = Image.alpha_composite(frame, comp.frameRender(compNo, i[0], i[1]))
self.renderQueue.put([i[0], frame]) self.renderQueue.put([i[0], frame])
self.compositeQueue.task_done() self.compositeQueue.task_done()
@ -59,10 +59,8 @@ class Worker(QtCore.QObject):
for i in range(0, len(self.completeAudioArray), self.sampleSize): for i in range(0, len(self.completeAudioArray), self.sampleSize):
self.compositeQueue.put([i, self.bgI]) self.compositeQueue.put([i, self.bgI])
if not self.imBackground: # increment tracked video frame for next iteration
# increment background video frame for next iteration self.bgI += 1
if self.bgI < len(self.backgroundFrames)-1:
self.bgI += 1
def previewDispatch(self): def previewDispatch(self):
while not self.stopped: while not self.stopped:
@ -74,39 +72,18 @@ class Worker(QtCore.QObject):
self.previewQueue.task_done() self.previewQueue.task_done()
def getBackgroundAtIndex(self, i): @pyqtSlot(str, str, list)
background = Image.new( def createVideo(self, inputFile, outputFile, components):
"RGBA",
(self.width, self.height),
(0, 0, 0, 255)
)
layer = self.core.drawBaseImage(self.backgroundFrames[i])
background.paste(layer)
return background
@pyqtSlot(str, str, str, list)
def createVideo(self, backgroundImage, inputFile, outputFile, components):
self.encoding.emit(True) self.encoding.emit(True)
self.components = components self.components = components
self.outputFile = outputFile self.outputFile = outputFile
self.bgI = 0 # tracked video frame
self.reset() self.reset()
self.width = int(self.core.settings.value('outputWidth')) self.width = int(self.core.settings.value('outputWidth'))
self.height = int(self.core.settings.value('outputHeight')) self.height = int(self.core.settings.value('outputHeight'))
# print('worker thread id: {}'.format(QtCore.QThread.currentThreadId())) # print('worker thread id: {}'.format(QtCore.QThread.currentThreadId()))
progressBarValue = 0 progressBarValue = 0
self.progressBarUpdate.emit(progressBarValue) self.progressBarUpdate.emit(progressBarValue)
self.progressBarSetText.emit('Loading background image…')
self.backgroundImage = backgroundImage
self.backgroundFrames = self.core.parseBaseImage(backgroundImage)
if len(self.backgroundFrames) < 2:
# the base image is not a video so we can draw it now
self.imBackground = self.getBackgroundAtIndex(0)
else:
# base images will be drawn while drawing the audio bars
self.imBackground = None
self.bgI = 0
self.progressBarSetText.emit('Loading audio file...') self.progressBarSetText.emit('Loading audio file...')
self.completeAudioArray = self.core.readAudioFile(inputFile, self) self.completeAudioArray = self.core.readAudioFile(inputFile, self)
@ -120,6 +97,7 @@ class Worker(QtCore.QObject):
ffmpegCommand = [ ffmpegCommand = [
self.core.FFMPEG_BIN, self.core.FFMPEG_BIN,
'-thread_queue_size', '512',
'-y', # (optional) means overwrite the output file if it already exists. '-y', # (optional) means overwrite the output file if it already exists.
'-f', 'rawvideo', '-f', 'rawvideo',
'-vcodec', 'rawvideo', '-vcodec', 'rawvideo',
@ -165,7 +143,7 @@ class Worker(QtCore.QObject):
) )
if properties and 'static' in properties: if properties and 'static' in properties:
self.staticComponents[compNo] = copy(comp.frameRender(compNo, 0)) self.staticComponents[compNo] = copy(comp.frameRender(compNo, 0, 0))
self.progressBarUpdate.emit(100) self.progressBarUpdate.emit(100)
self.compositeQueue = Queue() self.compositeQueue = Queue()
@ -250,7 +228,6 @@ class Worker(QtCore.QObject):
self.error = False self.error = False
self.canceled = False self.canceled = False
self.parent.drawPreview() self.parent.drawPreview()
self.core.deleteTempDir()
self.stopped = True self.stopped = True
self.encoding.emit(False) self.encoding.emit(False)
self.videoCreated.emit() self.videoCreated.emit()