Esempio n. 1
0
def build(fastflix: FastFlix):
    settings: x264Settings = fastflix.current_video.video_settings.video_encoder_settings

    beginning, ending = generate_all(fastflix, "libx264")

    beginning += f'{f"-tune:v {settings.tune}" if settings.tune else ""} {generate_color_details(fastflix)} '

    if settings.profile and settings.profile != "default":
        beginning += f"-profile:v {settings.profile} "

    pass_log_file = fastflix.current_video.work_path / f"pass_log_file_{secrets.token_hex(10)}"

    if settings.bitrate:
        command_1 = (
            f"{beginning} -pass 1 "
            f'-passlogfile "{pass_log_file}" -b:v {settings.bitrate} -preset:v {settings.preset} {settings.extra if settings.extra_both_passes else ""} -an -sn -dn -f mp4 {null}'
        )
        command_2 = (
            f'{beginning} -pass 2 -passlogfile "{pass_log_file}" '
            f"-b:v {settings.bitrate} -preset:v {settings.preset} {settings.extra} "
        ) + ending
        return [
            Command(command=command_1, name="First pass bitrate", exe="ffmpeg"),
            Command(command=command_2, name="Second pass bitrate", exe="ffmpeg"),
        ]

    elif settings.crf:
        command = f"{beginning} -crf:v {settings.crf} " f"-preset:v {settings.preset} {settings.extra} {ending}"
        return [Command(command=command, name="Single pass CRF", exe="ffmpeg")]

    else:
        return []
Esempio n. 2
0
def build(fastflix: FastFlix):
    settings: AOMAV1Settings = fastflix.current_video.video_settings.video_encoder_settings
    beginning, ending = generate_all(fastflix, "libaom-av1")

    beginning += ("-strict experimental "
                  f"-cpu-used {settings.cpu_used} "
                  f"-tile-rows {settings.tile_rows} "
                  f"-tile-columns {settings.tile_columns} "
                  f"-usage {settings.usage} "
                  f"{generate_color_details(fastflix)} ")

    if settings.row_mt.lower() == "enabled":
        beginning += f"-row-mt 1 "

    if settings.bitrate:
        pass_log_file = fastflix.current_video.work_path / f"pass_log_file_{secrets.token_hex(10)}"
        command_1 = f'{beginning} -passlogfile "{pass_log_file}" -b:v {settings.bitrate} -pass 1 {settings.extra if settings.extra_both_passes else ""} -an -f matroska {null}'
        command_2 = (
            f'{beginning} -passlogfile "{pass_log_file}" -b:v {settings.bitrate} -pass 2 {settings.extra} {ending}'
        )
        return [
            Command(command=command_1, name="First Pass bitrate"),
            Command(command=command_2, name="Second Pass bitrate"),
        ]
    elif settings.crf:
        command_1 = f"{beginning} -b:v 0 -crf {settings.crf} {settings.extra} {ending}"
        return [Command(command=command_1, name="Single Pass CRF")]
Esempio n. 3
0
def build(fastflix: FastFlix):
    settings: FFmpegNVENCSettings = fastflix.current_video.video_settings.video_encoder_settings

    beginning, ending = generate_all(fastflix, "hevc_nvenc")

    beginning += f'{f"-tune:v {settings.tune}" if settings.tune else ""} {generate_color_details(fastflix)} -spatial_aq:v {settings.spatial_aq} -tier:v {settings.tier} -rc-lookahead:v {settings.rc_lookahead} -gpu {settings.gpu} -b_ref_mode {settings.b_ref_mode} '

    if settings.profile:
        beginning += f"-profile:v {settings.profile} "

    if settings.rc:
        beginning += f"-rc:v {settings.rc} "

    if settings.level:
        beginning += f"-level:v {settings.level} "

    pass_log_file = fastflix.current_video.work_path / f"pass_log_file_{secrets.token_hex(10)}"

    command_1 = (
        f"{beginning} -pass 1 "
        f'-passlogfile "{pass_log_file}" -b:v {settings.bitrate} -preset:v {settings.preset} -2pass 1 '
        f'{settings.extra if settings.extra_both_passes else ""} -an -sn -dn -f mp4 {null}'
    )
    command_2 = (
        f'{beginning} -pass 2 -passlogfile "{pass_log_file}" -2pass 1 '
        f"-b:v {settings.bitrate} -preset:v {settings.preset} {settings.extra} "
    ) + ending
    return [
        Command(command=command_1, name="First pass bitrate", exe="ffmpeg"),
        Command(command=command_2, name="Second pass bitrate", exe="ffmpeg"),
    ]
Esempio n. 4
0
def build(fastflix: FastFlix):
    settings: AOMAV1Settings = fastflix.current_video.video_settings.video_encoder_settings
    beginning, ending = generate_all(fastflix, "libaom-av1")

    beginning += ("-strict experimental "
                  f"-cpu-used {settings.cpu_used} "
                  f"-tile-rows {settings.tile_rows} "
                  f"-tile-columns {settings.tile_columns} "
                  f"-usage {settings.usage} "
                  f"{generate_color_details(fastflix)} ")

    if settings.row_mt.lower() == "enabled":
        beginning += f"-row-mt 1 "

    beginning = re.sub("[ ]+", " ", beginning)

    if settings.bitrate:
        pass_log_file = fastflix.current_video.work_path / f"pass_log_file_{secrets.token_hex(10)}.log"
        command_1 = f'{beginning} -passlogfile "{pass_log_file}" -b:v {settings.bitrate} -pass 1 -an -f matroska {null}'
        command_2 = f'{beginning} -passlogfile "{pass_log_file}" -b:v {settings.bitrate} -pass 2' + ending
        return [
            Command(command_1, ["ffmpeg", "output"],
                    False,
                    name="First Pass bitrate"),
            Command(command_2, ["ffmpeg", "output"],
                    False,
                    name="Second Pass bitrate"),
        ]
    elif settings.crf:
        command_1 = f"{beginning} -b:v 0 -crf {settings.crf}" + ending
        return [
            Command(command_1, ["ffmpeg", "output"],
                    False,
                    name="Single Pass CRF")
        ]
Esempio n. 5
0
def build(fastflix: FastFlix):
    settings: rav1eSettings = fastflix.current_video.video_settings.video_encoder_settings
    beginning, ending = generate_all(fastflix, "librav1e")

    beginning += ("-strict experimental "
                  f"-speed {settings.speed} "
                  f"-tile-columns {settings.tile_columns} "
                  f"-tile-rows {settings.tile_rows} "
                  f"-tiles {settings.tiles} "
                  f"{generate_color_details(fastflix)} ")

    # if not fastflix.current_video.video_settings.remove_hdr:

    # Currently unsupported https://github.com/xiph/rav1e/issues/2554
    #         rav1e_options = []
    # if side_data.master_display:
    #     rav1e_options.append(
    #         "mastering-display="
    #         f"G{side_data.master_display.green}"
    #         f"B{side_data.master_display.blue}"
    #         f"R{side_data.master_display.red}"
    #         f"WP{side_data.master_display.white}"
    #         f"L{side_data.master_display.luminance}"
    #     )
    #
    # if side_data.cll:
    #     rav1e_options.append(f"content-light={side_data.cll}")
    # if rav1e_options:
    #     opts = ":".join(rav1e_options)
    #     beginning += f'-rav1e-params "{opts}"'

    beginning = re.sub("[ ]+", " ", beginning)

    if not settings.single_pass:
        pass_log_file = fastflix.current_video.work_path / f"pass_log_file_{secrets.token_hex(10)}"
        beginning += f'-passlogfile "{pass_log_file}" '

    pass_type = "bitrate" if settings.bitrate else "QP"

    if not settings.bitrate:
        command_1 = f"{beginning} -qp {settings.qp} {settings.extra} {ending}"
        return [Command(command=command_1, name=f"{pass_type}", exe="ffmpeg")]

    if settings.single_pass:
        command_1 = f"{beginning} -b:v {settings.bitrate} {settings.extra} {ending}"
        return [Command(command=command_1, name=f"{pass_type}", exe="ffmpeg")]
    else:
        command_1 = f"{beginning} -b:v {settings.bitrate} -pass 1 {settings.extra if settings.extra_both_passes else ''} -an -f matroska {null}"
        command_2 = f"{beginning} -b:v {settings.bitrate} -pass 2 {settings.extra} {ending}"
        return [
            Command(command=command_1,
                    name=f"First pass {pass_type}",
                    exe="ffmpeg"),
            Command(command=command_2,
                    name=f"Second pass {pass_type} ",
                    exe="ffmpeg"),
        ]
