def _get_caller(log_cb=None): def _log_call(*lines): _log(lines, prefix=" ", stream="call") def _log_stdout(*lines): _log(lines, prefix=">", stream="stdout") def _log_stderr(*lines): _log(lines, prefix="!", stream="stderr") def _log(lines, prefix=None, stream=None): if log_cb is None: return log_cb(lines, prefix=prefix, stream=stream) caller = CommandlineCaller() if log_cb is not None: caller.on_log_call = _log_call caller.on_log_stdout = _log_stdout caller.on_log_stderr = _log_stderr return caller
def _do_copy_log(self): # Get the name of the tarball we're going to copy the log # files to. tarball_filename = self.build_tarball_filename() self._log("tarball = <%s>" % tarball_filename) # Get the location where we're going to save the tarball. logpath = self.find_logpath() self._log("logpath = <%s>" % logpath) # Build the full path to the tarball tarball_path = os.path.join(logpath, tarball_filename) self._log("tarball_path = <%s>" % tarball_path) # Get the names of the log files logfiles = self.get_log_file_names() self._log("logfiles = <%s>" % logfiles) # Now build the command. command = "tar cvf %s %s" % (tarball_path, logfiles) self._log("command = <%s>" % command) # Construct a commandline caller to run the tar command. caller = CommandlineCaller() caller.on_log_call = self.display_call_stdout caller.on_log_stdout = self.display_call_stdout caller.on_log_stderr = self.display_stderr # Execute the command. self.display("") caller.call(command) # Finish off with a message stating that the tarball has been # created. done_message = "Logs copied to file \"%s\"" % tarball_path self._log(done_message) self.display("\n" + done_message) self.display("")
def _render(self): """Rendering runnable.""" ffmpeg = settings().get(["webcam", "ffmpeg"]) commandline = settings().get(["webcam", "ffmpegCommandline"]) bitrate = settings().get(["webcam", "bitrate"]) if ffmpeg is None or bitrate is None: self._logger.warning( "Cannot create movie, path to ffmpeg or desired bitrate is unset" ) return if self._videocodec == "mpeg2video": extension = "mpg" else: extension = "mp4" input = os.path.join( self._capture_dir, self._capture_format.format( prefix=self._prefix, postfix=self._postfix if self._postfix is not None else "", ), ) output_name = self._output_format.format( prefix=self._prefix, postfix=self._postfix if self._postfix is not None else "", extension=extension, ) temporary = os.path.join(self._output_dir, ".{}".format(output_name)) output = os.path.join(self._output_dir, output_name) for i in range(4): if os.path.exists(input % i): break else: self._logger.warning("Cannot create a movie, no frames captured") self._notify_callback( "fail", output, returncode=0, stdout="", stderr="", reason="no_frames" ) return hflip = settings().getBoolean(["webcam", "flipH"]) vflip = settings().getBoolean(["webcam", "flipV"]) rotate = settings().getBoolean(["webcam", "rotate90"]) watermark = None if settings().getBoolean(["webcam", "watermark"]): watermark = os.path.join( os.path.dirname(__file__), "static", "img", "watermark.png" ) if sys.platform == "win32": # Because ffmpeg hiccups on windows' drive letters and backslashes we have to give the watermark # path a special treatment. Yeah, I couldn't believe it either... watermark = watermark.replace("\\", "/").replace(":", "\\\\:") # prepare ffmpeg command command_str = self._create_ffmpeg_command_string( commandline, ffmpeg, self._fps, bitrate, self._threads, input, temporary, self._videocodec, hflip=hflip, vflip=vflip, rotate=rotate, watermark=watermark, ) self._logger.debug("Executing command: {}".format(command_str)) with self.render_job_lock: try: self._notify_callback("start", output) self._logger.debug("Parsing ffmpeg output") c = CommandlineCaller() c.on_log_stderr = self._process_ffmpeg_output returncode, stdout_text, stderr_text = c.call( command_str, delimiter=b"\r", buffer_size=512 ) self._logger.debug("Done with parsing") if returncode == 0: shutil.move(temporary, output) self._notify_callback("success", output) else: self._logger.warning( "Could not render movie, got return code %r: %s" % (returncode, stderr_text) ) self._notify_callback( "fail", output, returncode=returncode, stdout=stdout_text, stderr=stderr_text, reason="returncode", ) except Exception: self._logger.exception("Could not render movie due to unknown error") self._notify_callback("fail", output, reason="unknown") finally: try: if os.path.exists(temporary): os.remove(temporary) except Exception: self._logger.warning( "Could not delete temporary timelapse {}".format(temporary) ) self._notify_callback("always", output)