talks-reducer 0.6.0__py3-none-any.whl → 0.6.1__py3-none-any.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -2,4 +2,4 @@
2
2
 
3
3
  __all__ = ["__version__"]
4
4
 
5
- __version__ = "0.6.0"
5
+ __version__ = "0.6.1"
talks_reducer/cli.py CHANGED
@@ -9,20 +9,16 @@ import subprocess
9
9
  import sys
10
10
  import time
11
11
  from importlib import import_module
12
- from importlib.metadata import PackageNotFoundError, version
13
12
  from pathlib import Path
14
13
  from typing import Dict, List, Optional, Sequence, Tuple
15
14
 
16
15
  from . import audio
17
16
 
18
- try:
19
- from .__about__ import __version__ as _about_version
20
- except Exception: # pragma: no cover - fallback if metadata file missing
21
- _about_version = ""
22
17
  from .ffmpeg import FFmpegNotFoundError
23
18
  from .models import ProcessingOptions, default_temp_folder
24
19
  from .pipeline import speed_up_video
25
20
  from .progress import TqdmProgressReporter
21
+ from .version_utils import resolve_version
26
22
 
27
23
 
28
24
  def _build_parser() -> argparse.ArgumentParser:
@@ -33,7 +29,7 @@ def _build_parser() -> argparse.ArgumentParser:
33
29
  )
34
30
 
35
31
  # Add version argument
36
- pkg_version = _resolve_version()
32
+ pkg_version = resolve_version()
37
33
 
38
34
  parser.add_argument(
39
35
  "--version",
@@ -120,18 +116,6 @@ def _build_parser() -> argparse.ArgumentParser:
120
116
  return parser
121
117
 
122
118
 
123
- def _resolve_version() -> str:
124
- """Determine the package version for CLI reporting."""
125
-
126
- if _about_version:
127
- return _about_version
128
-
129
- try:
130
- return version("talks-reducer")
131
- except (PackageNotFoundError, Exception):
132
- return "unknown"
133
-
134
-
135
119
  def gather_input_files(paths: List[str]) -> List[str]:
136
120
  """Expand provided paths into a flat list of files that contain audio streams."""
137
121
 
talks_reducer/gui.py CHANGED
@@ -13,7 +13,6 @@ import threading
13
13
  import urllib.error
14
14
  import urllib.parse
15
15
  import urllib.request
16
- from importlib.metadata import version
17
16
  from pathlib import Path
18
17
  from typing import (
19
18
  TYPE_CHECKING,
@@ -38,6 +37,7 @@ try:
38
37
  from .models import ProcessingOptions, default_temp_folder
39
38
  from .pipeline import speed_up_video
40
39
  from .progress import ProgressHandle, SignalProgressReporter
40
+ from .version_utils import resolve_version
41
41
  except ImportError: # pragma: no cover - handled at runtime
42
42
  if __package__ not in (None, ""):
43
43
  raise
@@ -53,6 +53,7 @@ except ImportError: # pragma: no cover - handled at runtime
53
53
  from talks_reducer.models import ProcessingOptions, default_temp_folder
54
54
  from talks_reducer.pipeline import speed_up_video
55
55
  from talks_reducer.progress import ProgressHandle, SignalProgressReporter
56
+ from talks_reducer.version_utils import resolve_version
56
57
 
57
58
 
58
59
  def _check_tkinter_available() -> tuple[bool, str]:
@@ -198,7 +199,13 @@ def _ensure_server_tray_running(extra_args: Optional[Sequence[str]] = None) -> N
198
199
  if _TRAY_PROCESS is not None and _TRAY_PROCESS.poll() is None:
199
200
  return
200
201
 
201
- command = [sys.executable, "-m", "talks_reducer.server_tray"]
202
+ package_name = __package__ or "talks_reducer"
203
+
204
+ if getattr(sys, "frozen", False):
205
+ command = [sys.executable, "--server"]
206
+ else:
207
+ command = [sys.executable, "-m", f"{package_name}.server_tray"]
208
+
202
209
  if extra_args:
203
210
  command.extend(extra_args)
204
211
 
@@ -387,11 +394,11 @@ class TalksReducerGUI:
387
394
  else:
388
395
  self.root = tk.Tk()
389
396
 
390
- # Set window title with version
391
- try:
392
- app_version = version("talks-reducer")
397
+ # Set window title with version information
398
+ app_version = resolve_version()
399
+ if app_version and app_version != "unknown":
393
400
  self.root.title(f"Talks Reducer v{app_version}")
394
- except Exception:
401
+ else:
395
402
  self.root.title("Talks Reducer")
396
403
 
397
404
  self._apply_window_icon()
@@ -453,6 +460,7 @@ class TalksReducerGUI:
453
460
  self._basic_defaults: dict[str, float] = {}
454
461
  self._basic_variables: dict[str, tk.DoubleVar] = {}
455
462
  self._slider_updaters: dict[str, Callable[[str], None]] = {}
463
+ self._sliders: list[tk.Scale] = []
456
464
 
457
465
  self._build_layout()
458
466
  self._apply_simple_mode(initial=True)
@@ -473,7 +481,7 @@ class TalksReducerGUI:
473
481
  def ping_worker() -> None:
474
482
  try:
475
483
  if self._ping_server(server_url):
476
- self._set_status("Idle", f"Server {host_label} is reachable")
484
+ self._set_status("Idle", f"Server {host_label} is ready")
477
485
  self._notify(
478
486
  lambda: self._append_log(f"Server {host_label} ready")
479
487
  )
@@ -610,6 +618,7 @@ class TalksReducerGUI:
610
618
  text="Reset to defaults",
611
619
  command=self._reset_basic_defaults,
612
620
  state=self.tk.DISABLED,
621
+ style="Link.TButton",
613
622
  )
614
623
 
615
624
  self.basic_options_frame = self.ttk.Labelframe(
@@ -895,6 +904,7 @@ class TalksReducerGUI:
895
904
  showvalue=False,
896
905
  command=update,
897
906
  length=240,
907
+ highlightthickness=0,
898
908
  )
899
909
  slider.grid(row=row, column=1, sticky="ew", pady=4, padx=(0, 8))
900
910
 
@@ -904,6 +914,7 @@ class TalksReducerGUI:
904
914
  self._basic_defaults[setting_key] = default_value
905
915
  self._basic_variables[setting_key] = variable
906
916
  variable.trace_add("write", lambda *_: self._update_basic_reset_state())
917
+ self._sliders.append(slider)
907
918
 
908
919
  def _update_basic_reset_state(self) -> None:
909
920
  """Enable or disable the reset control based on slider values."""
@@ -1253,11 +1264,33 @@ class TalksReducerGUI:
1253
1264
  "TRadiobutton",
1254
1265
  background=[("active", palette.get("hover", palette["background"]))],
1255
1266
  )
