| a/trunk/tubetutor/ffmpeg.py | b/trunk/tubetutor/ffmpeg.py | ||
|---|---|---|---|
| ... | ... | ||
| 17 | #font="Arial" | 17 | #font="Arial" | 
| 18 | font=os.path.join("media", "Roboto-Regular.ttf") | 18 | font=os.path.join("media", "Roboto-Regular.ttf") | 
| 19 | proc_ffmpeg=None | 19 | proc_ffmpeg=None | 
| 20 | 20 | ||
| 21 | if platform.system() == "Linux": | 21 | if platform.system() == "Linux": | 
| 22 | grabber="-video_size 1920x1080 -f x11grab -framerate 20 -i :0.0" | 22 |     grabber="-video_size 1920x1080 -f x11grab -framerate 20 -i :0.0 -f pulse -i 1" | 
| 23 | else: | 23 | else: | 
| 24 | grabber="-f gdigrab -framerate 20 -i desktop" | 24 | grabber="-f gdigrab -framerate 20 -i desktop" | 
| 25 | 25 | ||
| 26 | # | 26 | # | 
| 27 | # The following helper functions will retrieve the pathnames for the ffmpeg tools | 27 | # The following helper functions will retrieve the pathnames for the ffmpeg tools | 
| 28 | # | 28 | # | 
| 29 | def get_cmd_ffmpeg(): | 29 | def get_cmd_ffmpeg(): | 
| 30 | subdir=os.path.join(os.path.dirname(sys.argv[0]), "ffmpeg") | 30 |     subdir=os.path.join(os.path.dirname(sys.argv[0]), "ffmpeg -loglevel verbose") | 
| 31 | if os.path.exists(subdir): | 31 | if os.path.exists(subdir): | 
| 32 | return os.path.join(subdir, "ffmpeg.exe") | 32 |         return os.path.join(subdir, "ffmpeg.exe -loglevel verbose") | 
| 33 | return "ffmpeg" | 33 |     return "ffmpeg -loglevel verbose" | 
| 34 | 34 | ||
| 35 | def get_cmd_ffprobe(): | 35 | def get_cmd_ffprobe(): | 
| 36 | subdir=os.path.join(os.path.dirname(sys.argv[0]), "ffmpeg") | 36 | subdir=os.path.join(os.path.dirname(sys.argv[0]), "ffmpeg") | 
| 37 | if os.path.exists(subdir): | 37 | if os.path.exists(subdir): | 
| 38 | return os.path.join(subdir, "ffprobe.exe") | 38 | return os.path.join(subdir, "ffprobe.exe") | 
| ... | ... | ||
| 55 | cmd += " " + output | 55 | cmd += " " + output | 
| 56 |     print ("====================================================") | 56 |     print ("====================================================") | 
| 57 |     print ("cmd: %s" % cmd) | 57 |     print ("cmd: %s" % cmd) | 
| 58 | p = subprocess.Popen(cmd, stdout=subprocess.PIPE, shell=True) | 58 | p = subprocess.Popen(cmd, stdout=subprocess.PIPE, shell=True) | 
| 59 | (out, error) = p.communicate() | 59 | (out, error) = p.communicate() | 
| 60 | if p.returncode != 0: | ||
| 61 |         raise Exception('error: command failed: %s' % cmd) | ||
| 60 |     print("output:\n%s" % out) | 62 |     print("output:\n%s" % out) | 
| 61 |     print("error:\n%s" % error) | 63 |     print("error:\n%s" % error) | 
| 62 | 64 | ||
| 63 | def start(filename, params): | 65 | def start(filename, params): | 
| 64 | global proc_ffmpeg | 66 | global proc_ffmpeg | 
| ... | ... | ||
| 99 | cmd += " -show_entries format=duration" | 101 | cmd += " -show_entries format=duration" | 
| 100 |     print ("====================================================") | 102 |     print ("====================================================") | 
| 101 |     print ("cmd: %s" % cmd) | 103 |     print ("cmd: %s" % cmd) | 
| 102 | p = subprocess.Popen(cmd, stdout=subprocess.PIPE, shell=True) | 104 | p = subprocess.Popen(cmd, stdout=subprocess.PIPE, shell=True) | 
| 103 | (output, error) = p.communicate() | 105 | (output, error) = p.communicate() | 
| 106 | if p.returncode != 0: | ||
| 107 |         raise Exception('error: command failed: %s' % cmd) | ||
| 104 |     print("duration output: %s - %s" % (output, error)) | 108 |     print("duration output: %s - %s" % (output, error)) | 
| 105 | durations = re.findall(r'duration=[0-9.]*', str(output)) | 109 | durations = re.findall(r'duration=[0-9.]*', str(output)) | 
| 106 | for d in durations: | 110 | for d in durations: | 
| 107 |         duration = d.split("=")[1] | 111 |         duration = d.split("=")[1] | 
| 108 |         print("duration string: %s" % duration) | 112 |         print("duration string: %s" % duration) | 
| ... | ... | ||
| 147 |         convert_image(os.path.join("media", "back.png"), image, params) | 151 |         convert_image(os.path.join("media", "back.png"), image, params) | 
| 148 | self.add_image(image, duration) | 152 | self.add_image(image, duration) | 
| 149 | return content | 153 | return content | 
| 150 | 154 | ||
| 151 | def add_image(self, filename, duration=5, fadein=True): | 155 | def add_image(self, filename, duration=5, fadein=True): | 
| 152 |         print(self.tmppath) | 156 |         print("*** add_image(%s, %d, %s)" % (filename, duration, fadein)) | 
| 153 | tmpimage = os.path.join(self.tmppath, os.path.basename(filename) + ".png") | 157 | tmpimage = os.path.join(self.tmppath, os.path.basename(filename) + ".png") | 
| 154 | tmpfilename = os.path.join(self.tmppath, os.path.basename(filename) + ".mkv") | 158 | tmpfilename = os.path.join(self.tmppath, os.path.basename(filename) + ".mkv") | 
| 155 |         params = " -scale %s!" % self.vidresolution.replace(":", "x") | 159 |         params = " -scale %s!" % self.vidresolution.replace(":", "x") | 
| 156 | convert_image(filename, tmpimage, params) | 160 | convert_image(filename, tmpimage, params) | 
| 157 | 161 | ||
| 158 | params = " -y -loop 1 -t %d -i %s" % (duration, tmpimage) | 162 | params = " -y -loop 1 -t %d -i %s" % (duration, tmpimage) | 
| 163 | # add silent audio | ||
| 164 | params += " -f lavfi -i anullsrc=channel_layout=stereo:sample_rate=44100 -shortest" | ||
| 159 | if fadein: | 165 | if fadein: | 
| 160 | params += " -filter_complex \"fade=in:0:d=1[v];[v]fade=out:st=%f:d=2\"" % ((duration-2)) | 166 | params += " -filter_complex \"fade=in:0:d=1[v];[v]fade=out:st=%f:d=2\"" % ((duration-2)) | 
| 161 | else: | 167 | else: | 
| 162 | params += " -filter_complex \"fade=out:st=%f:d=1\"" % ((duration-3)) | 168 | params += " -filter_complex \"fade=out:st=%f:d=1\"" % ((duration-3)) | 
| 163 | params += self.qfilter | 169 | params += self.qfilter | 
| ... | ... | ||
| 166 | 172 | ||
| 167 | self.pconcat += " -i %s" % (tmpfilename) | 173 | self.pconcat += " -i %s" % (tmpfilename) | 
| 168 | self.nconcat+=1 | 174 | self.nconcat+=1 | 
| 169 | 175 | ||
| 170 | def add_video(self, filename): | 176 | def add_video(self, filename): | 
| 177 |         print("*** add_video(%s)" % (filename)) | ||
| 171 | # fade video temporarily | 178 | # fade video temporarily | 
| 172 | tmpfilename = os.path.join(self.tmppath, "add_" + os.path.basename(filename)) | 179 | tmpfilename = os.path.join(self.tmppath, "add_" + os.path.basename(filename)) | 
| 173 |         (w,h) = self.vidresolution.split(":") | 180 |         (w,h) = self.vidresolution.split(":") | 
| 174 | 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) | 181 | 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) | 
| 175 | params += self.qfilter | 182 | params += self.qfilter | 
| ... | ... | ||
| 178 | 185 | ||
| 179 | self.pconcat += " -i %s" % (tmpfilename) | 186 | self.pconcat += " -i %s" % (tmpfilename) | 
| 180 | self.nconcat+=1 | 187 | self.nconcat+=1 | 
| 181 | 188 | ||
| 182 | def speedup(self, filename, pts=0.7): | 189 | def speedup(self, filename, pts=0.7): | 
| 190 |         print("*** speedup(%s, %f)" % (filename, pts)) | ||
| 183 | params = " -i %s -y -filter:v \"setpts=%f*PTS\"" % (self.lastfilename, pts) | 191 | params = " -i %s -y -filter:v \"setpts=%f*PTS\"" % (self.lastfilename, pts) | 
| 184 | params += self.qfilter | 192 | params += self.qfilter | 
| 185 | self.lastfilename = filename | 193 | self.lastfilename = filename | 
| 186 | start(filename, params) | 194 | start(filename, params) | 
| 187 | wait() | 195 | wait() | 
| 188 | 196 | ||
| 189 | def mux(self, filename, audiofile): | 197 | def mux(self, filename, audiofile): | 
| 198 |         print("*** mux(%s, %s)" % (filename, audiofile)) | ||
| 190 | duration = video_duration(self.lastfilename) | 199 | duration = video_duration(self.lastfilename) | 
| 191 | params = " -i %s -i %s -y" % (self.lastfilename, audiofile) | 200 | params = " -i %s -i %s -y" % (self.lastfilename, audiofile) | 
| 192 | params += " -t %d" % (int(duration)+1) | 201 | params += " -t %d" % (int(duration)+1) | 
| 193 |         params += " -af \"afade=out:st=%f:d=3\"" % (duration-3.0) | 202 |         params += " -filter_complex \"[0:a][1:a]amerge,afade=out:st=%f:d=3\"" % (duration-3.0) | 
| 194 | params += " -map 0:v:0 -map 1:a:0" | 203 | params += " -map 0:v:0 -map 1:a:0" | 
| 195 | params += self.qfilter | 204 | params += self.qfilter | 
| 196 | self.lastfilename = filename | 205 | self.lastfilename = filename | 
| 197 | start(filename, params) | 206 | start(filename, params) | 
| 198 | wait() | 207 | wait() | 
| ... | ... | ||
| 236 | self.lastfilename = filename | 245 | self.lastfilename = filename | 
| 237 | params += self.qfilter | 246 | params += self.qfilter | 
| 238 | start(filename, params) | 247 | start(filename, params) | 
| 239 | wait() | 248 | wait() | 
| 240 | 249 | ||
| 241 | 250 | ||
| 242 | 251 |