Diff of /trunk/tubetutor/ffmpeg.py [000000] .. [r1]  Maximize  Restore

Switch to side-by-side view

--- a
+++ b/trunk/tubetutor/ffmpeg.py
@@ -0,0 +1,224 @@
+#
+# Wrapper for the ffmpeg utilities
+#
+# Default search path is relatively to the main script that is called:
+# <script path>/ffmpeg
+#
+# Otherwise, the windows search path is used
+#
+import subprocess
+import ctypes
+import sys
+import os
+import re
+
+#font="Arial"
+font=os.path.join("media", "Roboto-Regular.ttf")
+proc_ffmpeg=None
+
+#
+# The following helper functions will retrieve the pathnames for the ffmpeg tools
+#
+def get_cmd_ffmpeg():
+	subdir=os.path.join(os.path.dirname(sys.argv[0]), "ffmpeg")
+	if os.path.exists(subdir):
+		return os.path.join(subdir, "ffmpeg.exe")
+	return "ffmpeg.exe"
+
+def get_cmd_ffprobe():
+	subdir=os.path.join(os.path.dirname(sys.argv[0]), "ffmpeg")
+	if os.path.exists(subdir):
+		return os.path.join(subdir, "ffprobe.exe")
+	return "ffprobe.exe"
+
+def get_cmd_convert():
+	subdir=os.path.join(os.path.dirname(sys.argv[0]), "imagemagick")
+	if os.path.exists(subdir):
+		return os.path.join(subdir, "convert.exe")
+	return "convert.exe"
+
+def is_recording():
+	return proc_ffmpeg != None
+
+def convert_image(input, output, params):
+	global font
+	cmd = get_cmd_convert()
+	cmd += " " + input
+	cmd += " " + params
+	cmd += " " + output
+	print ("====================================================")
+	print ("cmd: %s" % cmd)
+	p = subprocess.Popen(cmd, stdout=subprocess.PIPE, shell=False)
+	(out, error) = p.communicate()
+	print("output:\n%s" % out)
+	print("error:\n%s" % error)
+
+def start(filename, params):
+	global proc_ffmpeg
+
+	# Kill remaining ffmpeg instances
+	stop()
+	# execute ffmpeg cmd
+	cmd = get_cmd_ffmpeg()
+	cmd += " " + params
+	cmd += " " + filename
+	print ("====================================================")
+	print ("cmd: %s" % cmd)
+	proc_ffmpeg = subprocess.Popen(cmd, stdout=subprocess.PIPE, shell=False)
+
+def record(filename, resolution=""):
+	if resolution != "":
+		start(filename, " -f gdigrab -framerate 20 -i desktop -y -vf scale=%s -v:q 1" % (resolution))
+	else:
+		start(filename, " -f gdigrab -framerate 20 -i desktop -y -v:q 1")
+
+def stop():
+	global proc_ffmpeg
+	# Kill remaining ffmpeg instances
+	if proc_ffmpeg:
+		ctypes.windll.kernel32.TerminateProcess(int(proc_ffmpeg._handle), -1)
+		proc_ffmpeg.kill()
+		proc_ffmpeg=None
+		
+def video_duration(filename):
+	cmd = get_cmd_ffprobe()
+	cmd += " -i %s" % filename
+	cmd += " -show_entries format=duration"
+	print ("====================================================")
+	print ("cmd: %s" % cmd)
+	p = subprocess.Popen(cmd, stdout=subprocess.PIPE, shell=False)
+	(output, error) = p.communicate()
+	print("duration output: %s - %s" % (output, error))
+	durations = re.findall(r'duration=[0-9.]*', str(output))
+	for d in durations:
+		duration = d.split("=")[1]
+		print("duration string: %s" % duration)
+		print("duration: %f" % float(duration))
+		return float(duration)
+
+def wait():
+	global proc_ffmpeg
+	if proc_ffmpeg:
+		(out, error) = proc_ffmpeg.communicate()
+		print("output:\n%s" % out)
+		print("error:\n%s" % error)
+		proc_ffmpeg = None
+
+class renderer:
+	pconcat=""
+	nconcat=0
+	vidfilter=[]
+	vidresolution=""
+	lastfilename=""
+	tmppath=""
+	framerate=20
+	qfilter=" -v:q 1 "
+
+	def __init__(self):
+		self.tmppath = os.path.join("videos", "tmp")
+		self.framerate = 20
+		
+	def add_text(self, filename, duration=5):
+		f = open(filename, "r")
+		if f:
+			content = f.read()
+			f.close()
+		if content.replace("\n", "") == "":
+			return
+
+		params = " -scale %s!" % self.vidresolution.replace(":", "x")
+		params += " -font %s -weight 500 -pointsize 75" % font
+		params += " -draw \"gravity northwest fill white text 100,650 '%s'\"" % content
+		params += " -scale %s!" % self.vidresolution.replace(":", "x")
+		image = os.path.splitext(filename)[0] + ".png"
+		convert_image(os.path.join("media", "back.png"), image, params)
+		self.add_image(image, duration)
+		return content
+	
+	def add_image(self, filename, duration=5, fadein=True):
+		print(self.tmppath)
+		tmpfilename = os.path.join(self.tmppath, os.path.basename(filename) + ".mkv")
+		params = " -y -loop 1 -t %d -i %s" % (duration, filename)
+		if fadein:
+			params += " -filter_complex \"fade=in:0:d=1[v];[v]fade=out:st=%f:d=2\"" % ((duration-2))
+		else:
+			params += " -filter_complex \"fade=out:st=%f:d=1\"" % ((duration-3))
+		params += self.qfilter
+		start(tmpfilename, params)
+		wait()
+
+		self.pconcat += " -i %s" % (tmpfilename)
+		self.nconcat+=1
+	
+	def add_video(self, filename):
+		# fade video temporarily
+		tmpfilename = os.path.join(self.tmppath, os.path.basename(filename))
+		(w,h) = self.vidresolution.split(":")
+		params = " -y -i %s -filter_complex \"scale=-1:%s[v];[v]crop=%s:0:0[v];[v]fade=in:0:10\"" % (filename, h, self.vidresolution)
+		params += self.qfilter
+		start(tmpfilename, params)
+		wait()
+		
+		self.pconcat += " -i %s" % (tmpfilename)
+		self.nconcat+=1
+
+	def speedup(self, filename, pts=0.7):
+		params = " -i %s -y -filter:v \"setpts=%f*PTS\"" % (self.lastfilename, pts)
+		params += self.qfilter
+		self.lastfilename = filename
+		start(filename, params)
+		wait()
+
+	def mux(self, filename, audiofile):
+		duration = video_duration(self.lastfilename)
+		params = " -i %s -i %s -y" % (self.lastfilename, audiofile)
+		params += " -t %d" % (int(duration)+1)
+		params += " -af \"afade=out:st=%f:d=3\"" % (duration-3.0)
+		params += " -map 0:v:0 -map 1:a:0"
+		params += self.qfilter
+		self.lastfilename = filename
+		start(filename, params)
+		wait()
+
+	def filter(self, filter):
+		self.vidfilter = filter
+
+	def resolution(self, resolution):
+		self.vidresolution = resolution
+
+	def concat(self, filename, audio=False):
+		if self.lastfilename != "":
+			self.nconcat += 1
+			self.pconcat = "-i %s %s " % (self.lastfilename, self.pconcat)
+
+		if audio:
+			a=1
+		else:
+			a=0
+		if len(self.vidfilter) > 0:
+			params = self.pconcat + " -y -filter_complex \"concat=n=%d:v=1:a=%d,%s\"" % (a, self.nconcat, ",".join(self.vidfilter))
+		else:
+			params = self.pconcat + " -y -filter_complex concat=n=%d:v=1:a=%d" % (self.nconcat, a)
+		self.lastfilename = filename
+		params += self.qfilter
+		start(filename, params)
+		wait()
+
+	def filename(self, filename):
+		self.lastfilename = filename
+
+	def framerate(self, framerate):
+		self.framerate = framerate
+
+	def tmppath(self, path):
+		self.tmppath = path
+
+	def process(self, filename, param):
+		params = " -y -i %s %s " % (self.lastfilename, param)
+		self.lastfilename = filename
+		params += self.qfilter
+		start(filename, params)
+		wait()
+		
+		
+