Esempio n. 6
0
def build(fastflix: FastFlix):
    settings: VP9Settings = fastflix.current_video.video_settings.video_encoder_settings
    beginning, ending = generate_all(fastflix, "libvpx-vp9")

    beginning += f'{"-row-mt 1" if settings.row_mt else ""} ' f"{generate_color_details(fastflix)} "

    if not settings.single_pass:
        pass_log_file = fastflix.current_video.work_path / f"pass_log_file_{secrets.token_hex(10)}"
        beginning += f'-passlogfile "{pass_log_file}" '

    # TODO color_range 1
    # if not fastflix.current_video.video_settings.remove_hdr and settings.pix_fmt in ("yuv420p10le", "yuv420p12le"):
    #     if fastflix.current_video.color_space.startswith("bt2020"):
    #         beginning += "-color_primaries bt2020 -color_trc smpte2084 -colorspace bt2020nc -color_range 1"

    details = f"-quality:v {settings.quality} -profile:v {settings.profile} -tile-columns:v {settings.tile_columns} -tile-rows:v {settings.tile_rows} "

    if settings.bitrate:
        if settings.quality == "realtime":
            return [
                Command(
                    command=
                    f"{beginning} -speed:v {settings.speed} -b:v {settings.bitrate} {details} {settings.extra} {ending} ",
                    name="Single pass realtime bitrate",
                    exe="ffmpeg",
                )
            ]
        command_1 = f"{beginning} -speed:v {'4' if settings.fast_first_pass else settings.speed} -b:v {settings.bitrate} {details} -pass 1 {settings.extra if settings.extra_both_passes else ''} -an -f webm {null}"
        command_2 = (
            f"{beginning} -speed:v {settings.speed} -b:v {settings.bitrate} {details} -pass 2 {settings.extra} {ending}"
        )

    elif settings.crf:
        command_1 = f"{beginning} -b:v 0 -crf:v {settings.crf} {details} -pass 1 {settings.extra if settings.extra_both_passes else ''} -an -f webm {null}"
        command_2 = (
            f"{beginning} -b:v 0 -crf:v {settings.crf} {details} "
            f'{"-pass 2" if not settings.single_pass else ""} {settings.extra} {ending}'
        )

    else:
        return []

    if settings.crf and settings.single_pass:
        return [
            Command(command=command_2, name="Single pass CRF", exe="ffmpeg")
        ]
    pass_type = "bitrate" if settings.bitrate else "CRF"

    return [
        Command(command=command_1,
                name=f"First pass {pass_type}",
                exe="ffmpeg"),
        Command(command=command_2,
                name=f"Second pass {pass_type} ",
                exe="ffmpeg"),
    ]
Esempio n. 7
0
def build(fastflix: FastFlix):
    settings: SVTAV1Settings = fastflix.current_video.video_settings.video_encoder_settings
    beginning, ending = generate_all(fastflix, "libsvtav1")

    beginning += (f"-strict experimental "
                  f"-preset {settings.speed} "
                  f"-tile_columns {settings.tile_columns} "
                  f"-tile_rows {settings.tile_rows} "
                  f"-tier {settings.tier} "
                  f"{generate_color_details(fastflix)} ")

    beginning = re.sub("[ ]+", " ", beginning)

    if not settings.single_pass:
        pass_log_file = fastflix.current_video.work_path / f"pass_log_file_{secrets.token_hex(10)}.log"
        beginning += f'-passlogfile "{pass_log_file}" '

    pass_type = "bitrate" if settings.bitrate else "QP"

    if settings.single_pass:
        if settings.bitrate:
            command_1 = f"{beginning} -b:v {settings.bitrate} -rc 1" + ending

        elif settings.qp is not None:
            command_1 = f"{beginning} -qp {settings.qp} -rc 0" + ending
        else:
            return []
        return [
            Command(command_1, ["ffmpeg", "output"],
                    False,
                    name=f"{pass_type}",
                    exe="ffmpeg")
        ]
    else:
        if settings.bitrate:
            command_1 = f"{beginning} -b:v {settings.bitrate} -rc 1 -pass 1 -an -f matroska {null}"
            command_2 = f"{beginning} -b:v {settings.bitrate} -rc 1 -pass 2" + ending

        elif settings.qp is not None:
            command_1 = f"{beginning} -qp {settings.qp} -rc 0 -pass 1 -an -f matroska {null}"
            command_2 = f"{beginning} -qp {settings.qp} -rc 0 -pass 2" + ending
        else:
            return []
        return [
            Command(command_1, ["ffmpeg", "output"],
                    False,
                    name=f"First pass {pass_type}",
                    exe="ffmpeg"),
            Command(command_2, ["ffmpeg", "output"],
                    False,
                    name=f"Second pass {pass_type} ",
                    exe="ffmpeg"),
        ]
Esempio n. 8
0
def build(
    source,
    video_track,
    ffmpeg,
    temp_dir,
    output_video,
    fps=15,
    dither="sierra2_4a",
    extra="",
    start_time=0,
    end_time=None,
    **kwargs,
):
    palletgen_filters = generate_filters(video_track=video_track,
                                         custom_filters="palettegen",
                                         **kwargs)
    filters = generate_filters(video_track=video_track,
                               custom_filters=f"fps={fps:.2f}",
                               raw_filters=True,
                               **kwargs)
    output_video = output_video.replace("\\", "/")
    beginning = (f'"{ffmpeg}" -y '
                 f'{f"-ss {start_time}" if start_time else ""} '
                 f'{f"-to {end_time}" if end_time else ""} '
                 f'-i "{source}" ')
    if extra:
        beginning += f" {extra} "

    temp_palette = Path(temp_dir) / f"temp_palette_{secrets.token_hex(10)}.png"

    command_1 = f'{beginning} {palletgen_filters}  -y "{temp_palette}"'

    gif_filters = f"fps={fps:.2f}"
    if filters:
        gif_filters += f",{filters}"

    command_2 = (
        f'{beginning} -i "{temp_palette}" '
        f'-filter_complex "{filters};[v][1:v]paletteuse=dither={dither}[o]" -map "[o]" -y "{output_video}" '
    )

    return [
        Command(command_1, ["ffmpeg", "pallet_file", "output"],
                False,
                name="Pallet generation",
                exe="ffmpeg"),
        Command(command_2, ["ffmpeg", "pallet_file", "output"],
                False,
                name="GIF creation",
                exe="ffmpeg"),
    ]
Esempio n. 9
0
def build(
    source,
    video_track,
    ffmpeg,
    temp_dir,
    output_video,
    fps=15,
    dither="sierra2_4a",
    extra="",
    start_time=0,
    end_time=None,
    **kwargs,
):
    filters = generate_filters(**kwargs)

    beginning = (f'"{ffmpeg}" -y '
                 f'{f"-ss {start_time}" if start_time else ""} '
                 f'{f"-to {end_time}" if end_time else ""} '
                 f'-i "{source}" ')
    if extra:
        beginning += f" {extra} "

    temp_palette = Path(temp_dir) / f"temp_palette_{secrets.token_hex(10)}.png"

    command_1 = (
        f"{beginning} -map 0:{video_track} "
        f'-vf "{f"{filters}," if filters else ""}palettegen" -y "{temp_palette}"'
    )

    gif_filters = f"fps={fps:.2f}"
    if filters:
        gif_filters += f",{filters}"

    command_2 = (
        f'{beginning} -i "{temp_palette}" -map 0:{video_track} '
        f'-lavfi "{gif_filters} [x]; [x][1:v] paletteuse=dither={dither}" -y "{output_video}" '
    )

    return [
        Command(command_1, ["ffmpeg", "pallet_file", "output"],
                False,
                name="Pallet generation",
                exe="ffmpeg"),
        Command(command_2, ["ffmpeg", "pallet_file", "output"],
                False,
                name="GIF creation",
                exe="ffmpeg"),
    ]
