Exemple #1
0
def create_video_queue_vs(project: Project, split_locations: List[int],
                          script: str) -> List[Chunk]:
    """
    Create a list of chunks using vspipe and ffms2 for frame accurate seeking

    :param project: the Project
    :param split_locations: a list of frames to split on
    :param script: source filter script to use with vspipe (ignored with vs input)
    :return: A list of chunks
    """
    # add first frame and last frame
    last_frame = project.get_frames()
    split_locs_fl = [0] + split_locations + [last_frame]

    # pair up adjacent members of this list ex: [0, 10, 20, 30] -> [(0, 10), (10, 20), (20, 30)]
    chunk_boundaries = zip(split_locs_fl, split_locs_fl[1:])

    source_file = project.input.absolute().as_posix()
    vs_script = project.input

    if not project.is_vs:
        # create a vapoursynth script that will load the source with ffms2
        load_script = project.temp / 'split' / 'loadscript.vpy'
        cache_file = (project.temp / 'split' /
                      'ffms2cache.ffindex').absolute().as_posix()
        with open(load_script, 'w+') as file:
            file.write(script.format(source_file, cache_file))
        vs_script = load_script

    chunk_queue = [
        create_vs_chunk(project, index, vs_script, *cb)
        for index, cb in enumerate(chunk_boundaries)
    ]

    return chunk_queue
Exemple #2
0
def create_video_queue_vs(project: Project,
                          split_locations: List[int]) -> List[Chunk]:
    """
    Create a list of chunks using vspipe and ffms2 for frame accurate seeking

    :param project: the Project
    :param split_locations: a list of frames to split on
    :param script: source filter script to use with vspipe (ignored with vs input)
    :return: A list of chunks
    """
    # add first frame and last frame
    last_frame = project.get_frames()
    split_locs_fl = [0] + split_locations + [last_frame]

    # pair up adjacent members of this list ex: [0, 10, 20, 30] -> [(0, 10), (10, 20), (20, 30)]
    chunk_boundaries = zip(split_locs_fl, split_locs_fl[1:])

    source_file = project.input.absolute().as_posix()
    if project.is_vs:
        vs_script = project.input
    else:
        vs_script = create_vs_file(project.temp, source_file,
                                   project.chunk_method)

    chunk_queue = [
        create_vs_chunk(project, index, vs_script, *cb)
        for index, cb in enumerate(chunk_boundaries)
    ]

    return chunk_queue
Exemple #3
0
def create_chunk_from_segment(project: Project, index: int,
                              file: Path) -> Chunk:
    """
    Creates a Chunk object from a segment file generated by ffmpeg

    :param project: the Project
    :param index: the index of the chunk
    :param file: the segmented file
    :return: A Chunk
    """
    ffmpeg_gen_cmd = [
        "ffmpeg",
        "-y",
        "-hide_banner",
        "-loglevel",
        "error",
        "-i",
        file.as_posix(),
        *project.pix_format,
        "-f",
        "yuv4mpegpipe",
        "-",
    ]
    file_size = file.stat().st_size
    frames = project.get_frames()
    extension = ENCODERS[project.encoder].output_extension

    chunk = Chunk(project.temp, index, ffmpeg_gen_cmd, extension, file_size,
                  frames)

    return chunk
Exemple #4
0
def startup_check(project: Project):
    """
    Performing essential checks at startup_check
    Set constant values
    """
    if sys.version_info < (3, 6):
        print("Python 3.6+ required")
        sys.exit()
    if sys.platform == "linux":

        def restore_term():
            os.system("stty sane")

        atexit.register(restore_term)

    if project.encoder not in ["rav1e", "aom", "svt_av1", "vpx"] and project.output_ivf:
        print(".ivf only supports VP8, VP9, and AV1")
        sys.exit(1)

    if not project.chunk_method:
        project.select_best_chunking_method()

    project.is_vs = is_vapoursynth(project.input[0])

    if project.is_vs:
        project.chunk_method = "vs_ffms2"

    project.check_exes()

    set_target_quality(project)

    setup_encoder(project)

    project.audio_params = shlex.split(project.audio_params)
    project.ffmpeg = shlex.split(project.ffmpeg)

    project.pix_format = ["-strict", "-1", "-pix_fmt", project.pix_format]
    project.ffmpeg_pipe = [
        *project.ffmpeg,
        *project.pix_format,
        "-f",
        "yuv4mpegpipe",
        "-",
    ]
Exemple #5
0
def setup_encoder(project: Project):
    """
    Setup encoder params and passes
    :param project: the Project
    """
    encoder = ENCODERS[project.encoder]

    # validate encoder settings
    settings_valid, error_msg = encoder.is_valid(project)
    if not settings_valid:
        print(error_msg)
        terminate()

    if project.passes is None:
        project.passes = encoder.default_passes

    project.video_params = encoder.default_args if project.video_params is None \
        else shlex.split(project.video_params)

    validate_inputs(project)
Exemple #6
0
def create_video_queue_select(project: Project,
                              split_locations: List[int]) -> List[Chunk]:
    """
    Create a list of chunks using the select filter

    :param project: the Project
    :param split_locations: a list of frames to split on
    :return: A list of chunks
    """
    # add first frame and last frame
    last_frame = project.get_frames()
    split_locs_fl = [0] + split_locations + [last_frame]

    # pair up adjacent members of this list ex: [0, 10, 20, 30] -> [(0, 10), (10, 20), (20, 30)]
    chunk_boundaries = zip(split_locs_fl, split_locs_fl[1:])

    chunk_queue = [
        create_select_chunk(project, index, project.input, *cb)
        for index, cb in enumerate(chunk_boundaries)
    ]

    return chunk_queue
