diff options
| -rw-r--r-- | core.py | 61 | ||||
| -rw-r--r-- | main.py | 6 | ||||
| -rw-r--r-- | main.ui | 5 | ||||
| -rw-r--r-- | preview_thread.py | 11 | ||||
| -rw-r--r-- | video_thread.py | 50 |
5 files changed, 104 insertions, 29 deletions
@@ -6,6 +6,9 @@ import subprocess as sp import numpy from PIL import Image, ImageDraw, ImageFont from PIL.ImageQt import ImageQt +import tempfile +from shutil import rmtree +import atexit class Core(): @@ -14,6 +17,8 @@ class Core(): self._image = None self.FFMPEG_BIN = self.findFfmpeg() + self.tempDir = None + atexit.register(self.deleteTempDir) def findFfmpeg(self): if sys.platform == "win32": @@ -26,22 +31,32 @@ class Core(): except: return "avconv" - def drawBaseImage(self, backgroundImage, titleText, titleFont, fontSize, alignment, xOffset, yOffset): - - if self._image == None or not self.lastBackgroundImage == backgroundImage: - self.lastBackgroundImage = backgroundImage - + def parseBaseImage(self, backgroundImage, preview=False): + ''' determines if the base image is a single frame or list of frames ''' if backgroundImage == "": - im = Image.new("RGB", (1280, 720), "black") + return [] else: - im = Image.open(backgroundImage) + _, bgExt = os.path.splitext(backgroundImage) + if not bgExt == '.mp4': + return [backgroundImage] + else: + return self.getVideoFrames(backgroundImage, preview) + + def drawBaseImage(self, backgroundFile, titleText, titleFont, fontSize, alignment, xOffset, yOffset): + if backgroundFile == '': + im = Image.new("RGB", (1280, 720), "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 == (1280, 720): im = im.resize((1280, 720), Image.ANTIALIAS) self._image = ImageQt(im) - + self._image1 = QtGui.QImage(self._image) painter = QPainter(self._image1) font = titleFont @@ -81,9 +96,8 @@ class Core(): imBottom = imTop.transpose(Image.FLIP_TOP_BOTTOM) - + im = Image.new("RGB", (1280, 720), "black") - im.paste(image, (0, 0)) im.paste(imTop, (0, 0), mask=imTop) im.paste(imBottom, (0, 360), mask=imBottom) @@ -150,3 +164,30 @@ class Core(): x = frequencies[0:int(paddedSampleSize/2) - 1] return lastSpectrum + + def deleteTempDir(self): + if self.tempDir and os.path.exists(self.tempDir): + rmtree(self.tempDir) + + + def getVideoFrames(self, videoPath, firstOnly=False): + 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)]) @@ -131,7 +131,7 @@ class Main(QtCore.QObject): backgroundDir = self.settings.value("backgroundDir", expanduser("~")) fileName = QtGui.QFileDialog.getOpenFileName(self.window, - "Open Background Image", backgroundDir, "Image Files (*.jpg *.png)"); + "Open Background Image", backgroundDir, "Image Files (*.jpg *.png);; Video Files (*.mp4)"); if not fileName == "": self.settings.setValue("backgroundDir", os.path.dirname(fileName)) @@ -147,6 +147,7 @@ class Main(QtCore.QObject): self.videoWorker.moveToThread(self.videoThread) self.videoWorker.videoCreated.connect(self.videoCreated) self.videoWorker.progressBarUpdate.connect(self.progressBarUpdated) + self.videoWorker.progressBarSetText.connect(self.progressBarSetText) self.videoThread.start() self.videoTask.emit(self.window.label_background.text(), @@ -163,6 +164,9 @@ class Main(QtCore.QObject): def progressBarUpdated(self, value): self.window.progressBar_create.setValue(value) + def progressBarSetText(self, value): + self.window.progressBar_create.setFormat(value) + def videoCreated(self): self.videoThread.quit() self.videoThread.wait() @@ -386,7 +386,10 @@ <number>24</number> </property> <property name="textVisible"> - <bool>false</bool> + <bool>true</bool> + </property> + <property name="alignment"> + <enum>Qt::AlignCenter</enum> </property> </widget> </item> diff --git a/preview_thread.py b/preview_thread.py index 9dc7e4c..5bad653 100644 --- a/preview_thread.py +++ b/preview_thread.py @@ -43,8 +43,17 @@ class Worker(QtCore.QObject): except Empty: continue + bgImage = self.core.parseBaseImage(\ + nextPreviewInformation["backgroundImage"], + preview=True + ) + if bgImage == []: + bgImage = '' + else: + bgImage = bgImage[0] + im = self.core.drawBaseImage( - nextPreviewInformation["backgroundImage"], + bgImage, nextPreviewInformation["titleText"], nextPreviewInformation["titleFont"], nextPreviewInformation["fontSize"], diff --git a/video_thread.py b/video_thread.py index 1d1d44b..bd832be 100644 --- a/video_thread.py +++ b/video_thread.py @@ -11,6 +11,7 @@ class Worker(QtCore.QObject): videoCreated = pyqtSignal() progressBarUpdate = pyqtSignal(int) + progressBarSetText = pyqtSignal(str) def __init__(self, parent=None): QtCore.QObject.__init__(self) @@ -21,18 +22,29 @@ class Worker(QtCore.QObject): @pyqtSlot(str, str, QtGui.QFont, int, int, int, int, str, str) def createVideo(self, backgroundImage, titleText, titleFont, fontSize, alignment, xOffset, yOffset, inputFile, outputFile): # print('worker thread id: {}'.format(QtCore.QThread.currentThreadId())) - - imBackground = self.core.drawBaseImage( - backgroundImage, - titleText, - titleFont, - fontSize, - alignment, - xOffset, - yOffset) - - self.progressBarUpdate.emit(0) - + def getBackgroundAtIndex(i): + return self.core.drawBaseImage( + backgroundFrames[i], + titleText, + titleFont, + fontSize, + alignment, + xOffset, + yOffset) + + progressBarValue = 0 + self.progressBarUpdate.emit(progressBarValue) + self.progressBarSetText.emit('Loading background image…') + + backgroundFrames = self.core.parseBaseImage(backgroundImage) + if len(backgroundFrames) < 2: + # the base image is not a video so we can draw it now + imBackground = getBackgroundAtIndex(0) + else: + # base images will be drawn while drawing the audio bars + imBackground = None + + self.progressBarSetText.emit('Loading audio file…') completeAudioArray = self.core.readAudioFile(inputFile) # test if user has libfdk_aac @@ -71,11 +83,10 @@ class Worker(QtCore.QObject): smoothConstantDown = 0.08 smoothConstantUp = 0.8 lastSpectrum = None - progressBarValue = 0 sampleSize = 1470 - + numpy.seterr(divide='ignore') - + bgI = 0 for i in range(0, len(completeAudioArray), sampleSize): # create video for output lastSpectrum = self.core.transformData( @@ -85,7 +96,12 @@ class Worker(QtCore.QObject): smoothConstantDown, smoothConstantUp, lastSpectrum) - im = self.core.drawBars(lastSpectrum, imBackground) + if imBackground != None: + im = self.core.drawBars(lastSpectrum, imBackground) + else: + im = self.core.drawBars(lastSpectrum, getBackgroundAtIndex(bgI)) + if bgI < len(backgroundFrames)-1: + bgI += 1 # write to out_pipe try: @@ -97,6 +113,7 @@ class Worker(QtCore.QObject): if progressBarValue + 1 <= (i / len(completeAudioArray)) * 100: progressBarValue = numpy.floor((i / len(completeAudioArray)) * 100) self.progressBarUpdate.emit(progressBarValue) + self.progressBarSetText.emit('%s%%' % str(int(progressBarValue))) numpy.seterr(all='print') @@ -108,4 +125,5 @@ class Worker(QtCore.QObject): out_pipe.wait() print("Video file created") self.progressBarUpdate.emit(100) + self.progressBarSetText.emit('100%') self.videoCreated.emit() |