Esempio n. 10
0
def build(
    source,
    video_track,
    ffmpeg,
    temp_dir,
    output_video,
    lossless=True,
    compression=6,
    extra="",
    preset="default",
    start_time=0,
    qscale="75",
    **kwargs,
):
    filters = generate_filters(video_track=video_track, **kwargs)
    beginning = generate_ffmpeg_start(source,
                                      ffmpeg,
                                      encoder="libwebp",
                                      video_track=video_track,
                                      start_time=start_time,
                                      filters=filters,
                                      **kwargs)
    ending = generate_ending("", "", "", output_video=output_video, **kwargs)

    return [
        Command(
            f"{beginning}  -lossless {lossless} -compression_level {compression} "
            f"-qscale {qscale} -preset {preset} {extra} {ending}",
            ["ffmpeg", "output"],
            False,
            name="WebP",
            exe="ffmpeg",
        ),
    ]
Esempio n. 11
0
def build(fastflix: FastFlix):
    settings: GIFSettings = fastflix.current_video.video_settings.video_encoder_settings

    args = f"=stats_mode={settings.stats_mode}"
    if settings.max_colors != "256":
        args += f":max_colors={settings.max_colors}"

    palletgen_filters = generate_filters(
        custom_filters=f"palettegen{args}", **fastflix.current_video.video_settings.dict()
    )

    filters = generate_filters(
        custom_filters=f"fps={settings.fps:.2f}", raw_filters=True, **fastflix.current_video.video_settings.dict()
    )

    output_video = clean_file_string(fastflix.current_video.video_settings.output_path)

    beginning = (
        f'"{fastflix.config.ffmpeg}" -y '
        f'{f"-ss {fastflix.current_video.video_settings.start_time}" if fastflix.current_video.video_settings.start_time else ""} '
        f'{f"-to {fastflix.current_video.video_settings.end_time}" if fastflix.current_video.video_settings.end_time else ""} '
        f'{f"-r {fastflix.current_video.video_settings.source_fps } " if fastflix.current_video.video_settings.source_fps else ""}'
        f' -i "{fastflix.current_video.source}" '
    )
    if settings.extra:
        beginning += f"  "

    temp_palette = fastflix.current_video.work_path / f"temp_palette_{secrets.token_hex(10)}.png"

    command_1 = (
        f'{beginning} {palletgen_filters} {settings.extra if settings.extra_both_passes else ""} -y "{temp_palette}"'
    )

    gif_filters = f"fps={settings.fps:.2f}"
    if filters:
        gif_filters += f",{filters}"

    command_2 = (
        f'{beginning} -i "{temp_palette}" '
        f'-filter_complex "{filters};[v][1:v]paletteuse=dither={settings.dither}[o]" -map "[o]" {settings.extra} -y "{output_video}" '
    )

    return [
        Command(command=command_1, name="Pallet generation", exe="ffmpeg"),
        Command(command=command_2, name="GIF creation", exe="ffmpeg"),
    ]
Esempio n. 12
0
def build(fastflix: FastFlix):
    settings: GIFSettings = fastflix.current_video.video_settings.video_encoder_settings

    palletgen_filters = generate_filters(
        custom_filters="palettegen",
        **asdict(fastflix.current_video.video_settings))

    filters = generate_filters(custom_filters=f"fps={settings.fps:.2f}",
                               raw_filters=True,
                               **asdict(fastflix.current_video.video_settings))

    output_video = str(
        fastflix.current_video.video_settings.output_path).replace("\\", "/")
    beginning = (
        f'"{fastflix.config.ffmpeg}" -y '
        f'{f"-ss {fastflix.current_video.video_settings.start_time}" if fastflix.current_video.video_settings.start_time else ""} '
        f'{f"-to {fastflix.current_video.video_settings.end_time}" if fastflix.current_video.video_settings.end_time else ""} '
        f'-i "{fastflix.current_video.source}" ')
    if settings.extra:
        beginning += f" {settings.extra} "

    temp_palette = fastflix.current_video.work_path / f"temp_palette_{secrets.token_hex(10)}.png"

    command_1 = f'{beginning} {palletgen_filters}  -y "{temp_palette}"'

    gif_filters = f"fps={settings.fps:.2f}"
    if filters:
        gif_filters += f",{filters}"

    command_2 = (
        f'{beginning} -i "{temp_palette}" '
        f'-filter_complex "{filters};[v][1:v]paletteuse=dither={settings.dither}[o]" -map "[o]" -y "{output_video}" '
    )

    return [
        Command(command_1, ["ffmpeg", "pallet_file", "output"],
                False,
                name="Pallet generation",
                exe="ffmpeg"),
        Command(command_2, ["ffmpeg", "pallet_file", "output"],
                False,
                name="GIF creation",
                exe="ffmpeg"),
    ]
Esempio n. 13
0
def build(fastflix: FastFlix):

    beginning, ending = generate_all(fastflix, "copy", disable_filters=True)

    return [
        Command(
            command=
            f"{beginning} {fastflix.current_video.video_settings.video_encoder_settings.extra} {ending}",
            name="No Video Encoding",
            exe="ffmpeg",
        )
    ]
Esempio n. 14
0
def build(fastflix: FastFlix):

    beginning, ending = generate_all(fastflix, "copy", disable_filters=True)

    return [
        Command(
            re.sub("[ ]+", " ", f"{beginning} {ending}"),
            ["ffmpeg", "output"],
            False,
            name="No Video Encoding",
            exe="ffmpeg",
        )
    ]
Esempio n. 15
0
def build(fastflix: FastFlix):
    settings: HEVCVideoToolboxSettings = fastflix.current_video.video_settings.video_encoder_settings
    beginning, ending = generate_all(fastflix, "hevc_videotoolbox")

    beginning += generate_color_details(fastflix)

    def clean_bool(item):
        return "true" if item else "false"

    details = (f"-profile:v {settings.profile} "
               f"-allow_sw {clean_bool(settings.allow_sw)} "
               f"-require_sw {clean_bool(settings.require_sw)} "
               f"-realtime {clean_bool(settings.realtime)} "
               f"-frames_before {clean_bool(settings.frames_before)} "
               f"-frames_after {clean_bool(settings.frames_after)} ")

    if settings.bitrate:
        pass_log_file = fastflix.current_video.work_path / f"pass_log_file_{secrets.token_hex(10)}"
        beginning += f" "

        command_1 = f"{beginning} -b:v {settings.bitrate} {details} -pass 1 -passlogfile \"{pass_log_file}\" {settings.extra if settings.extra_both_passes else ''} -an -f mp4 {null}"
        command_2 = f'{beginning} -b:v {settings.bitrate} {details} -pass 2 -passlogfile "{pass_log_file}" {settings.extra} {ending}'
        return [
            Command(command=command_1,
                    name=f"First pass bitrate",
                    exe="ffmpeg"),
            Command(command=command_2,
                    name=f"Second pass bitrate",
                    exe="ffmpeg"),
        ]
    command_1 = f"{beginning} -q:v {settings.q} {details} {settings.extra} {ending}"

    return [
        Command(command=command_1,
                name=f"Single pass constant quality",
                exe="ffmpeg"),
    ]
Esempio n. 16
0
def build(fastflix: FastFlix):
    settings: x264Settings = fastflix.current_video.video_settings.video_encoder_settings

    beginning, ending = generate_all(fastflix, "libx264")

    beginning += f'{f"-tune {settings.tune}" if settings.tune else ""} ' f"{generate_color_details(fastflix)} "

    if settings.profile and settings.profile != "default":
        beginning += f"-profile {settings.profile} "

    pass_log_file = fastflix.current_video.work_path / f"pass_log_file_{secrets.token_hex(10)}.log"

    if settings.bitrate:
        command_1 = (
            f"{beginning} -pass 1 "
            f'-passlogfile "{pass_log_file}" -b:v {settings.bitrate} -preset {settings.preset} -an -sn -dn -f mp4 {null}'
        )
        command_2 = (
            f'{beginning} -pass 2 -passlogfile "{pass_log_file}" ' f"-b:v {settings.bitrate} -preset {settings.preset}"
        ) + ending
        return [
            Command(
                re.sub("[ ]+", " ", command_1), ["ffmpeg", "output"], False, name="First pass bitrate", exe="ffmpeg"
            ),
            Command(
                re.sub("[ ]+", " ", command_2), ["ffmpeg", "output"], False, name="Second pass bitrate", exe="ffmpeg"
            ),
        ]

    elif settings.crf:
        command = (f"{beginning} -crf {settings.crf} " f"-preset {settings.preset} ") + ending
        return [
            Command(re.sub("[ ]+", " ", command), ["ffmpeg", "output"], False, name="Single pass CRF", exe="ffmpeg")
        ]

    else:
        return []
