Exemplo n.º 1
0
def generate_ffmpeg_start(
    source,
    ffmpeg,
    encoder,
    selected_track,
    start_time=0,
    end_time=None,
    pix_fmt="yuv420p10le",
    filters=None,
    max_muxing_queue_size="default",
    fast_seek=True,
    video_title="",
    maxrate=None,
    bufsize=None,
    source_fps: Union[str, None] = None,
    vsync: Union[str, None] = None,
    concat: bool = False,
    enable_opencl: bool = False,
    remove_hdr: bool = True,
    **_,
) -> str:
    time_settings = f'{f"-ss {start_time}" if start_time else ""} {f"-to {end_time}" if end_time else ""} '
    time_one = time_settings if fast_seek else ""
    time_two = time_settings if not fast_seek else ""
    incoming_fps = f"-r {source_fps}" if source_fps else ""
    vsync_text = f"-vsync {vsync}" if vsync else ""
    title = f'-metadata title="{video_title}"' if video_title else ""
    source = clean_file_string(source)
    ffmpeg = clean_file_string(ffmpeg)

    return " ".join([
        f'"{ffmpeg}"',
        "-y",
        time_one,
        incoming_fps,
        f"{'-f concat -safe 0' if concat else ''}",
        f'-i "{source}"',
        time_two,
        title,
        f"{f'-max_muxing_queue_size {max_muxing_queue_size}' if max_muxing_queue_size != 'default' else ''}",
        f'{f"-map 0:{selected_track}" if not filters else ""}',
        vsync_text,
        f'{filters if filters else ""}',
        f"-c:v {encoder}",
        f"-pix_fmt {pix_fmt}",
        f"{f'-maxrate:v {maxrate}k' if maxrate else ''}",
        f"{f'-bufsize:v {bufsize}k' if bufsize else ''}",
        ("-init_hw_device opencl=ocl -filter_hw_device ocl "
         if enable_opencl and remove_hdr else ""),
        " ",  # Leave space after commands
    ])
Exemplo n.º 2
0
def build_attachments(attachments: List[AttachmentTrack]) -> str:

    commands = []
    for attachment in attachments:
        if attachment.attachment_type == "cover":
            mime_type, ext_type = image_type(attachment.file_path)
            clean_path = clean_file_string(attachment.file_path)
            commands.append(
                f' -attach "{clean_path}" -metadata:s:{attachment.outdex} mimetype="{mime_type}" '
                f'-metadata:s:{attachment.outdex}  filename="{attachment.filename}.{ext_type}" '
            )
    return " ".join(commands)
Exemplo n.º 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"),
    ]
    def run(self):
        if not self.app.fastflix.current_video.hdr10_plus:
            self.main.thread_logging_signal.emit(
                "ERROR:No tracks have HDR10+ data to extract")
            return

        output = self.app.fastflix.current_video.work_path / "metadata.json"

        track = self.app.fastflix.current_video.video_settings.selected_track
        if track not in self.app.fastflix.current_video.hdr10_plus:
            self.main.thread_logging_signal.emit(
                "WARNING:Selected video track not detected to have HDR10+ data, selecting first track that does"
            )
            track = self.app.fastflix.current_video.hdr10_plus[0]

        self.main.thread_logging_signal.emit(
            f'INFO:{t("Extracting HDR10+ metadata")} to {output}')

        self.ffmpeg_signal.emit("Extracting HDR10+ metadata")

        hdr10_parser_version_output = check_output(
            [str(self.app.fastflix.config.hdr10plus_parser), "--version"],
            encoding="utf-8")
        _, version_string = hdr10_parser_version_output.rsplit(sep=" ",
                                                               maxsplit=1)
        hdr10_parser_version = LooseVersion(version_string)
        self.main.thread_logging_signal.emit(
            f"Using HDR10 parser version {hdr10_parser_version}")

        ffmpeg_command = [
            str(self.app.fastflix.config.ffmpeg),
            "-y",
            "-i",
            clean_file_string(self.app.fastflix.current_video.source),
            "-map",
            f"0:{track}",
            "-c:v",
            "copy",
            "-vbsf",
            "hevc_mp4toannexb",
            "-f",
            "hevc",
            "-",
        ]

        hdr10_parser_command = [
            str(self.app.fastflix.config.hdr10plus_parser), "-o",
            clean_file_string(output), "-"
        ]
        if hdr10_parser_version >= LooseVersion("1.0.0"):
            hdr10_parser_command.insert(1, "extract")

        self.main.thread_logging_signal.emit(
            f"Running command: {' '.join(ffmpeg_command)} | {' '.join(hdr10_parser_command)}"
        )

        process = Popen(
            ffmpeg_command,
            stdout=PIPE,
            stderr=open(
                self.app.fastflix.current_video.work_path /
                "hdr10extract_out.txt", "wb"),
            # stdin=PIPE,  # FFmpeg can try to read stdin and wrecks havoc
        )

        process_two = Popen(
            hdr10_parser_command,
            stdout=PIPE,
            stderr=PIPE,
            stdin=process.stdout,
            encoding="utf-8",
            cwd=str(self.app.fastflix.current_video.work_path),
        )

        with open(self.app.fastflix.current_video.work_path /
                  "hdr10extract_out.txt",
                  "r",
                  encoding="utf-8") as f:
            while True:
                if process.poll() is not None or process_two.poll(
                ) is not None:
                    break
                if line := f.readline().rstrip():
                    if line.startswith("frame"):
                        self.ffmpeg_signal.emit(line)