feat: Merge sequence — add (file/selection), reorder, remove

This commit is contained in:
2026-07-02 16:04:01 +02:00
parent de7da3cad6
commit b8aa1606d8
2 changed files with 110 additions and 5 deletions
+63 -5
View File
@@ -4544,6 +4544,7 @@ class MainWindow(QMainWindow):
self._merge_list.setSelectionMode(
QAbstractItemView.SelectionMode.SingleSelection)
self._merge_list.setToolTip("Clips to merge, top to bottom")
self._merge_temps: set[str] = set()
self._spn_crossfade = QDoubleSpinBox()
self._spn_crossfade.setRange(0.0, 10.0)
self._spn_crossfade.setDecimals(2)
@@ -6579,17 +6580,74 @@ class MainWindow(QMainWindow):
start = self._cursor
self._timeline.set_audio_region(start, start + self._spn_audio_len.value())
def _on_merge_add_selection(self) -> None:
pass # implemented in M3
def _merge_add_paths(self, paths: list[str]) -> None:
QApplication.setOverrideCursor(Qt.CursorShape.WaitCursor)
try:
for p in paths:
ap = os.path.abspath(p)
dur = probe_duration(ap)
text = (f"{os.path.basename(ap)} ({dur:.2f}s)"
if dur is not None else os.path.basename(ap))
item = QListWidgetItem(text)
item.setData(Qt.ItemDataRole.UserRole, ap)
item.setData(Qt.ItemDataRole.UserRole + 1, dur)
self._merge_list.addItem(item)
finally:
QApplication.restoreOverrideCursor()
def _on_merge_add_file(self) -> None:
pass # implemented in M3
default_dir = (self._settings.value("audio_extract_dir", "")
or os.path.dirname(self._file_path or ""))
paths, _sel = QFileDialog.getOpenFileNames(
self, "Add audio file(s)", default_dir,
"Audio (*.wav *.mp3 *.flac *.m4a *.ogg *.opus *.aac);;All files (*)")
if paths:
self._merge_add_paths(paths)
def _on_merge_add_selection(self) -> None:
if not self._file_path:
self._show_status("Load a video first", 3000)
return
import tempfile
start = self._cursor
dur = self._spn_audio_len.value()
fd, tmp = tempfile.mkstemp(suffix=".wav", prefix="8cut_merge_")
os.close(fd)
self._show_status("Rendering selection…")
QApplication.setOverrideCursor(Qt.CursorShape.WaitCursor)
try:
cmd = build_audio_clip_command(self._file_path, start, dur, tmp,
filters=self._current_edit_filters() or None)
proc = subprocess.run(cmd, capture_output=True, timeout=120)
except Exception:
proc = None
finally:
QApplication.restoreOverrideCursor()
if proc is not None and proc.returncode == 0 and os.path.exists(tmp):
self._merge_temps.add(tmp)
self._merge_add_paths([tmp])
else:
try:
os.remove(tmp)
except OSError:
pass
self._show_status("Could not render selection", 3000)
def _merge_move(self, delta: int) -> None:
pass # implemented in M3
row = self._merge_list.currentRow()
if row < 0:
return
new = row + delta
if new < 0 or new >= self._merge_list.count():
return
item = self._merge_list.takeItem(row)
self._merge_list.insertItem(new, item)
self._merge_list.setCurrentRow(new)
def _merge_remove_selected(self) -> None:
pass # implemented in M3
row = self._merge_list.currentRow()
if row >= 0:
self._merge_list.takeItem(row)
def _on_merge_preview(self) -> None:
pass # implemented in M4