Esempio n. 17
0
def build(fastflix: FastFlix):
    settings: WebPSettings = fastflix.current_video.video_settings.video_encoder_settings

    beginning, ending = generate_all(fastflix,
                                     "libwebp",
                                     audio=False,
                                     subs=False)

    return [
        Command(
            command=
            f"{beginning}  -lossless {settings.lossless} -compression_level {settings.compression} "
            f"-qscale {settings.qscale} -preset {settings.preset} {settings.extra} {ending}",
            name="WebP",
            exe="ffmpeg",
        ),
    ]
Esempio n. 18
0
def build(
    source,
    video_track,
    ffmpeg,
    temp_dir,
    output_video,
    bitrate=None,
    crf=None,
    subtitle_tracks=(),
    single_pass=False,
    quality="good",
    audio_tracks=(),
    speed=1,
    row_mt=0,
    pix_fmt="yuv420p10le",
    attachments="",
    disable_hdr=False,
    side_data=None,
    **kwargs,
):
    filters = generate_filters(disable_hdr=disable_hdr, **kwargs)
    audio = build_audio(audio_tracks)
    subtitles = build_subtitle(subtitle_tracks)
    ending = generate_ending(audio=audio,
                             subtitles=subtitles,
                             cover=attachments,
                             output_video=output_video,
                             **kwargs)
    beginning = generate_ffmpeg_start(
        source=source,
        ffmpeg=ffmpeg,
        encoder="libvpx-vp9",
        video_track=video_track,
        filters=filters,
        pix_fmt=pix_fmt,
        **kwargs,
    )

    beginning += f'{"-row-mt 1" if row_mt else ""} '

    if not single_pass:
        pass_log_file = Path(
            temp_dir) / f"pass_log_file_{secrets.token_hex(10)}.log"
        beginning += f'-passlogfile "{pass_log_file}" '

    if not disable_hdr and pix_fmt == "yuv420p10le":

        if side_data and side_data.get("color_primaries") == "bt2020":
            beginning += "-color_primaries bt2020 -color_trc smpte2084 -colorspace bt2020nc"

    beginning = re.sub("[ ]+", " ", beginning)

    if bitrate:
        command_1 = f"{beginning} -b:v {bitrate} -quality good -pass 1 -an -f webm {null}"
        command_2 = f"{beginning} -b:v {bitrate} -quality {quality} -speed {speed} -pass 2" + ending

    elif crf:
        command_1 = f"{beginning} -b:v 0 -crf {crf} -quality good -pass 1 -an -f webm {null}"
        command_2 = (
            f"{beginning} -b:v 0 -crf {crf} -quality {quality} -speed {speed} "
            f'{"-pass 2" if not single_pass else ""}') + ending

    else:
        return []

    if crf and single_pass:
        return [
            Command(command_2, ["ffmpeg", "output"],
                    False,
                    name="Single pass CRF",
                    exe="ffmpeg")
        ]
    pass_type = "bitrate" if bitrate else "CRF"
    return [
        Command(command_1, ["ffmpeg", "output"],
                False,
                name=f"First pass {pass_type}",
                exe="ffmpeg"),
        Command(command_2, ["ffmpeg", "output"],
                False,
                name=f"Second pass {pass_type} ",
                exe="ffmpeg"),
    ]
Esempio n. 19
0
def build(
    source,
    video_track,
    ffmpeg,
    temp_dir,
    output_video,
    streams,
    stream_track,
    bitrate=None,
    crf=None,
    audio_tracks=(),
    subtitle_tracks=(),
    disable_hdr=False,
    side_data=None,
    row_mt=None,
    cpu_used="1",
    tile_columns="-1",
    tile_rows="-1",
    attachments="",
    pix_fmt="yuv420p10le",
    usage="good",
    **kwargs,
):
    audio = build_audio(audio_tracks)
    subtitles, burn_in_track = build_subtitle(subtitle_tracks)
    filters = generate_filters(video_track=video_track, disable_hdr=disable_hdr, burn_in_track=burn_in_track, **kwargs)
    ending = generate_ending(audio=audio, subtitles=subtitles, cover=attachments, output_video=output_video, **kwargs)
    beginning = generate_ffmpeg_start(
        source=source,
        ffmpeg=ffmpeg,
        encoder="libaom-av1",
        video_track=video_track,
        filters=filters,
        pix_fmt=pix_fmt,
        **kwargs,
    )

    beginning += (
        "-strict experimental "
        f"-cpu-used {cpu_used} "
        f"-tile-rows {tile_rows} "
        f"-tile-columns {tile_columns} "
        f"-usage {usage} "
    )

    if row_mt is not None:
        beginning += f"-row-mt {row_mt} "

    if not disable_hdr and pix_fmt in ("yuv420p10le", "yuv420p12le"):

        if streams.video[stream_track].get("color_primaries") == "bt2020" or (
            side_data and side_data.get("color_primaries") == "bt2020"
        ):
            beginning += "-color_primaries bt2020 -color_trc smpte2084 -colorspace bt2020nc"

    beginning = re.sub("[ ]+", " ", beginning)

    if bitrate:
        pass_log_file = Path(temp_dir) / f"pass_log_file_{secrets.token_hex(10)}.log"
        command_1 = f'{beginning} -passlogfile "{pass_log_file}" -b:v {bitrate} -pass 1 -an -f matroska {null}'
        command_2 = f'{beginning} -passlogfile "{pass_log_file}" -b:v {bitrate} -pass 2' + ending
        return [
            Command(command_1, ["ffmpeg", "output"], False, name="First Pass bitrate"),
            Command(command_2, ["ffmpeg", "output"], False, name="Second Pass bitrate"),
        ]
    elif crf:
        command_1 = f"{beginning} -b:v 0 -crf {crf}" + ending
        return [Command(command_1, ["ffmpeg", "output"], False, name="Single Pass CRF")]
Esempio n. 20
0
def build(
    source,
    video_track,
    ffmpeg,
    temp_dir,
    output_video,
    bitrate=None,
    crf=None,
    preset="fast",
    audio_tracks=(),
    subtitle_tracks=(),
    disable_hdr=False,
    side_data=None,
    pix_fmt="yuv420p",
    tune=None,
    profile="default",
    attachments="",
    **kwargs,
):
    filters = generate_filters(disable_hdr=disable_hdr, **kwargs)
    audio = build_audio(audio_tracks)
    subtitles = build_subtitle(subtitle_tracks)
    ending = generate_ending(audio=audio,
                             subtitles=subtitles,
                             cover=attachments,
                             output_video=output_video,
                             **kwargs)

    if not side_data:
        side_data = Box(default_box=True)

    beginning = generate_ffmpeg_start(
        source=source,
        ffmpeg=ffmpeg,
        encoder="libx264",
        video_track=video_track,
        filters=filters,
        pix_fmt=pix_fmt,
        **kwargs,
    )

    beginning += f'{f"-tune {tune}" if tune else ""} '

    if profile and profile != "default":
        beginning += f"-profile {profile} "

    if not disable_hdr and pix_fmt == "yuv420p10le":

        if side_data and side_data.get("color_primaries") == "bt2020":
            beginning += "-color_primaries bt2020 -color_trc smpte2084 -colorspace bt2020nc"

    if side_data.cll:
        pass

    extra_data = "-map_chapters 0 "  # -map_metadata 0 # safe to do for rotation?
    pass_log_file = Path(
        temp_dir) / f"pass_log_file_{secrets.token_hex(10)}.log"

    if bitrate:
        command_1 = (
            f"{beginning} -pass 1 "
            f'-passlogfile "{pass_log_file}" -b:v {bitrate} -preset {preset} -an -sn -dn -f mp4 {null}'
        )
        command_2 = (f'{beginning} -pass 2 -passlogfile "{pass_log_file}" '
                     f"-b:v {bitrate} -preset {preset} {extra_data}") + ending
        return [
            Command(re.sub("[ ]+", " ", command_1), ["ffmpeg", "output"],
                    False,
                    name="First pass bitrate",
                    exe="ffmpeg"),
            Command(re.sub("[ ]+", " ", command_2), ["ffmpeg", "output"],
                    False,
                    name="Second pass bitrate",
                    exe="ffmpeg"),
        ]

    elif crf:
        command = (f"{beginning} -crf {crf} "
                   f"-preset {preset} {extra_data}") + ending
        return [
            Command(re.sub("[ ]+", " ", command), ["ffmpeg", "output"],
                    False,
                    name="Single pass CRF",
                    exe="ffmpeg")
        ]

    else:
        return []
