feat: add stream-copy exports

This commit is contained in:
2026-08-16 09:29:47 +02:00
parent 8f354254b2
commit d5d74066b0
6 changed files with 264 additions and 47 deletions
+29 -3
View File
@@ -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),