コード例 #1
0
ファイル: command_builder.py プロジェクト: pzprovi/FastFlix
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"),
    ]
コード例 #2
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",
        ),
    ]
コード例 #3
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"),
    ]
コード例 #4
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"),
    ]
コード例 #5
0
ファイル: large_preview.py プロジェクト: cdgriffith/FastFlix
    def generate_image(self):
        settings = self.main.app.fastflix.current_video.video_settings.dict()

        if (self.main.app.fastflix.current_video.video_settings.
                video_encoder_settings.pix_fmt == "yuv420p10le" and self.main.
                app.fastflix.current_video.color_space.startswith("bt2020")):
            settings["remove_hdr"] = True

        filters = helpers.generate_filters(
            enable_opencl=self.main.app.fastflix.opencl_support,
            start_filters="select=eq(pict_type\\,I)"
            if self.main.widgets.thumb_key.isChecked() else None,
            **settings,
        )

        output = self.main.app.fastflix.config.work_path / f"large_preview_{secrets.token_hex(16)}.tiff"

        thumb_command = generate_thumbnail_command(
            config=self.main.app.fastflix.config,
            source=self.main.source_material,
            output=output,
            filters=filters,
            start_time=self.main.preview_place,
            enable_opencl=self.main.app.fastflix.opencl_support,
            input_track=self.main.app.fastflix.current_video.video_settings.
            selected_track,
        )
        if thumb_command == self.last_command:
            return

        logger.info(f"Generating large thumbnail: {thumb_command}")

        thumb_run = run(thumb_command, shell=True, stderr=PIPE, stdout=PIPE)
        if thumb_run.returncode > 0:
            logger.warning(
                f"Could not generate large thumbnail: {thumb_run.stdout} |----| {thumb_run.stderr}"
            )
            return

        self.current_image = QtGui.QPixmap(str(output))
        if self.last_path:
            try:
                self.last_path.unlink(missing_ok=True)
            except OSError:
                logger.warning(
                    f"Could not delete last large preview {self.last_path}")
        self.last_path = output
        self.label.setPixmap(self.current_image)
        self.resize(self.current_image.width(), self.current_image.height())
コード例 #6
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"),
    ]
コード例 #7
0
    def generate_thumbnail(self, settings):
        if not self.input_video or self.loading_video:
            return

        if settings.pix_fmt == "yuv420p10le" and self.pix_fmt in ("yuv420p10le", "yuv420p12le"):
            settings.disable_hdr = True
        filters = helpers.generate_filters(**settings)

        thumb_command = self.flix.generate_thumbnail_command(
            source=self.input_video,
            output=self.thumb_file,
            video_track=self.streams["video"][self.video_track]["index"],
            filters=filters,
            start_time=settings.start_time,
        )
        try:
            self.thumb_file.unlink()
        except OSError:
            pass
        worker = ThumbnailCreator(self, thumb_command)
        worker.start()
コード例 #8
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"),
    ]
コード例 #9
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 []
コード例 #10
0
ファイル: command_builder.py プロジェクト: pzprovi/FastFlix
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"),
        ]
コード例 #11
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 []
コード例 #12
0
ファイル: command_builder.py プロジェクト: pzprovi/FastFlix
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")]
コード例 #13
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"),
        ]