Esempio n. 21
0
def build(
    source,
    video_track,
    ffmpeg,
    temp_dir,
    output_video,
    streams,
    stream_track,
    bitrate=None,
    crf=None,
    preset="fast",
    audio_tracks=(),
    subtitle_tracks=(),
    disable_hdr=False,
    side_data=None,
    x265_params=None,
    intra_encoding=False,
    pix_fmt="yuv420p10le",
    tune=None,
    profile="default",
    attachments="",
    hdr10=False,
    hdr10_opt=False,
    repeat_headers=False,
    hdr10plus_metadata="",
    aq_mode=2,
    **kwargs,
):
    audio = build_audio(audio_tracks)
    subtitles, burn_in_track = build_subtitle(subtitle_tracks)
    filters = generate_filters(video_track=video_track, disable_hdr=disable_hdr, burn_in_track=burn_in_track, **kwargs)
    ending = generate_ending(audio=audio, subtitles=subtitles, cover=attachments, output_video=output_video, **kwargs)

    if not side_data:
        side_data = Box(default_box=True)

    beginning = generate_ffmpeg_start(
        source=source,
        ffmpeg=ffmpeg,
        encoder="libx265",
        video_track=video_track,
        filters=filters,
        pix_fmt=pix_fmt,
        **kwargs,
    )

    beginning += f'{f"-tune {tune}" if tune else ""} '

    if profile and profile != "default":
        beginning += f"-profile {profile} "

    if not x265_params:
        x265_params = []

    x265_params.append(f"aq-mode={aq_mode}")
    x265_params.append(f"repeat-headers={'1' if repeat_headers else '0'}")

    if not disable_hdr and pix_fmt in ("yuv420p10le", "yuv420p12le"):
        x265_params.append(f"hdr10_opt={'1' if hdr10_opt else '0'}")

        if streams.video[stream_track].get("color_primaries") == "bt2020" or (
            side_data and side_data.get("color_primaries") == "bt2020"
        ):
            x265_params.extend(
                [
                    "colorprim=bt2020",
                    "transfer=smpte2084",
                    "colormatrix=bt2020nc",
                ]
            )

        if side_data.master_display:
            hdr10 = True
            x265_params.append(
                "master-display="
                f"G{side_data.master_display.green}"
                f"B{side_data.master_display.blue}"
                f"R{side_data.master_display.red}"
                f"WP{side_data.master_display.white}"
                f"L{side_data.master_display.luminance}"
            )

        if side_data.cll:
            hdr10 = True
            x265_params.append(f"max-cll={side_data.cll}")

        x265_params.append(f"hdr10={'1' if hdr10 else '0'}")

    if hdr10plus_metadata:
        x265_params.append(f"dhdr10-info='{hdr10plus_metadata}'")

    if intra_encoding:
        x265_params.append("keyint=1")

    if side_data.cll:
        pass

    pass_log_file = Path(temp_dir) / f"pass_log_file_{secrets.token_hex(10)}.log"

    def get_x265_params(params=()):
        if not isinstance(params, (list, tuple)):
            params = [params]
        all_params = x265_params + list(params)
        return '-x265-params "{}" '.format(":".join(all_params)) if all_params else ""

    if bitrate:
        command_1 = (
            f'{beginning} {get_x265_params(["pass=1", "no-slow-firstpass=1"])} '
            f'-passlogfile "{pass_log_file}" -b:v {bitrate} -preset {preset} -an -sn -dn -f mp4 {null}'
        )
        command_2 = (
            f'{beginning} {get_x265_params(["pass=2"])} -passlogfile "{pass_log_file}" '
            f"-b:v {bitrate} -preset {preset} "
        ) + ending
        return [
            Command(
                re.sub("[ ]+", " ", command_1), ["ffmpeg", "output"], False, name="First pass bitrate", exe="ffmpeg"
            ),
            Command(
                re.sub("[ ]+", " ", command_2), ["ffmpeg", "output"], False, name="Second pass bitrate", exe="ffmpeg"
            ),
        ]

    elif crf:
        command = (f"{beginning} {get_x265_params()}  -crf {crf} " f"-preset {preset} ") + ending
        return [
            Command(re.sub("[ ]+", " ", command), ["ffmpeg", "output"], False, name="Single pass CRF", exe="ffmpeg")
        ]

    else:
        return []
Esempio n. 22
0
def build(fastflix: FastFlix):
    video: Video = fastflix.current_video
    settings: VCEEncCSettings = fastflix.current_video.video_settings.video_encoder_settings

    master_display = None
    if fastflix.current_video.master_display:
        master_display = (
            f'--master-display "G{fastflix.current_video.master_display.green}'
            f"B{fastflix.current_video.master_display.blue}"
            f"R{fastflix.current_video.master_display.red}"
            f"WP{fastflix.current_video.master_display.white}"
            f'L{fastflix.current_video.master_display.luminance}"'
        )

    max_cll = None
    if fastflix.current_video.cll:
        max_cll = f'--max-cll "{fastflix.current_video.cll}"'

    dhdr = None
    if settings.hdr10plus_metadata:
        dhdr = f'--dhdr10-info "{settings.hdr10plus_metadata}"'

    trim = ""
    try:
        if "/" in video.frame_rate:
            over, under = [int(x) for x in video.frame_rate.split("/")]
            rate = over / under
        else:
            rate = float(video.frame_rate)
    except Exception:
        logger.exception("Could not get framerate of this movie!")
    else:
        if video.video_settings.end_time:
            end_frame = int(video.video_settings.end_time * rate)
            start_frame = 0
            if video.video_settings.start_time:
                start_frame = int(video.video_settings.start_time * rate)
            trim = f"--trim {start_frame}:{end_frame}"
        elif video.video_settings.start_time:
            trim = f"--seek {video.video_settings.start_time}"

    if (video.frame_rate != video.average_frame_rate) and trim:
        logger.warning("Cannot use 'trim' when working with variable frame rate videos")
        trim = ""

    transform = ""
    if video.video_settings.vertical_flip or video.video_settings.horizontal_flip:
        transform = f"--vpp-transform flip_x={'true' if video.video_settings.horizontal_flip else 'false'},flip_y={'true' if video.video_settings.vertical_flip else 'false'}"

    remove_hdr = ""
    if video.video_settings.remove_hdr:
        remove_type = (
            video.video_settings.tone_map
            if video.video_settings.tone_map in ("mobius", "hable", "reinhard")
            else "mobius"
        )
        remove_hdr = f"--vpp-colorspace hdr2sdr={remove_type}" if video.video_settings.remove_hdr else ""

    crop = ""
    if video.video_settings.crop:
        crop = f"--crop {video.video_settings.crop.left},{video.video_settings.crop.top},{video.video_settings.crop.right},{video.video_settings.crop.bottom}"

    vbv = ""
    if video.video_settings.maxrate:
        vbv = f"--max-bitrate {video.video_settings.maxrate} --vbv-bufsize {video.video_settings.bufsize}"

    try:
        stream_id = int(video.current_video_stream["id"], 16)
    except Exception:
        if len(video.streams.video) > 1:
            logger.warning("Could not get stream ID from source, the proper video track may not be selected!")
        stream_id = None

    vsync_setting = "cfr" if video.frame_rate == video.average_frame_rate else "vfr"
    if video.video_settings.vsync == "cfr":
        vsync_setting = "forcecfr"
    elif video.video_settings.vsync == "vfr":
        vsync_setting = "vfr"

    command = [
        f'"{clean_file_string(fastflix.config.vceencc)}"',
        ("--avhw" if settings.decoder == "Hardware" else "--avsw"),
        "-i",
        f'"{clean_file_string(video.source)}"',
        (f"--video-streamid {stream_id}" if stream_id else ""),
        trim,
        (f"--vpp-rotate {video.video_settings.rotate * 90}" if video.video_settings.rotate else ""),
        transform,
        (f'--output-res {video.video_settings.scale.replace(":", "x")}' if video.video_settings.scale else ""),
        crop,
        (
            f"--video-metadata clear --metadata clear"
            if video.video_settings.remove_metadata
            else "--video-metadata copy  --metadata copy"
        ),
        (f'--video-metadata title="{video.video_settings.video_title}"' if video.video_settings.video_title else ""),
        ("--chapter-copy" if video.video_settings.copy_chapters else ""),
        "-c",
        "hevc",
        (f"--vbr {settings.bitrate.rstrip('k')}" if settings.bitrate else f"--cqp {settings.cqp}"),
        vbv,
        (f"--qp-min {settings.min_q}" if settings.min_q and settings.bitrate else ""),
        (f"--qp-max {settings.max_q}" if settings.max_q and settings.bitrate else ""),
        (f"--ref {settings.ref}" if settings.ref else ""),
        "--preset",
        settings.preset,
        "--tier",
        settings.tier,
        "--level",
        (settings.level or "auto"),
        "--colormatrix",
        (video.video_settings.color_space or "auto"),
        "--transfer",
        (video.video_settings.color_transfer or "auto"),
        "--colorprim",
        (video.video_settings.color_primaries or "auto"),
        (master_display if master_display else ""),
        (max_cll if max_cll else ""),
        (dhdr if dhdr else ""),
        "--output-depth",
        ("10" if video.current_video_stream.bit_depth > 8 and not video.video_settings.remove_hdr else "8"),
        "--motion-est",
        settings.mv_precision,
        ("--vbaq" if settings.vbaq else ""),
        ("--pe" if settings.pre_encode else ""),
        ("--pa" if settings.pre_analysis else ""),
        "--chromaloc",
        "auto",
        "--colorrange",
        "auto",
        f"--avsync {vsync_setting}",
        (f"--interlace {video.interlaced}" if video.interlaced and video.interlaced != "False" else ""),
        ("--vpp-nnedi" if video.video_settings.deinterlace else ""),
        (f"--vpp-colorspace hdr2sdr=mobius" if video.video_settings.remove_hdr else ""),
        remove_hdr,
        "--psnr --ssim" if settings.metrics else "",
        build_audio(video.video_settings.audio_tracks, video.streams.audio),
        build_subtitle(video.video_settings.subtitle_tracks, video.streams.subtitle),
        settings.extra,
        "-o",
        f'"{clean_file_string(video.video_settings.output_path)}"',
    ]

    return [Command(command=" ".join(x for x in command if x), name="NVEncC Encode", exe="NVEncE")]
