示例#1
0
def extract_frames(video_path: str, output_frames_dir: str, notification_path: Optional[str]=None, quality: int=0) -> None:
	"""Use ffmpeg to read a video file and extract the frames.
	Requires 'ffmpeg' to be on the command line.
	The resulting JPEG frames will be named in the format '%06d.jpg'.
	Uses notification_path to indicate whether the extraction completed;
	this will be named video_path'/.finished-extraction' if None.
	Will warn and write over the output dir if it exists but no file at notification_path exists.
	Quality must be between 0 and 31, where 0 is the highest.
	"""
	if notification_path is None: notification_path = pjoin(dirname(video_path), ".finished-extraction")

	if pexists(notification_path) and pexists(output_frames_dir):
		logger.info("Frames directory {} is already complete; skipping.".format(output_frames_dir))
	else:

		if pexists(output_frames_dir):
			logger.warn("Frames directory {} already exists but is incomplete. Extracting frames...".format(output_frames_dir))
		else:
			logger.info("Extracting frames into {}".format(output_frames_dir))

		if not pexists(video_path):
			raise ValueError('Cannot extract frames: video.avi does not exist')

		wrap_cmd_call([
				'ffmpeg',
				'-i', video_path,
				'-q:v', quality,
				pjoin(output_frames_dir, '%06d.jpg')
		])
		with open(notification_path, 'w'): print('')  # all done
示例#2
0
    def run(self, args: List[str]) -> None:

        full_args = self.parser.parse_args(args[1:2])
        subcommand = full_args.subcommand.replace('-', '_')

        if not hasattr(self.target,
                       subcommand) and not subcommand.startswith('_'):
            print(Fore.RED + 'Unrecognized subcommand {}'.format(subcommand))
            self.parser.print_help()
            return

        # clever; from Chase Seibert: https://chase-seibert.github.io/blog/2014/03/21/python-multilevel-argparse.html
        # use dispatch pattern to invoke method with same name
        try:
            if self.temp_dir is not None:
                if pexists(self.temp_dir) and pdir(self.temp_dir):
                    shutil.rmtree(self.temp_dir)
                elif pexists(self.temp_dir):
                    raise InvalidDirectoryException(self.temp_dir)
                remake_dirs(self.temp_dir)
                logger.debug("Created temp dir at {}".format(self.temp_dir))
            getattr(self.target, subcommand)()
        except NaturalExpectedException as e:
            pass  # ignore totally
        except KeyboardInterrupt as e:
            try:
                logger.fatal("Received cancellation signal", exc_info=True)
                self.cancel_handler(e)
            except BaseException:
                pass
            raise e
        except SystemExit as e:
            try:
                logger.fatal("Received system exit signal", exc_info=True)
                self.cancel_handler(e)
            except BaseException:
                pass
            raise e
        except BaseException as e:
            try:
                logger.fatal("{} failed!".format(self.parser.prog),
                             exc_info=True)
                self.error_handler(e)
            except BaseException:
                pass
            raise e
        finally:
            if self.temp_dir is not None:
                if pexists(self.temp_dir):
                    logger.debug("Deleted temp dir at {}".format(
                        self.temp_dir))
                    shutil.rmtree(self.temp_dir)
                    try:
                        os.remove(self.temp_dir)
                    except IOError:
                        pass
示例#3
0
def pempty(s: str):
    """
	Assesses whether the path is "empty" OR does not exist.
	Returns False if the path exists or is either:
		- A socket or block device (even if "empty" -- does not attempt to read)
		- A nonempty file
		- A directory containing subpaths
		- A symlink to a nonempty file
	Currently DOES NOT HANDLE: Symlinks to anything other than a file. Will raise a TypeError.
	"""
    if not pexists(s): return True
    s = Path(s)
    if s.is_block_device() or s.is_socket():
        return False
    elif s.is_dir():
        # short-circuit
        for _ in s.iterdir():
            return False
        return True
    elif s.is_symlink():
        target = Path(os.readlink(str(s)))
        if not target.exists():
            return True
        if target.is_file():
            return s.lstat().st_size == 0
        # TODO if dir without infinite loops
    elif s.is_file():
        return s.stat().st_size == 0
    raise TypeError("Unknown path type {}".format(s))
示例#4
0
def sevenz(dir_to_sevenz: str,
           sevenz_path: str,
           overwrite: OverwriteChoice = OverwriteChoice.FAIL,
           _7z_executable: str = '7z') -> None:
    """7-zips a directory and adds a .sha256 with the same base filename of the output archive.
	Leaves the original directory when it finishes.
	Requires '7z' to be on the command line.
	"""
    if not pexists(dir_to_sevenz):
        raise InvalidDirectoryException(
            "The path {} to 7-zip does not exist".format(dir_to_sevenz))
    if not pdir(dir_to_sevenz):
        raise InvalidDirectoryException(
            "The path {} to 7-zip is not a directory".format(dir_to_sevenz))

    file_hasher = FileHasher(algorithm=hashlib.sha256, extension='.sha256')
    logging.info("7-zipping files in {}".format(dir_to_sevenz))

    if pexists(sevenz_path) and not pfile(sevenz_path):
        raise InvalidFileException(
            "The 7-zip file cannot be written to {}: The path exists and is not a file"
            .format(sevenz_path))

    if pexists(sevenz_path):
        if overwrite is OverwriteChoice.FAIL:
            raise InvalidFileException(
                "Cannot proceed: The 7-zip file {} already exists.".format(
                    sevenz_path))
        elif overwrite is OverwriteChoice.WARN:
            warnings.warn(
                "The 7-zip file {} already exists. Won't overwrite.".format(
                    sevenz_path))
        elif overwrite is OverwriteChoice.OVERWRITE:
            os.remove(sevenz_path)
        elif overwrite is OverwriteChoice.IGNORE:
            pass

    wrap_cmd_call([_7z_executable, 'a', sevenz_path, dir_to_sevenz])
    file_hasher.add_hash(sevenz_path)  # will overwrite regardless
示例#5
0
def file_from_env_var(var: str) -> str:
    """
	Just returns the path of a file specified in an environment variable, checking that it's a file.
	Will raise a MissingResourceException error if not set or not a file.
	:param var: The environment variable name, not including the $
	"""
    if var not in os.environ:
        raise MissingResourceException(
            'Environment variable ${} is not set'.format(var))
    config_file_path = fix_path(os.environ[var])
    if not pexists(config_file_path):
        raise MissingResourceException("{} file {} does not exist".format(
            var, config_file_path))
    if not pfile(config_file_path):
        raise MissingResourceException("{} file {} is not a file".format(
            var, config_file_path))
    return config_file_path