1267
+ self.style.configure(
1268
+ "Link.TButton",
1269
+ background=palette["background"],
1270
+ foreground=palette["accent"],
1271
+ borderwidth=0,
1272
+ relief="flat",
1273
+ highlightthickness=0,
1274
+ padding=2,
1275
+ font=("TkDefaultFont", 8, "underline"),
1276
+ )
1277
+ self.style.map(
1278
+ "Link.TButton",
1279
+ background=[
1280
+ ("active", palette.get("hover", palette["background"])),
1281
+ ("disabled", palette["background"]),
1282
+ ],
1283
+ foreground=[
1284
+ ("active", palette.get("accent", palette["foreground"])),
1285
+ ("disabled", palette["foreground"]),
1286
+ ],
1287
+ )
1256
1288
  self.style.configure(
1257
1289
  "TButton",
1258
1290
  background=palette["surface"],
1259
1291
  foreground=palette["foreground"],
1260
- padding=6,
1292
+ padding=4,
1293
+ font=("TkDefaultFont", 8),
1261
1294
  )
1262
1295
  self.style.map(
1263
1296
  "TButton",
@@ -1323,6 +1356,24 @@ class TalksReducerGUI:
1323
1356
  fg=palette["foreground"],
1324
1357
  highlightthickness=0,
1325
1358
  )