Exemple #7
0
def create_video_queue_hybrid(project: Project,
                              split_locations: List[int]) -> List[Chunk]:
    """
    Create list of chunks using hybrid segment-select approach

    :param project: the Project
    :param split_locations: a list of frames to split on
    :return: A list of chunks
    """
    keyframes = get_keyframes(str(project.input.resolve()))

    end = [project.get_frames()]

    splits = [0] + split_locations + end

    segments_list = list(zip(splits, splits[1:]))
    to_split = [x for x in keyframes if x in splits]
    segments = []

    # Make segments
    log("Segmenting Video")
    segment(str(project.input.resolve()), str(project.temp.resolve()),
            to_split[1:])
    log("Segment Done")
    source_path = project.temp / "split"
    queue_files = [x for x in source_path.iterdir() if x.suffix == ".mkv"]
    queue_files.sort(key=lambda p: p.stem)

    kf_list = list(zip(to_split, to_split[1:] + end))
    for f, (x, y) in zip(queue_files, kf_list):
        to_add = [(f, [s[0] - x, s[1] - x]) for s in segments_list
                  if s[0] >= x and s[1] <= y and s[0] - x < s[1] - x]
        segments.extend(to_add)

    chunk_queue = [
        create_select_chunk(project, index, file, *cb)
        for index, (file, cb) in enumerate(segments)
    ]
    return chunk_queue
Exemple #8
0
def create_chunk_from_segment(project: Project, index: int,
                              file: Path) -> Chunk:
    """
    Creates a Chunk object from a segment file generated by ffmpeg

    :param project: the Project
    :param index: the index of the chunk
    :param file: the segmented file
    :return: A Chunk
    """
    ffmpeg_gen_cmd = [
        'ffmpeg', '-y', '-hide_banner', '-loglevel', 'error', '-i',
        file.as_posix(), *project.pix_format, '-color_range', '0', '-f',
        'yuv4mpegpipe', '-'
    ]
    file_size = file.stat().st_size
    frames = project.get_frames()
    extension = ENCODERS[project.encoder].output_extension

    chunk = Chunk(project.temp, index, ffmpeg_gen_cmd, extension, file_size,
                  frames)

    return chunk
Exemple #9
0
def startup_check(project: Project):
    """
    Performing essential checks at startup_check
    Set constant values
    """
    if sys.version_info < (3, 6):
        print('Python 3.6+ required')
        sys.exit()
    if sys.platform == 'linux':
        def restore_term():
            os.system("stty sane")

        atexit.register(restore_term)

    if not project.chunk_method:
        project.select_best_chunking_method()

    # project.is_vs = is_vapoursynth(project.input)

    if project.is_vs:
        project.chunk_method = 'vs_ffms2'

    project.check_exes()

    set_target_quality(project)

    if project.reuse_first_pass and project.encoder != 'aom' and project.split_method != 'aom_keyframes':
        print('Reusing the first pass is only supported with \
              the aom encoder and aom_keyframes split method.')
        terminate()

    setup_encoder(project)

    # No check because vvc
    if project.encoder == 'vvc':
        project.no_check = True

    if project.encoder == 'svt_vp9' and project.passes == 2:
        print("Implicitly changing 2 pass svt-vp9 to 1 pass\n2 pass svt-vp9 isn't supported")
        project.passes = 1

    project.audio_params = shlex.split(project.audio_params)
    project.ffmpeg = shlex.split(project.ffmpeg)

    project.pix_format = ['-strict', '-1', '-pix_fmt', project.pix_format]
    project.ffmpeg_pipe = [*project.ffmpeg, *project.pix_format,'-color_range', '0', '-f', 'yuv4mpegpipe', '-']
Exemple #10
0
def startup_check(project: Project):
    """
    Performing essential checks at startup_check
    Set constant values
    """
    if sys.version_info < (3, 6):
        print("Python 3.6+ required")
        sys.exit()
    if sys.platform == "linux":

        def restore_term():
            os.system("stty sane")

        atexit.register(restore_term)

    if not project.chunk_method:
        project.select_best_chunking_method()

    project.is_vs = is_vapoursynth(project.input[0])

    if project.is_vs:
        project.chunk_method = "vs_ffms2"

    project.check_exes()

    set_target_quality(project)

    if (project.reuse_first_pass and project.encoder != "aom"
            and project.split_method != "aom_keyframes"):
        print("Reusing the first pass is only supported with \
              the aom encoder and aom_keyframes split method.")
        terminate()

    setup_encoder(project)

    # No check because vvc
    if project.encoder == "vvc":
        project.no_check = True

    if project.encoder == "svt_vp9" and project.passes == 2:
        print(
            "Implicitly changing 2 pass svt-vp9 to 1 pass\n2 pass svt-vp9 isn't supported"
        )
        project.passes = 1

    project.audio_params = shlex.split(project.audio_params)
    project.ffmpeg = shlex.split(project.ffmpeg)

    project.pix_format = ["-strict", "-1", "-pix_fmt", project.pix_format]
    project.ffmpeg_pipe = [
        *project.ffmpeg,
        *project.pix_format,
        "-f",
        "yuv4mpegpipe",
        "-",
    ]
Exemple #11
0
def get_av1an_proj(args):
    return Project(args)