Esempio n. 23
0
def build(fastflix: FastFlix):
    video: Video = fastflix.current_video
    settings: NVEncCAVCSettings = fastflix.current_video.video_settings.video_encoder_settings

    trim = ""
    try:
        if "/" in video.frame_rate:
            over, under = [int(x) for x in video.frame_rate.split("/")]
            rate = over / under
        else:
            rate = float(video.frame_rate)
    except Exception:
        logger.exception("Could not get framerate of this movie!")
    else:
        if video.video_settings.end_time:
            end_frame = int(video.video_settings.end_time * rate)
            start_frame = 0
            if video.video_settings.start_time:
                start_frame = int(video.video_settings.start_time * rate)
            trim = f"--trim {start_frame}:{end_frame}"
        elif video.video_settings.start_time:
            trim = f"--seek {video.video_settings.start_time}"

    if (video.frame_rate != video.average_frame_rate) and trim:
        logger.warning("Cannot use 'trim' when working with variable frame rate videos")
        trim = ""

    transform = ""
    if video.video_settings.vertical_flip or video.video_settings.horizontal_flip:
        transform = f"--vpp-transform flip_x={'true' if video.video_settings.horizontal_flip else 'false'},flip_y={'true' if video.video_settings.vertical_flip else 'false'}"

    remove_hdr = ""
    if video.video_settings.remove_hdr:
        remove_type = (
            video.video_settings.tone_map
            if video.video_settings.tone_map in ("mobius", "hable", "reinhard")
            else "mobius"
        )
        remove_hdr = f"--vpp-colorspace hdr2sdr={remove_type}" if video.video_settings.remove_hdr else ""

    crop = ""
    if video.video_settings.crop:
        crop = f"--crop {video.video_settings.crop.left},{video.video_settings.crop.top},{video.video_settings.crop.right},{video.video_settings.crop.bottom}"

    vbv = ""
    if video.video_settings.maxrate:
        vbv = f"--max-bitrate {video.video_settings.maxrate} --vbv-bufsize {video.video_settings.bufsize}"

    init_q = settings.init_q_i
    if settings.init_q_i and settings.init_q_p and settings.init_q_b:
        init_q = f"{settings.init_q_i}:{settings.init_q_p}:{settings.init_q_b}"

    min_q = settings.min_q_i
    if settings.min_q_i and settings.min_q_p and settings.min_q_b:
        min_q = f"{settings.min_q_i}:{settings.min_q_p}:{settings.min_q_b}"

    max_q = settings.max_q_i
    if settings.max_q_i and settings.max_q_p and settings.max_q_b:
        max_q = f"{settings.max_q_i}:{settings.max_q_p}:{settings.max_q_b}"

    try:
        stream_id = int(video.current_video_stream["id"], 16)
    except Exception:
        if len(video.streams.video) > 1:
            logger.warning("Could not get stream ID from source, the proper video track may not be selected!")
        stream_id = None

    aq = "--no-aq"
    if settings.aq.lower() == "spatial":
        aq = f"--aq --aq-strength {settings.aq_strength}"
    elif settings.aq.lower() == "temporal":
        aq = f"--aq-temporal --aq-strength {settings.aq_strength}"

    vsync_setting = "cfr" if video.frame_rate == video.average_frame_rate else "vfr"
    if video.video_settings.vsync == "cfr":
        vsync_setting = "forcecfr"
    elif video.video_settings.vsync == "vfr":
        vsync_setting = "vfr"

    command = [
        f'"{clean_file_string(fastflix.config.nvencc)}"',
        "-i",
        f'"{clean_file_string(video.source)}"',
        (f"--video-streamid {stream_id}" if stream_id else ""),
        trim,
        (f"--vpp-rotate {video.video_settings.rotate * 90}" if video.video_settings.rotate else ""),
        transform,
        (f'--output-res {video.video_settings.scale.replace(":", "x")}' if video.video_settings.scale else ""),
        crop,
        (
            f"--video-metadata clear --metadata clear"
            if video.video_settings.remove_metadata
            else "--video-metadata copy  --metadata copy"
        ),
        (f'--video-metadata title="{video.video_settings.video_title}"' if video.video_settings.video_title else ""),
        ("--chapter-copy" if video.video_settings.copy_chapters else ""),
        "-c",
        "avc",
        (f"--vbr {settings.bitrate.rstrip('k')}" if settings.bitrate else f"--cqp {settings.cqp}"),
        vbv,
        (f"--vbr-quality {settings.vbr_target}" if settings.vbr_target is not None and settings.bitrate else ""),
        (f"--qp-init {init_q}" if init_q and settings.bitrate else ""),
        (f"--qp-min {min_q}" if min_q and settings.bitrate else ""),
        (f"--qp-max {max_q}" if max_q and settings.bitrate else ""),
        (f"--bframes {settings.b_frames}" if settings.b_frames else ""),
        (f"--ref {settings.ref}" if settings.ref else ""),
        f"--bref-mode {settings.b_ref_mode}",
        "--preset",
        settings.preset,
        (f"--lookahead {settings.lookahead}" if settings.lookahead else ""),
        aq,
        "--level",
        (settings.level or "auto"),
        "--colormatrix",
        (video.video_settings.color_space or "auto"),
        "--transfer",
        (video.video_settings.color_transfer or "auto"),
        "--colorprim",
        (video.video_settings.color_primaries or "auto"),
        "--multipass",
        settings.multipass,
        "--mv-precision",
        settings.mv_precision,
        "--chromaloc",
        "auto",
        "--colorrange",
        "auto",
        f"--avsync {vsync_setting}",
        (f"--interlace {video.interlaced}" if video.interlaced and video.interlaced != "False" else ""),
        ("--vpp-yadif" if video.video_settings.deinterlace else ""),
        (f"--vpp-colorspace hdr2sdr=mobius" if video.video_settings.remove_hdr else ""),
        remove_hdr,
        "--psnr --ssim" if settings.metrics else "",
        build_audio(video.video_settings.audio_tracks, video.streams.audio),
        build_subtitle(video.video_settings.subtitle_tracks, video.streams.subtitle),
        settings.extra,
        "-o",
        f'"{clean_file_string(video.video_settings.output_path)}"',
    ]

    return [Command(command=" ".join(x for x in command if x), name="NVEncC Encode", exe="NVEncE")]
