Esempio n. 1
0
def generate_all(fastflix: FastFlix,
                 encoder: str,
                 audio: bool = True,
                 subs: bool = True,
                 disable_filters: bool = False) -> Tuple[str, str]:
    settings = fastflix.current_video.video_settings.video_encoder_settings

    audio = build_audio(
        fastflix.current_video.video_settings.audio_tracks) if audio else ""

    subtitles, burn_in_track, burn_in_type = "", None, None
    if subs:
        subtitles, burn_in_track, burn_in_type = build_subtitle(
            fastflix.current_video.video_settings.subtitle_tracks)
        if burn_in_type == "text":
            for i, x in enumerate(fastflix.current_video.streams["subtitle"]):
                if x["index"] == burn_in_track:
                    burn_in_track = i
                    break

    attachments = build_attachments(
        fastflix.current_video.video_settings.attachment_tracks)

    filters = None
    if not disable_filters:
        filters = generate_filters(
            source=fastflix.current_video.source,
            burn_in_subtitle_track=burn_in_track,
            burn_in_subtitle_type=burn_in_type,
            enable_opencl=fastflix.opencl_support,
            **fastflix.current_video.video_settings.dict(),
        )

    ending = generate_ending(
        audio=audio,
        subtitles=subtitles,
        cover=attachments,
        output_video=fastflix.current_video.video_settings.output_path,
        **fastflix.current_video.video_settings.dict(),
    )

    beginning = generate_ffmpeg_start(
        source=fastflix.current_video.source,
        ffmpeg=fastflix.config.ffmpeg,
        encoder=encoder,
        filters=filters,
        concat=fastflix.current_video.concat,
        enable_opencl=fastflix.opencl_support,
        **fastflix.current_video.video_settings.dict(),
        **settings.dict(),
    )

    return beginning, ending
Esempio n. 2
0
def generate_all(
    fastflix: FastFlix, encoder: str, audio: bool = True, subs: bool = True, disable_filters: bool = False
) -> Tuple[str, str]:
    settings = fastflix.current_video.video_settings.video_encoder_settings

    audio = build_audio(fastflix.current_video.video_settings.audio_tracks) if audio else ""

    subtitles, burn_in_track = "", None
    if subs:
        subtitles, burn_in_track = build_subtitle(fastflix.current_video.video_settings.subtitle_tracks)

    attachments = build_attachments(fastflix.current_video.video_settings.attachment_tracks)

    filters = None
    if not disable_filters:
        filters = generate_filters(
            burn_in_subtitle_track=burn_in_track, **asdict(fastflix.current_video.video_settings)
        )

    ending = generate_ending(
        audio=audio,
        subtitles=subtitles,
        cover=attachments,
        output_video=fastflix.current_video.video_settings.output_path,
        extra=fastflix.current_video.video_settings.video_encoder_settings.extra,
        **asdict(fastflix.current_video.video_settings),
    )

    beginning = generate_ffmpeg_start(
        source=fastflix.current_video.source,
        ffmpeg=fastflix.config.ffmpeg,
        encoder=encoder,
        filters=filters,
        **asdict(fastflix.current_video.video_settings),
        **asdict(settings),
    )

    return beginning, ending
Esempio n. 3
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. 4
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. 5
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. 6
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. 7
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. 8
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"),
        ]