fix: audio extract honored a silent length clamp — 30s near the end became 3s
_on_extract_audio clamped the duration to (timeline_duration - cursor), so with
the playhead within the requested length of the end (or any under-reported
duration) a 30s request was silently truncated to whatever remained — the user
asked for 30s and got 3s with no indication why.
Drop the clamp: pass the requested length straight to ffmpeg, which stops
cleanly at end-of-file if the source is shorter. Then ffprobe the result and,
when it comes up short, say so ("Saved 3.0s — source ended before 30.0s
requested") instead of silently shrinking. When there's room, 30s now yields
exactly 30s.
Adds core.ffmpeg.probe_duration(). Verified end-to-end: a fitting request
returns the exact length; a genuine near-end request returns the available
audio (rc=0) and is reported as truncated.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
@@ -186,6 +186,21 @@ _AUDIO_CODEC_BY_EXT: dict[str, list[str]] = {
|
||||
}
|
||||
|
||||
|
||||
def probe_duration(path: str) -> float | None:
|
||||
"""Return the media duration in seconds via ffprobe, or None on failure."""
|
||||
try:
|
||||
r = subprocess.run(
|
||||
[_bin("ffprobe"), "-v", "error", "-show_entries", "format=duration",
|
||||
"-of", "default=nw=1:nk=1", path],
|
||||
capture_output=True, text=True, timeout=30,
|
||||
)
|
||||
if r.returncode == 0 and r.stdout.strip():
|
||||
return float(r.stdout.strip())
|
||||
except Exception:
|
||||
pass
|
||||
return None
|
||||
|
||||
|
||||
def build_audio_clip_command(input_path: str, start: float, duration: float,
|
||||
out_path: str) -> list[str]:
|
||||
"""ffmpeg command to extract exactly *duration* seconds of audio starting
|
||||
|
||||
Reference in New Issue
Block a user