talks-reducer 0.6.3__py3-none-any.whl → 0.7.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.
- talks_reducer/__about__.py +1 -1
- talks_reducer/cli.py +9 -3
- talks_reducer/{gui.py → gui/__init__.py} +375 -1192
- talks_reducer/gui/__main__.py +8 -0
- talks_reducer/gui/discovery.py +126 -0
- talks_reducer/gui/layout.py +526 -0
- talks_reducer/gui/preferences.py +113 -0
- talks_reducer/gui/remote.py +356 -0
- talks_reducer/gui/theme.py +269 -0
- talks_reducer/models.py +1 -1
- talks_reducer/pipeline.py +142 -92
- talks_reducer/server.py +52 -4
- talks_reducer/service_client.py +56 -4
- {talks_reducer-0.6.3.dist-info → talks_reducer-0.7.1.dist-info}/METADATA +14 -5
- talks_reducer-0.7.1.dist-info/RECORD +29 -0
- talks_reducer-0.6.3.dist-info/RECORD +0 -23
- {talks_reducer-0.6.3.dist-info → talks_reducer-0.7.1.dist-info}/WHEEL +0 -0
- {talks_reducer-0.6.3.dist-info → talks_reducer-0.7.1.dist-info}/entry_points.txt +0 -0
- {talks_reducer-0.6.3.dist-info → talks_reducer-0.7.1.dist-info}/licenses/LICENSE +0 -0
- {talks_reducer-0.6.3.dist-info → talks_reducer-0.7.1.dist-info}/top_level.txt +0 -0
talks_reducer/service_client.py
CHANGED
@@ -14,6 +14,11 @@ from gradio_client import Client
|
|
14
14
|
from gradio_client import file as gradio_file
|
15
15
|
from gradio_client.client import Status, StatusUpdate
|
16
16
|
|
17
|
+
try:
|
18
|
+
from .pipeline import ProcessingAborted
|
19
|
+
except ImportError: # pragma: no cover - allow running as script
|
20
|
+
from talks_reducer.pipeline import ProcessingAborted
|
21
|
+
|
17
22
|
|
18
23
|
def send_video(
|
19
24
|
input_path: Path,
|
@@ -21,13 +26,21 @@ def send_video(
|
|
21
26
|
server_url: str,
|
22
27
|
small: bool = False,
|
23
28
|
*,
|
29
|
+
silent_threshold: Optional[float] = None,
|
30
|
+
sounded_speed: Optional[float] = None,
|
31
|
+
silent_speed: Optional[float] = None,
|
24
32
|
log_callback: Optional[Callable[[str], None]] = None,
|
25
33
|
stream_updates: bool = False,
|
34
|
+
should_cancel: Optional[Callable[[], bool]] = None,
|
26
35
|
progress_callback: Optional[
|
27
36
|
Callable[[str, Optional[int], Optional[int], str], None]
|
28
37
|
] = None,
|
29
38
|
) -> Tuple[Path, str, str]:
|
30
|
-
"""Upload *input_path* to the Gradio server and download the processed video.
|
39
|
+
"""Upload *input_path* to the Gradio server and download the processed video.
|
40
|
+
|
41
|
+
When *should_cancel* returns ``True`` the remote job is cancelled and a
|
42
|
+
:class:`ProcessingAborted` exception is raised.
|
43
|
+
"""
|
31
44
|
|
32
45
|
if not input_path.exists():
|
33
46
|
raise FileNotFoundError(f"Input file does not exist: {input_path}")
|
@@ -36,9 +49,23 @@ def send_video(
|
|
36
49
|
job = client.submit(
|
37
50
|
gradio_file(str(input_path)),
|
38
51
|
bool(small),
|
52
|
+
silent_threshold,
|
53
|
+
sounded_speed,
|
54
|
+
silent_speed,
|
39
55
|
api_name="/process_video",
|
40
56
|
)
|
41
57
|
|
58
|
+
cancelled = False
|
59
|
+
|
60
|
+
def _cancel_if_requested() -> None:
|
61
|
+
nonlocal cancelled
|
62
|
+
if should_cancel and should_cancel():
|
63
|
+
if not cancelled:
|
64
|
+
with suppress(Exception):
|
65
|
+
job.cancel()
|
66
|
+
cancelled = True
|
67
|
+
raise ProcessingAborted("Remote processing cancelled by user.")
|
68
|
+
|
42
69
|
printed_lines = 0
|
43
70
|
|
44
71
|
def _emit_new_lines(log_text: str) -> None:
|
@@ -54,21 +81,31 @@ def send_video(
|
|
54
81
|
consumed_stream = False
|
55
82
|
|
56
83
|
if stream_updates:
|
84
|
+
stream_kwargs: dict[str, object] = {"progress_callback": progress_callback}
|
85
|
+
if should_cancel is not None:
|
86
|
+
stream_kwargs["cancel_callback"] = _cancel_if_requested
|
57
87
|
consumed_stream = _stream_job_updates(
|
58
88
|
job,
|
59
89
|
_emit_new_lines,
|
60
|
-
|
90
|
+
**stream_kwargs,
|
61
91
|
)
|
62
92
|
|
63
93
|
if not consumed_stream:
|
64
94
|
for output in job:
|
95
|
+
_cancel_if_requested()
|
65
96
|
if not isinstance(output, (list, tuple)) or len(output) != 4:
|
66
97
|
continue
|
67
98
|
log_text_candidate = output[1] or ""
|
68
99
|
if isinstance(log_text_candidate, str):
|
69
100
|
_emit_new_lines(log_text_candidate)
|
70
101
|
|
71
|
-
|
102
|
+
_cancel_if_requested()
|
103
|
+
|
104
|
+
try:
|
105
|
+
prediction = job.result()
|
106
|
+
except Exception:
|
107
|
+
_cancel_if_requested()
|
108
|
+
raise
|
72
109
|
|
73
110
|
try:
|
74
111
|
video_path, log_text, summary, download_path = prediction
|
@@ -86,6 +123,8 @@ def send_video(
|
|
86
123
|
if not download_path:
|
87
124
|
raise RuntimeError("Server did not return a processed file")
|
88
125
|
|
126
|
+
_cancel_if_requested()
|
127
|
+
|
89
128
|
download_source = Path(str(download_path))
|
90
129
|
if output_path is None:
|
91
130
|
destination = Path.cwd() / download_source.name
|
@@ -156,10 +195,13 @@ async def _pump_job_updates(
|
|
156
195
|
progress_callback: Optional[
|
157
196
|
Callable[[str, Optional[int], Optional[int], str], None]
|
158
197
|
],
|
198
|
+
cancel_callback: Optional[Callable[[], None]] = None,
|
159
199
|
) -> None:
|
160
200
|
"""Consume asynchronous updates from *job* and emit logs and progress."""
|
161
201
|
|
162
202
|
async for update in job: # type: ignore[async-for]
|
203
|
+
if cancel_callback:
|
204
|
+
cancel_callback()
|
163
205
|
update_type = getattr(update, "type", "status")
|
164
206
|
if update_type == "output":
|
165
207
|
outputs = getattr(update, "outputs", None) or []
|
@@ -195,11 +237,14 @@ def _poll_job_updates(
|
|
195
237
|
Callable[[str, Optional[int], Optional[int], str], None]
|
196
238
|
],
|
197
239
|
*,
|
240
|
+
cancel_callback: Optional[Callable[[], None]] = None,
|
198
241
|
interval: float = 0.25,
|
199
242
|
) -> None:
|
200
243
|
"""Poll *job* for outputs and status updates when async streaming is unavailable."""
|
201
244
|
|
202
245
|
while True:
|
246
|
+
if cancel_callback:
|
247
|
+
cancel_callback()
|
203
248
|
if job.done():
|
204
249
|
break
|
205
250
|
|
@@ -241,6 +286,7 @@ def _stream_job_updates(
|
|
241
286
|
progress_callback: Optional[
|
242
287
|
Callable[[str, Optional[int], Optional[int], str], None]
|
243
288
|
] = None,
|
289
|
+
cancel_callback: Optional[Callable[[], None]] = None,
|
244
290
|
) -> bool:
|
245
291
|
"""Attempt to stream updates directly from *job*.
|
246
292
|
|
@@ -258,10 +304,16 @@ def _stream_job_updates(
|
|
258
304
|
job,
|
259
305
|
emit_log,
|
260
306
|
progress_callback,
|
307
|
+
cancel_callback,
|
261
308
|
)
|
262
309
|
)
|
263
310
|
except RuntimeError:
|
264
|
-
_poll_job_updates(
|
311
|
+
_poll_job_updates(
|
312
|
+
job,
|
313
|
+
emit_log,
|
314
|
+
progress_callback,
|
315
|
+
cancel_callback=cancel_callback,
|
316
|
+
)
|
265
317
|
|
266
318
|
return True
|
267
319
|
|
@@ -1,6 +1,6 @@
|
|
1
1
|
Metadata-Version: 2.4
|
2
2
|
Name: talks-reducer
|
3
|
-
Version: 0.
|
3
|
+
Version: 0.7.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
|
@@ -26,7 +26,8 @@ Requires-Dist: bump-my-version>=0.5.0; extra == "dev"
|
|
26
26
|
Requires-Dist: pyinstaller>=6.4.0; extra == "dev"
|
27
27
|
Dynamic: license-file
|
28
28
|
|
29
|
-
# Talks Reducer
|
29
|
+
# Talks Reducer
|
30
|
+
|
30
31
|
Talks Reducer shortens long-form presentations by removing silent gaps and optionally re-encoding them to smaller files. The
|
31
32
|
project was renamed from **jumpcutter** to emphasize its focus on conference talks and screencasts.
|
32
33
|
|
@@ -47,10 +48,10 @@ Go to the [releases page](https://github.com/popstas/talks-reducer/releases) and
|
|
47
48
|
- **Windows** — `talks-reducer-windows-0.4.0.zip`
|
48
49
|
- **macOS** — `talks-reducer.app.zip`
|
49
50
|
|
50
|
-
> **Troubleshooting:** If launching the bundle (or running `python talks_reducer
|
51
|
+
> **Troubleshooting:** If launching the bundle (or running `python -m talks_reducer.gui`) prints `macOS 26 (2600) or later required, have instead 16 (1600)!`, make sure you're using a Python build that ships a modern Tk. The stock [python.org 3.13.5 installer](https://www.python.org/downloads/release/python-3135/) includes Tk 8.6 and has been verified to work.
|
51
52
|
|
52
|
-
When extracted on Windows the bundled `talks-reducer.exe` behaves like
|
53
|
-
`python talks_reducer
|
53
|
+
When extracted on Windows the bundled `talks-reducer.exe` behaves like running
|
54
|
+
`python -m talks_reducer.gui`: double-clicking it launches the GUI
|
54
55
|
and passing a video file path (for example via *Open with…* or drag-and-drop
|
55
56
|
onto the executable) automatically queues that recording for processing.
|
56
57
|
|
@@ -80,6 +81,10 @@ talks-reducer --url http://localhost:9005 demo.mp4
|
|
80
81
|
talks-reducer --host 192.168.1.42 demo.mp4
|
81
82
|
```
|
82
83
|
|
84
|
+
Remote jobs respect the same timing controls as the local CLI. Provide
|
85
|
+
`--silent-threshold`, `--sounded-speed`, or `--silent-speed` to tweak how the
|
86
|
+
server trims and accelerates segments without falling back to local mode.
|
87
|
+
|
83
88
|
Want to see progress as the remote server works? Add `--server-stream` so the
|
84
89
|
CLI prints live progress bars and log lines while you wait for the download.
|
85
90
|
|
@@ -98,6 +103,10 @@ Prefer a lightweight browser interface? Launch the Gradio-powered simple mode wi
|
|
98
103
|
talks-reducer server
|
99
104
|
```
|
100
105
|
|
106
|
+
The browser UI mirrors the CLI timing controls with sliders for the silent
|
107
|
+
threshold and playback speeds, so you can tune exports without leaving the
|
108
|
+
remote workflow.
|
109
|
+
|
101
110
|
Want the server to live in your system tray instead of a terminal window? Use:
|
102
111
|
|
103
112
|
```sh
|
@@ -0,0 +1,29 @@
|
|
1
|
+
talks_reducer/__about__.py,sha256=wwxwKZDkQSt_KMTilch61vXb8z9MEha3gfTpYfebr70,92
|
2
|
+
talks_reducer/__init__.py,sha256=Kzh1hXaw6Vq3DyTqrnJGOq8pn0P8lvaDcsg1bFUjFKk,208
|
3
|
+
talks_reducer/__main__.py,sha256=azR_vh8HFPLaOnh-L6gUFWsL67I6iHtbeH5rQhsipGY,299
|
4
|
+
talks_reducer/audio.py,sha256=sjHMeY0H9ESG-Gn5BX0wFRBX7sXjWwsgS8u9Vb0bJ88,4396
|
5
|
+
talks_reducer/chunks.py,sha256=IpdZxRFPURSG5wP-OQ_p09CVP8wcKwIFysV29zOTSWI,2959
|
6
|
+
talks_reducer/cli.py,sha256=MeL5feATcJc0bGPDuW_L3HgepKQUi335zs3HVg47WrE,16474
|
7
|
+
talks_reducer/discovery.py,sha256=BJ-iMir65cJMs0u-_EYdknBQT_grvCZaJNOx1xGi2PU,4590
|
8
|
+
talks_reducer/ffmpeg.py,sha256=dsHBOBcr5XCSg0q3xmzLOcibBiEdyrXdEQa-ze5vQsM,12551
|
9
|
+
talks_reducer/models.py,sha256=a1cHCVTNTJYh9I437CuANiaz5R_s-uECeGyK7WB67HQ,2018
|
10
|
+
talks_reducer/pipeline.py,sha256=OGZG_3G1fh6LFQw9NuhnLq7gwJ5YcJ6l76QNWJydD7c,13630
|
11
|
+
talks_reducer/progress.py,sha256=Mh43M6VWhjjUv9CI22xfD2EJ_7Aq3PCueqefQ9Bd5-o,4565
|
12
|
+
talks_reducer/server.py,sha256=CLcgEyfBjsglSG1VkqiaP-4NsZZklL5o7ayYwnNMqbs,15782
|
13
|
+
talks_reducer/server_tray.py,sha256=GBjx7Fr18Uy5O38ZjM5VXR77ou2_AEUqx2wN8MOZuss,23380
|
14
|
+
talks_reducer/service_client.py,sha256=8C2v2aNj8UAECfy1pw7oIzCK3Ktx5E6kZoNSYWH-8m8,12656
|
15
|
+
talks_reducer/version_utils.py,sha256=TkYrTznVb2JqxFXzVzPd6PEnYP2MH7dxKl1J4-3DjMA,755
|
16
|
+
talks_reducer/gui/__init__.py,sha256=UQJtyb87wwZyvauPo0mM_aiau9NAhKbl4ggwJoPCNC0,59870
|
17
|
+
talks_reducer/gui/__main__.py,sha256=9YWkGopLypanfMMq_RoQjjpPScTOxA7-biqMhQq-SSM,140
|
18
|
+
talks_reducer/gui/discovery.py,sha256=6AXPcFGXqHZNhSBE1O5PyoH_CEMCb0Jk-9JGFwyAuRk,4108
|
19
|
+
talks_reducer/gui/layout.py,sha256=rFzNt78sf6TQzHkEBUmINdD5-iJAWkBKHkIo_v5f7iU,17146
|
20
|
+
talks_reducer/gui/preferences.py,sha256=ahDLPNIzvL71sw8WvgY9-TV_kaWTl_JTkn1gf2Z1EaA,3531
|
21
|
+
talks_reducer/gui/remote.py,sha256=92HebrIo009GgRD7RBriw9yR8sbYHocsPzmjPe4ybhA,12071
|
22
|
+
talks_reducer/gui/theme.py,sha256=ueqpPVPOwnLkeHlOlWkUcdcoClJrAqz9LWT79p33Xic,7718
|
23
|
+
talks_reducer/resources/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
24
|
+
talks_reducer-0.7.1.dist-info/licenses/LICENSE,sha256=jN17mHNR3e84awmH3AbpWBcBDBzPxEH0rcOFoj1s7sQ,1124
|
25
|
+
talks_reducer-0.7.1.dist-info/METADATA,sha256=tiabxtCJb9UUqczxKpW0j27BWPWmfMfBAmb2n6jRt_U,8810
|
26
|
+
talks_reducer-0.7.1.dist-info/WHEEL,sha256=_zCd3N1l69ArxyTb8rzEoP9TpbYXkqRFSNOD5OuxnTs,91
|
27
|
+
talks_reducer-0.7.1.dist-info/entry_points.txt,sha256=X2pjoh2vWBXXExVWorv1mbA1aTEVP3fyuZH4AixqZK4,208
|
28
|
+
talks_reducer-0.7.1.dist-info/top_level.txt,sha256=pJWGcy__LR9JIEKH3QJyFmk9XrIsiFtqvuMNxFdIzDU,14
|
29
|
+
talks_reducer-0.7.1.dist-info/RECORD,,
|
@@ -1,23 +0,0 @@
|
|
1
|
-
talks_reducer/__about__.py,sha256=Ru7aBsnrNGQTUXUg8QmcQLNkibVg9YI78rRvvzMAfek,92
|
2
|
-
talks_reducer/__init__.py,sha256=Kzh1hXaw6Vq3DyTqrnJGOq8pn0P8lvaDcsg1bFUjFKk,208
|
3
|
-
talks_reducer/__main__.py,sha256=azR_vh8HFPLaOnh-L6gUFWsL67I6iHtbeH5rQhsipGY,299
|
4
|
-
talks_reducer/audio.py,sha256=sjHMeY0H9ESG-Gn5BX0wFRBX7sXjWwsgS8u9Vb0bJ88,4396
|
5
|
-
talks_reducer/chunks.py,sha256=IpdZxRFPURSG5wP-OQ_p09CVP8wcKwIFysV29zOTSWI,2959
|
6
|
-
talks_reducer/cli.py,sha256=JH8lvPUyk6jWGcnNRIGJeIh2ZcOvC5CORvj5GLuqq0c,16075
|
7
|
-
talks_reducer/discovery.py,sha256=BJ-iMir65cJMs0u-_EYdknBQT_grvCZaJNOx1xGi2PU,4590
|
8
|
-
talks_reducer/ffmpeg.py,sha256=dsHBOBcr5XCSg0q3xmzLOcibBiEdyrXdEQa-ze5vQsM,12551
|
9
|
-
talks_reducer/gui.py,sha256=Rzwsho7Y1nXxYP-8glthrFuRFImTyxHDW9nWlazehi4,89125
|
10
|
-
talks_reducer/models.py,sha256=6Q_8rmHLyImXp88D4B7ptTbFaH_xXa_yxs8A2dypz2Y,2004
|
11
|
-
talks_reducer/pipeline.py,sha256=naAP8gli9MahoxVdla2tRn2vdDuBBU5ywWkYfZLkMcE,12211
|
12
|
-
talks_reducer/progress.py,sha256=Mh43M6VWhjjUv9CI22xfD2EJ_7Aq3PCueqefQ9Bd5-o,4565
|
13
|
-
talks_reducer/server.py,sha256=QVMBSgxeTLCanUjf2CgeveOYmSuyGzJCVIIS7uJxX-E,14163
|
14
|
-
talks_reducer/server_tray.py,sha256=GBjx7Fr18Uy5O38ZjM5VXR77ou2_AEUqx2wN8MOZuss,23380
|
15
|
-
talks_reducer/service_client.py,sha256=JnhQhRxVwrGo9eUlduoZ6f_YYyXvjU7hF8UTNprH7TM,10984
|
16
|
-
talks_reducer/version_utils.py,sha256=TkYrTznVb2JqxFXzVzPd6PEnYP2MH7dxKl1J4-3DjMA,755
|
17
|
-
talks_reducer/resources/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
18
|
-
talks_reducer-0.6.3.dist-info/licenses/LICENSE,sha256=jN17mHNR3e84awmH3AbpWBcBDBzPxEH0rcOFoj1s7sQ,1124
|
19
|
-
talks_reducer-0.6.3.dist-info/METADATA,sha256=OSRp6SEzDtAV-4EJS6JNXkkSRlNKMojzPMCiq5Udev8,8415
|
20
|
-
talks_reducer-0.6.3.dist-info/WHEEL,sha256=_zCd3N1l69ArxyTb8rzEoP9TpbYXkqRFSNOD5OuxnTs,91
|
21
|
-
talks_reducer-0.6.3.dist-info/entry_points.txt,sha256=X2pjoh2vWBXXExVWorv1mbA1aTEVP3fyuZH4AixqZK4,208
|
22
|
-
talks_reducer-0.6.3.dist-info/top_level.txt,sha256=pJWGcy__LR9JIEKH3QJyFmk9XrIsiFtqvuMNxFdIzDU,14
|
23
|
-
talks_reducer-0.6.3.dist-info/RECORD,,
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|