1359
+
1360
+ slider_relief = self.tk.FLAT if mode == "dark" else self.tk.RAISED
1361
+ active_background = (
1362
+ palette.get("accent", palette["surface"])
1363
+ if mode == "dark"
1364
+ else palette.get("hover", palette["surface"])
1365
+ )
1366
+ for slider in getattr(self, "_sliders", []):
1367
+ slider.configure(
1368
+ # background=palette["background"],
1369
+ # foreground=palette["foreground"],
1370
+ troughcolor=palette["surface"],
1371
+ # activebackground=active_background,
1372
+ # highlightbackground=palette["background"],
1373
+ highlightcolor=palette["background"],
1374
+ sliderrelief=slider_relief,
1375
+ bd=0,
1376
+ )
1326
1377
  self.log_text.configure(
1327
1378
  bg=palette["surface"],
1328
1379
  fg=palette["foreground"],
talks_reducer/server.py CHANGED
@@ -19,6 +19,7 @@ from talks_reducer.ffmpeg import FFmpegNotFoundError
19
19
  from talks_reducer.models import ProcessingOptions, ProcessingResult
20
20
  from talks_reducer.pipeline import speed_up_video
21
21
  from talks_reducer.progress import ProgressHandle, SignalProgressReporter
22
+ from talks_reducer.version_utils import resolve_version
22
23
 
23
24
 
24
25
  class _GradioProgressHandle(AbstractContextManager[ProgressHandle]):
@@ -347,10 +348,15 @@ def build_interface() -> gr.Blocks:
347
348
 
348
349
  server_identity = _describe_server_host()
349
350
 
350
- with gr.Blocks(title="Talks Reducer Web UI") as demo:
351
+ app_version = resolve_version()
352
+ version_suffix = (
353
+ f" v{app_version}" if app_version and app_version != "unknown" else ""
354
+ )
355
+
356
+ with gr.Blocks(title=f"Talks Reducer Web UI{version_suffix}") as demo:
351
357
  gr.Markdown(
352
358
  f"""
353
- ## Talks Reducer Web UI
359
+ ## Talks Reducer Web UI{version_suffix}
354
360
  Drop a video into the zone below or click to browse. **Small video** is enabled
355
361
  by default to apply the 720p/128k preset before processing starts—clear it to
356
362
  keep the original resolution.
@@ -21,6 +21,7 @@ from urllib.parse import urlsplit, urlunsplit
21
21
  from PIL import Image
22
22
 
23
23
  from .server import build_interface
24
+ from .version_utils import resolve_version
24
25
 
25
26
  try: # pragma: no cover - import guarded for clearer error message at runtime
26
27
  import pystray
@@ -35,6 +36,7 @@ else:
35
36
 
36
37
 
37
38
  LOGGER = logging.getLogger(__name__)
39
+ APP_VERSION = resolve_version()
38
40
 
39
41
 
40
42
  def _guess_local_url(host: Optional[str], port: int) -> str:
@@ -121,7 +123,10 @@ def _iter_icon_candidates() -> Iterator[Path]:
121
123
  if candidate_root not in expanded_roots:
122
124
  expanded_roots.append(candidate_root)
123
125
 
124
- icon_names = ("icon.png", "icon.ico")
126
+ if sys.platform == "win32":
127
+ icon_names = ("icon.ico", "icon.png")
128
+ else:
129
+ icon_names = ("icon.png", "icon.ico")
125
130
  relative_paths = (
126
131
  Path("docs") / "assets",
127
132
  Path("assets"),
@@ -460,7 +465,12 @@ class _ServerTrayApplication:
460
465
  return
461
466
 
462
467
  icon_image = _load_icon()
468
+ version_suffix = (
469
+ f" v{APP_VERSION}" if APP_VERSION and APP_VERSION != "unknown" else ""
470
+ )
471
+ version_label = f"Talks Reducer{version_suffix}"
463
472
  menu = pystray.Menu(
473
+ pystray.MenuItem(version_label, None, enabled=False),
464
474
  pystray.MenuItem(
465
475
  "Open GUI",
466
476
  self._launch_gui,
@@ -470,7 +480,10 @@ class _ServerTrayApplication:
470
480
  pystray.MenuItem("Quit", self._handle_quit),
471
481
  )
472
482
  self._icon = pystray.Icon(
473
- "talks-reducer", icon_image, "Talks Reducer Server", menu=menu
483
+ "talks-reducer",
484
+ icon_image,
485
+ f"{version_label} Server",
486
+ menu=menu,
474
487
  )
475
488
 
476
489
  if self._tray_mode == "pystray-detached":
@@ -0,0 +1,22 @@
1
+ """Utilities for retrieving the Talks Reducer version across environments."""
2
+
3
+ from __future__ import annotations
4
+
5
+ from importlib.metadata import PackageNotFoundError, version as metadata_version
6
+
7
+ try: # pragma: no cover - defensive fallback when metadata module missing
8
+ from .__about__ import __version__ as _about_version
9
+ except Exception: # pragma: no cover - runtime fallback in frozen apps
10
+ _about_version = ""
11
+
12
+
13
+ def resolve_version(package_name: str = "talks-reducer") -> str:
14
+ """Return the package version, preferring bundled metadata when available."""
15
+
16
+ if _about_version:
17
+ return _about_version
18
+
19
+ try:
20
+ return metadata_version(package_name)
21
+ except (PackageNotFoundError, Exception):
22
+ return "unknown"
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: talks-reducer
3
- Version: 0.6.0
3
+ Version: 0.6.1
4
4
  Summary: CLI for speeding up long-form talks by removing silence
5
5
  Author: Talks Reducer Maintainers
6
6
  License-Expression: MIT
@@ -111,7 +111,8 @@ desktop shortcut without opening the GUI first.
111
111
  Pass `--debug` to print verbose logs about the tray icon lifecycle, and
112
112
  `--tray-mode pystray-detached` to try pystray's alternate detached runner. If
113
113
  the icon backend refuses to appear, fall back to `--tray-mode headless` to keep
114
- the web server running without a tray process. The tray menu includes an **Open GUI**
114
+ the web server running without a tray process. The tray menu highlights the
115
+ running Talks Reducer version and includes an **Open GUI**
115
116
  item (also triggered by double-clicking the icon) that launches the desktop
116
117
  Talks Reducer interface alongside an **Open WebUI** entry that opens the Gradio
117
118
  page in your browser. Close the GUI window to return to the tray without
@@ -125,8 +126,9 @@ browser automatically—pass `--open-browser` if you prefer the web page to
125
126
  launch as soon as the server is ready.
126
127
 
127
128
  This opens a local web page featuring a drag-and-drop upload zone, a **Small video** checkbox that mirrors the CLI preset, a live
128
- progress indicator, and automatic previews of the processed output. Once the job completes you can inspect the resulting compression
129
- ratio and download the rendered video directly from the page.
129
+ progress indicator, and automatic previews of the processed output. The page header and browser tab title include the current
130
+ Talks Reducer version so you can confirm which build the server is running. Once the job completes you can inspect the resulting
131
+ compression ratio and download the rendered video directly from the page.
130
132
 
131
133
  The desktop GUI mirrors this behaviour. Open **Advanced** settings to provide a
132
134
  server URL and click **Discover** to scan your local network for Talks Reducer
@@ -1,21 +1,22 @@
1
- talks_reducer/__about__.py,sha256=T9hVPyc5xZOC-_kFZV6XUTbJQBz0IfVup-zpFmtFjuk,92
1
+ talks_reducer/__about__.py,sha256=KW-viuoc2AcVVTHYXfURFg9xsicuBA_X9n4tgL9p2ag,92
2
2
  talks_reducer/__init__.py,sha256=Kzh1hXaw6Vq3DyTqrnJGOq8pn0P8lvaDcsg1bFUjFKk,208
3
3
  talks_reducer/__main__.py,sha256=azR_vh8HFPLaOnh-L6gUFWsL67I6iHtbeH5rQhsipGY,299
4
4
  talks_reducer/audio.py,sha256=sjHMeY0H9ESG-Gn5BX0wFRBX7sXjWwsgS8u9Vb0bJ88,4396
5
5
  talks_reducer/chunks.py,sha256=IpdZxRFPURSG5wP-OQ_p09CVP8wcKwIFysV29zOTSWI,2959
6
- talks_reducer/cli.py,sha256=6hHPuHzDh-BzZOLzHIAqEKU8VpD0cUnocpisLrOOe8I,16521
6
+ talks_reducer/cli.py,sha256=JH8lvPUyk6jWGcnNRIGJeIh2ZcOvC5CORvj5GLuqq0c,16075
7
7
  talks_reducer/discovery.py,sha256=BJ-iMir65cJMs0u-_EYdknBQT_grvCZaJNOx1xGi2PU,4590
8
8
  talks_reducer/ffmpeg.py,sha256=dsHBOBcr5XCSg0q3xmzLOcibBiEdyrXdEQa-ze5vQsM,12551
9
- talks_reducer/gui.py,sha256=7oYfqsUKGaSCJqJlqWKdNpSZu_14jC8ehMryU6NDmVc,87872
9
+ talks_reducer/gui.py,sha256=mTB4m9LxqqTAaHoNf1QZZ4KfHiSMk0C7SJ5BDhqNR3Q,89777
10
10
  talks_reducer/models.py,sha256=6Q_8rmHLyImXp88D4B7ptTbFaH_xXa_yxs8A2dypz2Y,2004
11
11
  talks_reducer/pipeline.py,sha256=naAP8gli9MahoxVdla2tRn2vdDuBBU5ywWkYfZLkMcE,12211
12
12
  talks_reducer/progress.py,sha256=Mh43M6VWhjjUv9CI22xfD2EJ_7Aq3PCueqefQ9Bd5-o,4565
13
- talks_reducer/server.py,sha256=NZ_xTSSHIc6DY0-UBz7FsGbsA1L7cZifcDbn3RUVUo0,13743
14
- talks_reducer/server_tray.py,sha256=Wmnhu9OujbJKo2gV4anZAElqgD8ME08EaZymN8TLsnc,22923
13
+ talks_reducer/server.py,sha256=IzPe0qkZTs8kqoc9gtGDSWtwN2CTWHVcsYzQah-W3cU,13977
14
+ talks_reducer/server_tray.py,sha256=9jqYfjBpXj7_V_ZlVc7oSDKYRPpG7sOGoxuKvSGEQGM,23373
15
15
  talks_reducer/service_client.py,sha256=JnhQhRxVwrGo9eUlduoZ6f_YYyXvjU7hF8UTNprH7TM,10984
16
- talks_reducer-0.6.0.dist-info/licenses/LICENSE,sha256=jN17mHNR3e84awmH3AbpWBcBDBzPxEH0rcOFoj1s7sQ,1124
17
- talks_reducer-0.6.0.dist-info/METADATA,sha256=6nQdOsM8Z33wuoplFcwrIDMLL0gRzwzLm5u4nVcOw84,8141
18
- talks_reducer-0.6.0.dist-info/WHEEL,sha256=_zCd3N1l69ArxyTb8rzEoP9TpbYXkqRFSNOD5OuxnTs,91
19
- talks_reducer-0.6.0.dist-info/entry_points.txt,sha256=X2pjoh2vWBXXExVWorv1mbA1aTEVP3fyuZH4AixqZK4,208
20
- talks_reducer-0.6.0.dist-info/top_level.txt,sha256=pJWGcy__LR9JIEKH3QJyFmk9XrIsiFtqvuMNxFdIzDU,14
21
- talks_reducer-0.6.0.dist-info/RECORD,,
16
+ talks_reducer/version_utils.py,sha256=TkYrTznVb2JqxFXzVzPd6PEnYP2MH7dxKl1J4-3DjMA,755
17
+ talks_reducer-0.6.1.dist-info/licenses/LICENSE,sha256=jN17mHNR3e84awmH3AbpWBcBDBzPxEH0rcOFoj1s7sQ,1124
18
+ talks_reducer-0.6.1.dist-info/METADATA,sha256=iTbxOTuZMnT2UG5KmwKDpKuy555CtsTSps7KSPAfJc0,8326
19
+ talks_reducer-0.6.1.dist-info/WHEEL,sha256=_zCd3N1l69ArxyTb8rzEoP9TpbYXkqRFSNOD5OuxnTs,91
20
+ talks_reducer-0.6.1.dist-info/entry_points.txt,sha256=X2pjoh2vWBXXExVWorv1mbA1aTEVP3fyuZH4AixqZK4,208
21
+ talks_reducer-0.6.1.dist-info/top_level.txt,sha256=pJWGcy__LR9JIEKH3QJyFmk9XrIsiFtqvuMNxFdIzDU,14
22
+ talks_reducer-0.6.1.dist-info/RECORD,,