Exemplo n.º 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
Exemplo n.º 2
0
def gen_video(video_path: str,
              input_frames_dir: str,
              video_frame_rate: str,
              input_image_extension: str = '.jpg',
              encoding: str = 'libx265',
              crf: int = 0) -> None:
    """Use ffmpeg to read generate a video from frames.
	Requires 'ffmpeg' to be on the command line.
	The resulting JPEG frames will be named in the format '%06d.jpg'.
	"""
    input_format_str = pjoin(input_frames_dir,
                             "%06d{}".format(input_image_extension))
    wrap_cmd_call([
        'ffmpeg',
        '-f',
        'concat',  # I don't remember why!
        '-r',
        video_frame_rate,  # we don't know this because we just have frames
        '-safe',
        '0',  # just allow any filename
        '-i',
        input_format_str,
        '-vf',
        'scale=trunc(iw/2)*2:trunc(ih/2)*2',  # compatibility with some players, including QuickTime
        '-c:v',
        encoding,
        '-crf',
        crf,
        '-pix_fmt',
        'yuv420p',
        '-y',
        video_path
    ])
Exemplo n.º 3
0
def fix_path(path: str) -> str:
    # ffmpeg won't recognize './' and will simply not write images!
    # and Python doesn't recognize ~
    if '%' in path:
        raise ValueError(
            'For technical limitations (regarding ffmpeg), local paths cannot contain a percent sign (%), but "{}" does'
            .format(path))
    if path == '~': return os.environ['HOME']  # prevent out of bounds
    if path.startswith('~'):
        path = pjoin(os.environ['HOME'], path[2:])
    return path.replace('./', '')
Exemplo n.º 4
0
def fix_path_platform_dependent(path: str) -> str:
    """Modifies path strings to work with Python and external tools.
	Replaces a beginning '~' with the HOME environment variable.
	Also accepts either / or \ (but not both) as a path separator in windows. 
	"""
    path = fix_path(path)
    # if windows, allow either / or \, but not both
    if platform.system() == 'Windows':
        bits = re.split('[/\\\\]', path)
        return pjoin(*bits).replace(":", ":\\")
    else:
        return path
Exemplo n.º 5
0
def pjoin_sanitized_rel(*pieces: Iterable[any]) -> str:
    """Builds a path from a hierarchy, sanitizing the path by replacing /, :, <, >, ", ', \, |, ?, *, <DEL>, and control characters 0–32 with a hyphen-minus (-).
	Each input to pjoin_sanitized must refer only to a single directory or file (cannot contain a path separator).
	This means that you cannot have an absolute path (it would begin with os.path (probably /); use pjoin_sanitized_abs for this.
	"""
    return pjoin(*[_sanitize_bit(str(bit)) for bit in pieces])
Exemplo n.º 6
0
def pjoin_sanitized_abs(*pieces: Iterable[any]) -> str:
    """Same as pjoin_sanitized_rel but starts with os.sep (the root directory)."""
    return pjoin(os.sep, pjoin_sanitized_rel(*pieces))