feat: Extract audio area — exact-length audio slice from the playhead, save-as
A dedicated "♪ Extract audio" button on the transport row grabs an exact length of audio (set via the adjacent length box, from the playhead) and opens a Save As dialog. Output format follows the chosen extension — WAV (pcm_s16le), MP3 (libmp3lame), FLAC, m4a/aac, ogg/opus — re-encoding as needed; unknown extensions let ffmpeg pick from the container. - core.ffmpeg.build_audio_clip_command(input, start, duration, out_path): fast-seek + exact -t duration + -vn, codec by extension. Verified end-to-end (wav/mp3/flac all land at exactly the requested duration). - Timeline shows the audio area as a distinct teal dashed band spanning [cursor, cursor+length], updated live as the playhead or length changes, so you see exactly what will be extracted. - Length + last save dir persist in QSettings; button enabled once a file loads. Tests: 3 core (codec-by-extension, exact length, case-insensitive) + 2 GUI (controls exist, band tracks cursor/length). Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
@@ -243,3 +243,28 @@ def test_subprofile_button_visibility_exact_match(win):
|
||||
win._apply_subcat_visibility()
|
||||
assert btns["blowjob"].isHidden()
|
||||
assert not btns["clap"].isHidden()
|
||||
|
||||
|
||||
def test_extract_audio_controls_exist(win):
|
||||
from PyQt6.QtWidgets import QPushButton, QDoubleSpinBox
|
||||
assert isinstance(win._btn_extract_audio, QPushButton)
|
||||
assert isinstance(win._spn_audio_len, QDoubleSpinBox)
|
||||
# Disabled until a file is loaded.
|
||||
assert not win._btn_extract_audio.isEnabled()
|
||||
|
||||
|
||||
def test_audio_region_tracks_cursor_and_length(win):
|
||||
# The teal audio band spans [cursor, cursor + length]; changing the length
|
||||
# or moving the cursor moves the band. Fake a loaded file so the guard in
|
||||
# _update_audio_region passes.
|
||||
win._file_path = "/x/video.mp4"
|
||||
win._cursor = 10.0
|
||||
win._spn_audio_len.setValue(4.0) # fires _on_audio_len_changed
|
||||
assert win._timeline._audio_region == (10.0, 14.0)
|
||||
win._cursor = 20.0
|
||||
win._update_audio_region()
|
||||
assert win._timeline._audio_region == (20.0, 24.0)
|
||||
# No file -> band cleared.
|
||||
win._file_path = ""
|
||||
win._update_audio_region()
|
||||
assert win._timeline._audio_region is None
|
||||
|
||||
Reference in New Issue
Block a user