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", ), ]
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"), ]
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 []
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"), ]
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 []
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")]
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"), ]