Esempio n. 24
0
def build(
    source,
    video_track,
    ffmpeg,
    temp_dir,
    output_video,
    streams,
    stream_track,
    tiles=0,
    tile_columns=0,
    tile_rows=0,
    speed=7,
    qp=-1,
    pix_fmt="yuv420p10le",
    bitrate=None,
    audio_tracks=(),
    subtitle_tracks=(),
    disable_hdr=False,
    side_data=None,
    single_pass=False,
    attachments="",
    **kwargs,
):
    audio = build_audio(audio_tracks)
    subtitles, burn_in_track = build_subtitle(subtitle_tracks)
    filters = generate_filters(video_track=video_track,
                               disable_hdr=disable_hdr,
                               burn_in_track=burn_in_track,
                               **kwargs)
    ending = generate_ending(audio=audio,
                             subtitles=subtitles,
                             cover=attachments,
                             output_video=output_video,
                             **kwargs)

    beginning = generate_ffmpeg_start(
        source=source,
        ffmpeg=ffmpeg,
        encoder="librav1e",
        video_track=video_track,
        filters=filters,
        pix_fmt=pix_fmt,
        **kwargs,
    )

    beginning += ("-strict experimental "
                  f"-speed {speed} "
                  f"-tile-columns {tile_columns} "
                  f"-tile-rows {tile_rows} "
                  f"-tiles {tiles} ")

    if not single_pass:
        pass_log_file = Path(
            temp_dir) / f"pass_log_file_{secrets.token_hex(10)}.log"
        beginning += f'-passlogfile "{pass_log_file}" '

    if not disable_hdr and pix_fmt in ("yuv420p10le", "yuv420p12le"):

        if streams.video[stream_track].get("color_primaries") == "bt2020" or (
                side_data and side_data.get("color_primaries") == "bt2020"):
            beginning += "-color_primaries bt2020 -color_trc smpte2084 -colorspace bt2020nc"

        # Currently unsupported https://github.com/xiph/rav1e/issues/2554
        #         rav1e_options = []
        # if side_data.master_display:
        #     rav1e_options.append(
        #         "mastering-display="
        #         f"G{side_data.master_display.green}"
        #         f"B{side_data.master_display.blue}"
        #         f"R{side_data.master_display.red}"
        #         f"WP{side_data.master_display.white}"
        #         f"L{side_data.master_display.luminance}"
        #     )
        #
        # if side_data.cll:
        #     rav1e_options.append(f"content-light={side_data.cll}")
        # if rav1e_options:
        #     opts = ":".join(rav1e_options)
        #     beginning += f'-rav1e-params "{opts}"'

    beginning = re.sub("[ ]+", " ", beginning)

    pass_type = "bitrate" if bitrate else "QP"

    if not bitrate:
        command_1 = f"{beginning} -qp {qp}" + ending
        return [
            Command(command_1, ["ffmpeg", "output"],
                    False,
                    name=f"{pass_type}",
                    exe="ffmpeg")
        ]

    if single_pass:
        command_1 = f'{beginning} -b:v {bitrate} {audio} {subtitles} {attachments} "{output_video}"'
        return [
            Command(command_1, ["ffmpeg", "output"],
                    False,
                    name=f"{pass_type}",
                    exe="ffmpeg")
        ]
    else:
        command_1 = f"{beginning} -b:v {bitrate} -pass 1 -an -f matroska {null}"
        command_2 = f"{beginning} -b:v {bitrate} -pass 2" + ending
        return [
            Command(command_1, ["ffmpeg", "output"],
                    False,
                    name=f"First pass {pass_type}",
                    exe="ffmpeg"),
            Command(command_2, ["ffmpeg", "output"],
                    False,
                    name=f"Second pass {pass_type} ",
                    exe="ffmpeg"),
        ]
Esempio n. 25
0
def build(fastflix: FastFlix):
    settings: SVTAV1Settings = fastflix.current_video.video_settings.video_encoder_settings
    beginning, ending = generate_all(fastflix, "libsvtav1")

    beginning += (
        f"-strict experimental "
        f"-preset {settings.speed} "
        f"-tile_columns {settings.tile_columns} "
        f"-tile_rows {settings.tile_rows} "
        f"-tier {settings.tier} "
        f"-sc_detection {'true' if settings.scene_detection else 'false'} "
        f"{generate_color_details(fastflix)} ")

    svtav1_params = settings.svtav1_params.copy()

    if not fastflix.current_video.video_settings.remove_hdr:

        if (fastflix.current_video.video_settings.color_primaries == "bt2020"
                or fastflix.current_video.color_primaries == "bt2020"):
            svtav1_params.append(f"color-primaries=9")

        if (fastflix.current_video.video_settings.color_transfer == "smpte2084"
                or fastflix.current_video.color_transfer == "smpte2084"):
            svtav1_params.append(f"transfer-characteristics=16")

        if (fastflix.current_video.video_settings.color_space and "bt2020"
                in fastflix.current_video.video_settings.color_space) or (
                    fastflix.current_video.color_space
                    and "bt2020" in fastflix.current_video.color_space):
            svtav1_params.append(f"matrix-coefficients=9")

        enable_hdr = False
        if settings.pix_fmt in ("yuv420p10le", "yuv420p12le"):

            def convert_me(two_numbers, conversion_rate=50_000) -> str:
                num_one, num_two = map(int, two_numbers.strip("()").split(","))
                return f"{num_one / conversion_rate:0.4f},{num_two / conversion_rate:0.4f}"

            if fastflix.current_video.master_display:
                svtav1_params.append(
                    "mastering-display="
                    f"G({convert_me(fastflix.current_video.master_display.green)})"
                    f"B({convert_me(fastflix.current_video.master_display.blue)})"
                    f"R({convert_me(fastflix.current_video.master_display.red)})"
                    f"WP({convert_me(fastflix.current_video.master_display.white)})"
                    f"L({convert_me(fastflix.current_video.master_display.luminance, 10_000)})"
                )
                enable_hdr = True

            if fastflix.current_video.cll:
                svtav1_params.append(
                    f"content-light={fastflix.current_video.cll}")
                enable_hdr = True

            if enable_hdr:
                svtav1_params.append("enable-hdr=1")

    if svtav1_params:
        beginning += f" -svtav1-params \"{':'.join(svtav1_params)}\" "

    if not settings.single_pass:
        pass_log_file = fastflix.current_video.work_path / f"pass_log_file_{secrets.token_hex(10)}"
        beginning += f'-passlogfile "{pass_log_file}" '

    pass_type = "bitrate" if settings.bitrate else "QP"

    if settings.single_pass:
        if settings.bitrate:
            command_1 = f"{beginning} -b:v {settings.bitrate} {settings.extra} {ending}"

        elif settings.qp is not None:
            command_1 = f"{beginning} -{settings.qp_mode} {settings.qp} {settings.extra} {ending}"
        else:
            return []
        return [Command(command=command_1, name=f"{pass_type}", exe="ffmpeg")]
    else:
        if settings.bitrate:
            command_1 = f"{beginning} -b:v {settings.bitrate} -pass 1 {settings.extra if settings.extra_both_passes else ''} -an -f matroska {null}"
            command_2 = f"{beginning} -b:v {settings.bitrate} -pass 2 {settings.extra} {ending}"

        elif settings.qp is not None:
            command_1 = f"{beginning} -qp {settings.qp} -pass 1 {settings.extra if settings.extra_both_passes else ''} -an -f matroska {null}"
            command_2 = f"{beginning} -qp {settings.qp} -pass 2 {settings.extra} {ending}"
        else:
            return []
        return [
            Command(command=command_1,
                    name=f"First pass {pass_type}",
                    exe="ffmpeg"),
            Command(command=command_2,
                    name=f"Second pass {pass_type} ",
                    exe="ffmpeg"),
        ]
