most solid commit
This commit is contained in:
@@ -237,6 +237,28 @@ class ChtWindow(Adw.ApplicationWindow):
|
||||
self._update_scrub_bar_manifest()
|
||||
self._populate_model_dropdown()
|
||||
|
||||
def _reload_waveform(self, mgr):
|
||||
"""Recompute waveform from existing segments in background."""
|
||||
segments = mgr.recording_segments
|
||||
if not segments:
|
||||
return
|
||||
from cht.stream import ffmpeg as ff
|
||||
|
||||
def _compute():
|
||||
audio_dir = mgr.audio_dir
|
||||
audio_dir.mkdir(parents=True, exist_ok=True)
|
||||
full_wav = audio_dir / "full.wav"
|
||||
try:
|
||||
ff.extract_audio_chunk(segments[0], full_wav)
|
||||
self._waveform_engine.compute_full(full_wav)
|
||||
peaks = self._waveform_engine.peaks
|
||||
bucket_dur = self._waveform_engine.bucket_duration
|
||||
GLib.idle_add(self._waveform_widget.set_peaks, peaks.copy(), bucket_dur)
|
||||
except Exception as e:
|
||||
log.error("Waveform reload failed: %s", e)
|
||||
|
||||
Thread(target=_compute, daemon=True, name="waveform_reload").start()
|
||||
|
||||
# -- Streaming --
|
||||
|
||||
def _start_stream(self, session_id=None):
|
||||
@@ -256,6 +278,7 @@ class ChtWindow(Adw.ApplicationWindow):
|
||||
if session_id:
|
||||
self._load_existing_frames()
|
||||
self._load_existing_transcript()
|
||||
self._reload_waveform(mgr)
|
||||
|
||||
self.set_title(f"{APP_NAME} — {mgr.session_id}")
|
||||
log.info("Waiting for sender...")
|
||||
@@ -406,6 +429,14 @@ class ChtWindow(Adw.ApplicationWindow):
|
||||
|
||||
Thread(target=_capture, daemon=True, name="scrub_capture").start()
|
||||
|
||||
def _manual_segment_cut(self):
|
||||
"""Ctrl+R: manually cut recording into a new segment."""
|
||||
if not self._lifecycle.is_streaming:
|
||||
return
|
||||
log.info("Manual segment cut requested")
|
||||
self._lifecycle._rotate_segment()
|
||||
self._agent_output.append("Segment cut.\n")
|
||||
|
||||
def _stop_stream(self, reload_session=False):
|
||||
log.info("Stopping stream...")
|
||||
mgr = self._lifecycle.stream_mgr
|
||||
@@ -523,6 +554,14 @@ class ChtWindow(Adw.ApplicationWindow):
|
||||
kb.bind(KEY_DELETE, lambda **_: self._agent_output.clear())
|
||||
kb.attach(self)
|
||||
|
||||
# Ctrl+R: manual segment cut
|
||||
ctrl_r = Gtk.ShortcutController()
|
||||
ctrl_r.add_shortcut(Gtk.Shortcut(
|
||||
trigger=Gtk.ShortcutTrigger.parse_string("<Ctrl>r"),
|
||||
action=Gtk.CallbackAction.new(lambda *_: self._manual_segment_cut()),
|
||||
))
|
||||
self.add_controller(ctrl_r)
|
||||
|
||||
# -- Agent actions --
|
||||
|
||||
def _build_selection_message(self, verb: str) -> str | None:
|
||||
@@ -635,7 +674,7 @@ class ChtWindow(Adw.ApplicationWindow):
|
||||
self._known_frames.add(fid)
|
||||
try:
|
||||
pixbuf = GdkPixbuf.Pixbuf.new_from_file_at_scale(str(entry["path"]), 256, 144, True)
|
||||
auto = not self._transcript_panel.has_selection
|
||||
auto = self._timeline.state.live and not self._transcript_panel.has_selection
|
||||
self._frames_panel.add_item(fid, pixbuf, entry["timestamp"], auto_select=auto)
|
||||
self._timeline_controls.scrub_bar.add_frame(entry["timestamp"], str(entry["path"]))
|
||||
except Exception as e:
|
||||
|
||||
Reference in New Issue
Block a user