feat: add stream-copy exports
This commit is contained in:
+29
-3
@@ -82,11 +82,12 @@ def build_ffmpeg_command(
|
||||
target_fps: float | None = None,
|
||||
snap32: bool = False,
|
||||
frames: int | None = None,
|
||||
stream_copy: bool = False,
|
||||
) -> list[str]:
|
||||
# -ss before -i: fast input-seeking. Safe here because we always re-encode,
|
||||
# so there is no keyframe-alignment issue from pre-input seek.
|
||||
# Re-encoded output is not constrained to source keyframes. Stream-copy
|
||||
# output remains keyframe-limited even though it uses the same fast seek.
|
||||
# Image sequences always use libwebp, so skip HW encoder setup.
|
||||
use_hw_vaapi = (encoder == "h264_vaapi" and not image_sequence
|
||||
use_hw_vaapi = (not stream_copy and encoder == "h264_vaapi" and not image_sequence
|
||||
and sys.platform == "linux")
|
||||
cmd = [_bin("ffmpeg"), "-y"]
|
||||
|
||||
@@ -96,6 +97,31 @@ def build_ffmpeg_command(
|
||||
cmd += ["-hwaccel", "vaapi", "-hwaccel_output_format", "vaapi",
|
||||
"-vaapi_device", vaapi_dev]
|
||||
|
||||
if stream_copy:
|
||||
incompatible = (
|
||||
image_sequence or short_side is not None or portrait_ratio is not None
|
||||
or target_fps is not None or snap32 or frames is not None
|
||||
)
|
||||
if incompatible:
|
||||
raise ValueError("Stream copy cannot be combined with image or video transforms")
|
||||
# Matroska/WebM input seeking can retain a whole cluster of keyframe
|
||||
# pre-roll and then count -t from its shifted timestamps. Keeping source
|
||||
# timestamps avoids that extension. MOV/MP4 needs normal timestamp
|
||||
# rebasing instead, so this workaround is deliberately container-only.
|
||||
ext = os.path.splitext(output_path)[1].lower()
|
||||
timestamp_args = (
|
||||
["-copyts", "-start_at_zero"] if ext in (".mkv", ".webm") else []
|
||||
)
|
||||
return cmd + [
|
||||
"-threads", "0",
|
||||
"-ss", str(start),
|
||||
"-i", input_path,
|
||||
"-t", str(duration),
|
||||
*timestamp_args,
|
||||
"-c", "copy",
|
||||
output_path,
|
||||
]
|
||||
|
||||
cmd += [
|
||||
"-threads", "0",
|
||||
"-ss", str(start),
|
||||
|
||||
+5
-2
@@ -25,14 +25,17 @@ def _log(*args) -> None:
|
||||
|
||||
|
||||
def build_export_path(folder: str, basename: str, counter: int,
|
||||
sub: int | None = None, tag: str | None = None) -> str:
|
||||
sub: int | None = None, tag: str | None = None,
|
||||
extension: str = ".mp4") -> str:
|
||||
"""Build clip output path. *folder* should be the vid folder (e.g. .../mp4/vid_001)."""
|
||||
name = f"{basename}_{counter:03d}"
|
||||
if tag is not None:
|
||||
name = f"{name}_{tag}"
|
||||
if sub is not None:
|
||||
name = f"{name}_{sub}"
|
||||
return os.path.join(folder, name + ".mp4")
|
||||
if extension and not extension.startswith("."):
|
||||
extension = "." + extension
|
||||
return os.path.join(folder, name + extension)
|
||||
|
||||
|
||||
def build_sequence_dir(folder: str, basename: str, counter: int,
|
||||
|
||||
Reference in New Issue
Block a user