def build(fastflix: FastFlix):
    settings: x265Settings = fastflix.current_video.video_settings.video_encoder_settings

    beginning, ending = generate_all(fastflix, "libx265")

    if settings.tune and settings.tune != "default":
        beginning += f"-tune:v {settings.tune} "

    if settings.profile and settings.profile != "default":
        beginning += f"-profile:v {settings.profile} "

    x265_params = settings.x265_params.copy() or []

    x265_params.append(f"aq-mode={settings.aq_mode}")
    x265_params.append(
        f"repeat-headers={'1' if settings.repeat_headers else '0'}")
    x265_params.append(
        f"{'' if settings.intra_smoothing else 'no-'}strong-intra-smoothing=1")
    x265_params.append(f"bframes={settings.bframes}")
    x265_params.append(f"b-adapt={settings.b_adapt}")
    x265_params.append(f"frame-threads={settings.frame_threads}")

    if not fastflix.current_video.video_settings.remove_hdr:

        if fastflix.current_video.video_settings.color_primaries:
            x265_params.append(
                f"colorprim={fastflix.current_video.video_settings.color_primaries}"
            )
        elif fastflix.current_video.color_primaries:
            if fastflix.current_video.color_primaries in x265_valid_color_primaries:
                x265_params.append(
                    f"colorprim={fastflix.current_video.color_primaries}")
            elif fastflix.current_video.color_primaries in color_primaries_mapping:
                x265_params.append(
                    f"colorprim={color_primaries_mapping[fastflix.current_video.color_primaries]}"
                )

        if fastflix.current_video.video_settings.color_transfer:
            x265_params.append(
                f"transfer={fastflix.current_video.video_settings.color_transfer}"
            )
        elif fastflix.current_video.color_transfer:
            if fastflix.current_video.color_transfer in x265_valid_color_transfers:
                x265_params.append(
                    f"transfer={fastflix.current_video.color_transfer}")
            elif fastflix.current_video.color_transfer in color_transfer_mapping:
                x265_params.append(
                    f"transfer={color_transfer_mapping[fastflix.current_video.color_transfer]}"
                )

        if fastflix.current_video.video_settings.color_space:
            x265_params.append(
                f"colormatrix={fastflix.current_video.video_settings.color_space}"
            )
        elif fastflix.current_video.color_space:
            if fastflix.current_video.color_space in x265_valid_color_matrix:
                x265_params.append(
                    f"colormatrix={fastflix.current_video.color_space}")
            elif fastflix.current_video.color_space in color_matrix_mapping:
                x265_params.append(
                    f"colormatrix={color_matrix_mapping[fastflix.current_video.color_space]}"
                )

        if settings.pix_fmt in ("yuv420p10le", "yuv420p12le"):
            x265_params.append(
                f"hdr10_opt={'1' if settings.hdr10_opt else '0'}")

            if fastflix.current_video.master_display:
                settings.hdr10 = True
                x265_params.append(
                    "master-display="
                    f"G{fastflix.current_video.master_display.green}"
                    f"B{fastflix.current_video.master_display.blue}"
                    f"R{fastflix.current_video.master_display.red}"
                    f"WP{fastflix.current_video.master_display.white}"
                    f"L{fastflix.current_video.master_display.luminance}")

            if fastflix.current_video.cll:
                settings.hdr10 = True
                x265_params.append(f"max-cll={fastflix.current_video.cll}")

            x265_params.append(f"hdr10={'1' if settings.hdr10 else '0'}")

        current_chroma_loc = fastflix.current_video.current_video_stream.get(
            "chroma_location")
        if current_chroma_loc in chromaloc_mapping:
            x265_params.append(
                f"chromaloc={chromaloc_mapping[current_chroma_loc]}")

    if settings.hdr10plus_metadata:
        x265_params.append(f"dhdr10-info='{settings.hdr10plus_metadata}'")

    if settings.intra_encoding:
        x265_params.append("keyint=1")

    if settings.intra_refresh:
        x265_params.append("intra-refresh=1")

    if settings.lossless:
        x265_params.append("lossless=1")

    if fastflix.current_video.video_settings.maxrate:
        x265_params.append(
            f"vbv-maxrate={fastflix.current_video.video_settings.maxrate}")
        x265_params.append(
            f"vbv-bufsize={fastflix.current_video.video_settings.bufsize}")

    if fastflix.current_video.cll:
        pass

    pass_log_file = fastflix.current_video.work_path / f"pass_log_file_{secrets.token_hex(10)}"

    def get_x265_params(params=()):
        if not isinstance(params, (list, tuple)):
            params = [params]
        all_params = x265_params + list(params)
        return '-x265-params "{}" '.format(
            ":".join(all_params)) if all_params else ""

    if settings.bitrate:
        command_1 = (
            f'{beginning} {get_x265_params(["pass=1", "no-slow-firstpass=1"])} '
            f'-passlogfile "{pass_log_file}" -b:v {settings.bitrate} -preset:v {settings.preset} {settings.extra if settings.extra_both_passes else ""} '
            f" -an -sn -dn -f mp4 {null}")
        command_2 = (
            f'{beginning} {get_x265_params(["pass=2"])} -passlogfile "{pass_log_file}" '
            f"-b:v {settings.bitrate} -preset:v {settings.preset} {settings.extra} {ending}"
        )
        return [
            Command(command=command_1, name="First pass bitrate",
                    exe="ffmpeg"),
            Command(command=command_2,
                    name="Second pass bitrate",
                    exe="ffmpeg"),
        ]

    elif settings.crf:
        command = (f"{beginning} {get_x265_params()}  -crf:v {settings.crf} "
                   f"-preset:v {settings.preset} {settings.extra} {ending}")
        return [Command(command=command, name="Single pass CRF", exe="ffmpeg")]

    else:
        return []
Esempio n. 27
0
def build(
    source,
    video_track,
    ffmpeg,
    temp_dir,
    output_video,
    streams,
    stream_track,
    tier="main",
    tile_columns=0,
    tile_rows=0,
    speed=7,
    qp=25,
    sc_detection=0,
    disable_hdr=False,
    pix_fmt="yuv420p10le",
    bitrate=None,
    audio_tracks=(),
    subtitle_tracks=(),
    side_data=None,
    single_pass=False,
    attachments="",
    **kwargs,
):
    audio = build_audio(audio_tracks)
    subtitles, burn_in_track = build_subtitle(subtitle_tracks)
    filters = generate_filters(video_track=video_track,
                               disable_hdr=disable_hdr,
                               burn_in_track=burn_in_track,
                               **kwargs)
    ending = generate_ending(audio=audio,
                             subtitles=subtitles,
                             cover=attachments,
                             output_video=output_video,
                             **kwargs)

    beginning = generate_ffmpeg_start(
        source=source,
        ffmpeg=ffmpeg,
        encoder="libsvtav1",
        video_track=video_track,
        filters=filters,
        pix_fmt=pix_fmt,
        **kwargs,
    )

    beginning += (f"-strict experimental "
                  f"-preset {speed} "
                  f"-tile_columns {tile_columns} "
                  f"-tile_rows {tile_rows} "
                  f"-tier {tier} "
                  f"-sc_detection {sc_detection} ")

    if not single_pass:
        pass_log_file = Path(
            temp_dir) / f"pass_log_file_{secrets.token_hex(10)}.log"
        beginning += f'-passlogfile "{pass_log_file}" '

    if not disable_hdr and pix_fmt in ("yuv420p10le", "yuv420p12le"):

        if streams.video[stream_track].get("color_primaries") == "bt2020" or (
                side_data and side_data.get("color_primaries") == "bt2020"):
            beginning += "-color_primaries bt2020 -color_trc smpte2084 -colorspace bt2020nc"

    beginning = re.sub("[ ]+", " ", beginning)

    pass_type = "bitrate" if bitrate else "QP"

    if single_pass:
        if bitrate:
            command_1 = f"{beginning} -b:v {bitrate} -rc 1" + ending

        elif qp is not None:
            command_1 = f"{beginning} -qp {qp} -rc 0" + ending
        else:
            return []
        return [
            Command(command_1, ["ffmpeg", "output"],
                    False,
                    name=f"{pass_type}",
                    exe="ffmpeg")
        ]
    else:
        if bitrate:
            command_1 = f"{beginning} -b:v {bitrate} -rc 1 -pass 1 -an -f matroska {null}"
            command_2 = f"{beginning} -b:v {bitrate} -rc 1 -pass 2" + ending

        elif qp is not None:
            command_1 = f"{beginning} -qp {qp} -rc 0 -pass 1 -an -f matroska {null}"
            command_2 = f"{beginning} -qp {qp} -rc 0 -pass 2" + ending
        else:
            return []
        return [
            Command(command_1, ["ffmpeg", "output"],
                    False,
                    name=f"First pass {pass_type}",
                    exe="ffmpeg"),
            Command(command_2, ["ffmpeg", "output"],
                    False,
                    name=f"Second pass {pass_type} ",
                    exe="ffmpeg"),
        ]