talks-reducer 0.4.1__tar.gz → 0.5.1__tar.gz

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.
Files changed (32) hide show
  1. talks_reducer-0.5.1/PKG-INFO +119 -0
  2. talks_reducer-0.5.1/README.md +92 -0
  3. {talks_reducer-0.4.1 → talks_reducer-0.5.1}/pyproject.toml +2 -0
  4. {talks_reducer-0.4.1 → talks_reducer-0.5.1}/talks_reducer/__about__.py +1 -1
  5. {talks_reducer-0.4.1 → talks_reducer-0.5.1}/talks_reducer/cli.py +25 -4
  6. {talks_reducer-0.4.1 → talks_reducer-0.5.1}/talks_reducer/ffmpeg.py +34 -6
  7. {talks_reducer-0.4.1 → talks_reducer-0.5.1}/talks_reducer/gui.py +162 -27
  8. {talks_reducer-0.4.1 → talks_reducer-0.5.1}/talks_reducer/models.py +29 -4
  9. {talks_reducer-0.4.1 → talks_reducer-0.5.1}/talks_reducer/pipeline.py +83 -9
  10. talks_reducer-0.5.1/talks_reducer/server.py +354 -0
  11. talks_reducer-0.5.1/talks_reducer/service_client.py +102 -0
  12. talks_reducer-0.5.1/talks_reducer.egg-info/PKG-INFO +119 -0
  13. {talks_reducer-0.4.1 → talks_reducer-0.5.1}/talks_reducer.egg-info/SOURCES.txt +5 -1
  14. {talks_reducer-0.4.1 → talks_reducer-0.5.1}/talks_reducer.egg-info/entry_points.txt +1 -0
  15. {talks_reducer-0.4.1 → talks_reducer-0.5.1}/talks_reducer.egg-info/requires.txt +1 -0
  16. {talks_reducer-0.4.1 → talks_reducer-0.5.1}/tests/test_cli.py +27 -0
  17. talks_reducer-0.5.1/tests/test_server.py +68 -0
  18. talks_reducer-0.5.1/tests/test_service_client.py +112 -0
  19. talks_reducer-0.4.1/PKG-INFO +0 -71
  20. talks_reducer-0.4.1/README.md +0 -45
  21. talks_reducer-0.4.1/talks_reducer.egg-info/PKG-INFO +0 -71
  22. {talks_reducer-0.4.1 → talks_reducer-0.5.1}/LICENSE +0 -0
  23. {talks_reducer-0.4.1 → talks_reducer-0.5.1}/setup.cfg +0 -0
  24. {talks_reducer-0.4.1 → talks_reducer-0.5.1}/talks_reducer/__init__.py +0 -0
  25. {talks_reducer-0.4.1 → talks_reducer-0.5.1}/talks_reducer/__main__.py +0 -0
  26. {talks_reducer-0.4.1 → talks_reducer-0.5.1}/talks_reducer/audio.py +0 -0
  27. {talks_reducer-0.4.1 → talks_reducer-0.5.1}/talks_reducer/chunks.py +0 -0
  28. {talks_reducer-0.4.1 → talks_reducer-0.5.1}/talks_reducer/progress.py +0 -0
  29. {talks_reducer-0.4.1 → talks_reducer-0.5.1}/talks_reducer.egg-info/dependency_links.txt +0 -0
  30. {talks_reducer-0.4.1 → talks_reducer-0.5.1}/talks_reducer.egg-info/top_level.txt +0 -0
  31. {talks_reducer-0.4.1 → talks_reducer-0.5.1}/tests/test_audio.py +0 -0
  32. {talks_reducer-0.4.1 → talks_reducer-0.5.1}/tests/test_pipeline_service.py +0 -0
@@ -0,0 +1,119 @@
1
+ Metadata-Version: 2.4
2
+ Name: talks-reducer
3
+ Version: 0.5.1
4
+ Summary: CLI for speeding up long-form talks by removing silence
5
+ Author: Talks Reducer Maintainers
6
+ License-Expression: MIT
7
+ Requires-Python: >=3.9
8
+ Description-Content-Type: text/markdown
9
+ License-File: LICENSE
10
+ Requires-Dist: audiotsm>=0.1.2
11
+ Requires-Dist: scipy>=1.10.0
12
+ Requires-Dist: numpy>=1.22.0
13
+ Requires-Dist: tqdm>=4.65.0
14
+ Requires-Dist: tkinterdnd2>=0.3.0
15
+ Requires-Dist: Pillow>=9.0.0
16
+ Requires-Dist: imageio-ffmpeg>=0.4.8
17
+ Requires-Dist: gradio>=4.0.0
18
+ Provides-Extra: dev
19
+ Requires-Dist: build>=1.0.0; extra == "dev"
20
+ Requires-Dist: twine>=4.0.0; extra == "dev"
21
+ Requires-Dist: pytest>=7.0.0; extra == "dev"
22
+ Requires-Dist: black>=23.0.0; extra == "dev"
23
+ Requires-Dist: isort>=5.12.0; extra == "dev"
24
+ Requires-Dist: bump-my-version>=0.5.0; extra == "dev"
25
+ Requires-Dist: pyinstaller>=6.4.0; extra == "dev"
26
+ Dynamic: license-file
27
+
28
+ # Talks Reducer
29
+ Talks Reducer shortens long-form presentations by removing silent gaps and optionally re-encoding them to smaller files. The
30
+ project was renamed from **jumpcutter** to emphasize its focus on conference talks and screencasts.
31
+
32
+ ![Main demo](docs/assets/screencast-main.gif)
33
+
34
+ ## Example
35
+ - 1h 37m, 571 MB — Original OBS video recording
36
+ - 1h 19m, 751 MB — Talks Reducer
37
+ - 1h 19m, 171 MB — Talks Reducer `--small`
38
+
39
+ ## Changelog
40
+
41
+ See [CHANGELOG.md](CHANGELOG.md).
42
+
43
+ ## Install GUI (Windows, macOS)
44
+ Go to the [releases page](https://github.com/popstas/talks-reducer/releases) and download the appropriate artifact:
45
+
46
+ - **Windows** — `talks-reducer-windows-0.4.0.zip`
47
+ - **macOS** — `talks-reducer.app.zip`
48
+
49
+ > **Troubleshooting:** If launching the bundle (or running `python talks_reducer/gui.py`) 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.
50
+
51
+ When extracted on Windows the bundled `talks-reducer.exe` behaves like the
52
+ `python talks_reducer/gui.py` entry point: double-clicking it launches the GUI
53
+ and passing a video file path (for example via *Open with…* or drag-and-drop
54
+ onto the executable) automatically queues that recording for processing.
55
+
56
+ ## Install CLI (Linux, Windows, macOS)
57
+ ```
58
+ pip install talks-reducer
59
+ ```
60
+
61
+ **Note:** FFmpeg is now bundled automatically with the package, so you don't need to install it separately. You you need, don't know actually.
62
+
63
+ The `--small` preset applies a 720p video scale and 128 kbps audio bitrate, making it useful for sharing talks over constrained
64
+ connections. Without `--small`, the script aims to preserve original quality while removing silence.
65
+
66
+ Example CLI usage:
67
+
68
+ ```sh
69
+ talks-reducer --small input.mp4
70
+ ```
71
+
72
+ ### Speech detection
73
+
74
+ Talks Reducer now relies on its built-in volume thresholding to detect speech. Adjust `--silent_threshold` if you need to fine-tune when segments count as silence. Dropping the optional Silero VAD integration keeps the install lightweight and avoids pulling in PyTorch.
75
+
76
+ When CUDA-capable hardware is available the pipeline leans on GPU encoders to keep export times low, but it still runs great on
77
+ CPUs.
78
+
79
+ ## Simple web server
80
+
81
+ Prefer a lightweight browser interface? Launch the Gradio-powered simple mode with:
82
+
83
+ ```sh
84
+ talks-reducer server
85
+ ```
86
+
87
+ This opens a local web page featuring a drag-and-drop upload zone, a **Small video** checkbox that mirrors the CLI preset, a live
88
+ progress indicator, and automatic previews of the processed output. Once the job completes you can inspect the resulting compression
89
+ ratio and download the rendered video directly from the page.
90
+
91
+ ### Uploading and retrieving a processed video
92
+
93
+ 1. Open the printed `http://localhost:<port>` address (the default port is `9005`).
94
+ 2. Drag a video onto the **Video file** drop zone or click to browse and select one from disk.
95
+ 3. (Optional) Enable **Small video** before the upload finishes to apply the 720p/128 kbps preset.
96
+ 4. Wait for the progress bar and log to report completion—the interface queues work automatically after the file arrives.
97
+ 5. Watch the processed preview in the **Processed video** player and click **Download processed file** to save the result locally.
98
+
99
+ Need to change where the server listens? Run `talks-reducer server --host 0.0.0.0 --port 7860` (or any other port) to bind to a
100
+ different address.
101
+
102
+ ### Automating uploads from the command line
103
+
104
+ Prefer to script uploads instead of using the browser UI? Start the server and use the bundled helper to submit a job and save
105
+ the processed video locally:
106
+
107
+ ```sh
108
+ python -m talks_reducer.service_client --server http://127.0.0.1:9005/ --input demo.mp4 --output output/demo_processed.mp4
109
+ ```
110
+
111
+ The helper wraps the Gradio API exposed by `server.py`, waits for processing to complete, then copies the rendered file to the
112
+ path you provide. Pass `--small` to mirror the **Small video** checkbox or `--print-log` to stream the server log after the
113
+ download finishes.
114
+
115
+ ## Contributing
116
+ See `CONTRIBUTION.md` for development setup details and guidance on sharing improvements.
117
+
118
+ ## License
119
+ Talks Reducer is released under the MIT License. See `LICENSE` for the full text.
@@ -0,0 +1,92 @@
1
+ # Talks Reducer
2
+ Talks Reducer shortens long-form presentations by removing silent gaps and optionally re-encoding them to smaller files. The
3
+ project was renamed from **jumpcutter** to emphasize its focus on conference talks and screencasts.
4
+
5
+ ![Main demo](docs/assets/screencast-main.gif)
6
+
7
+ ## Example
8
+ - 1h 37m, 571 MB — Original OBS video recording
9
+ - 1h 19m, 751 MB — Talks Reducer
10
+ - 1h 19m, 171 MB — Talks Reducer `--small`
11
+
12
+ ## Changelog
13
+
14
+ See [CHANGELOG.md](CHANGELOG.md).
15
+
16
+ ## Install GUI (Windows, macOS)
17
+ Go to the [releases page](https://github.com/popstas/talks-reducer/releases) and download the appropriate artifact:
18
+
19
+ - **Windows** — `talks-reducer-windows-0.4.0.zip`
20
+ - **macOS** — `talks-reducer.app.zip`
21
+
22
+ > **Troubleshooting:** If launching the bundle (or running `python talks_reducer/gui.py`) 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.
23
+
24
+ When extracted on Windows the bundled `talks-reducer.exe` behaves like the
25
+ `python talks_reducer/gui.py` entry point: double-clicking it launches the GUI
26
+ and passing a video file path (for example via *Open with…* or drag-and-drop
27
+ onto the executable) automatically queues that recording for processing.
28
+
29
+ ## Install CLI (Linux, Windows, macOS)
30
+ ```
31
+ pip install talks-reducer
32
+ ```
33
+
34
+ **Note:** FFmpeg is now bundled automatically with the package, so you don't need to install it separately. You you need, don't know actually.
35
+
36
+ The `--small` preset applies a 720p video scale and 128 kbps audio bitrate, making it useful for sharing talks over constrained
37
+ connections. Without `--small`, the script aims to preserve original quality while removing silence.
38
+
39
+ Example CLI usage:
40
+
41
+ ```sh
42
+ talks-reducer --small input.mp4
43
+ ```
44
+
45
+ ### Speech detection
46
+
47
+ Talks Reducer now relies on its built-in volume thresholding to detect speech. Adjust `--silent_threshold` if you need to fine-tune when segments count as silence. Dropping the optional Silero VAD integration keeps the install lightweight and avoids pulling in PyTorch.
48
+
49
+ When CUDA-capable hardware is available the pipeline leans on GPU encoders to keep export times low, but it still runs great on
50
+ CPUs.
51
+
52
+ ## Simple web server
53
+
54
+ Prefer a lightweight browser interface? Launch the Gradio-powered simple mode with:
55
+
56
+ ```sh
57
+ talks-reducer server
58
+ ```
59
+
60
+ This opens a local web page featuring a drag-and-drop upload zone, a **Small video** checkbox that mirrors the CLI preset, a live
61
+ progress indicator, and automatic previews of the processed output. Once the job completes you can inspect the resulting compression
62
+ ratio and download the rendered video directly from the page.
63
+
64
+ ### Uploading and retrieving a processed video
65
+
66
+ 1. Open the printed `http://localhost:<port>` address (the default port is `9005`).
67
+ 2. Drag a video onto the **Video file** drop zone or click to browse and select one from disk.
68
+ 3. (Optional) Enable **Small video** before the upload finishes to apply the 720p/128 kbps preset.
69
+ 4. Wait for the progress bar and log to report completion—the interface queues work automatically after the file arrives.
70
+ 5. Watch the processed preview in the **Processed video** player and click **Download processed file** to save the result locally.
71
+
72
+ Need to change where the server listens? Run `talks-reducer server --host 0.0.0.0 --port 7860` (or any other port) to bind to a
73
+ different address.
74
+
75
+ ### Automating uploads from the command line
76
+
77
+ Prefer to script uploads instead of using the browser UI? Start the server and use the bundled helper to submit a job and save
78
+ the processed video locally:
79
+
80
+ ```sh
81
+ python -m talks_reducer.service_client --server http://127.0.0.1:9005/ --input demo.mp4 --output output/demo_processed.mp4
82
+ ```
83
+
84
+ The helper wraps the Gradio API exposed by `server.py`, waits for processing to complete, then copies the rendered file to the
85
+ path you provide. Pass `--small` to mirror the **Small video** checkbox or `--print-log` to stream the server log after the
86
+ download finishes.
87
+
88
+ ## Contributing
89
+ See `CONTRIBUTION.md` for development setup details and guidance on sharing improvements.
90
+
91
+ ## License
92
+ Talks Reducer is released under the MIT License. See `LICENSE` for the full text.
@@ -20,6 +20,7 @@ dependencies = [
20
20
  "tkinterdnd2>=0.3.0",
21
21
  "Pillow>=9.0.0",
22
22
  "imageio-ffmpeg>=0.4.8",
23
+ "gradio>=4.0.0",
23
24
  ]
24
25
 
25
26
  [project.optional-dependencies]
@@ -36,6 +37,7 @@ dev = [
36
37
  [project.scripts]
37
38
  talks-reducer = "talks_reducer.cli:main"
38
39
  talks-reducer-gui = "talks_reducer.gui:main"
40
+ talks-reducer-server = "talks_reducer.server:main"
39
41
 
40
42
  [tool.setuptools.dynamic]
41
43
  version = {attr = "talks_reducer.__about__.__version__"}
@@ -2,4 +2,4 @@
2
2
 
3
3
  __all__ = ["__version__"]
4
4
 
5
- __version__ = "0.4.1"
5
+ __version__ = "0.5.1"
@@ -18,7 +18,7 @@ try:
18
18
  except Exception: # pragma: no cover - fallback if metadata file missing
19
19
  _about_version = ""
20
20
  from .ffmpeg import FFmpegNotFoundError
21
- from .models import ProcessingOptions
21
+ from .models import ProcessingOptions, default_temp_folder
22
22
  from .pipeline import speed_up_video
23
23
  from .progress import TqdmProgressReporter
24
24
 
@@ -55,7 +55,7 @@ def _build_parser() -> argparse.ArgumentParser:
55
55
  parser.add_argument(
56
56
  "--temp_folder",
57
57
  type=str,
58
- default="TEMP",
58
+ default=str(default_temp_folder()),
59
59
  help="The file path of the temporary working folder.",
60
60
  )
61
61
  parser.add_argument(
@@ -63,7 +63,7 @@ def _build_parser() -> argparse.ArgumentParser:
63
63
  "--silent_threshold",
64
64
  type=float,
65
65
  dest="silent_threshold",
66
- help="The volume amount that frames' audio needs to surpass to be considered sounded. Defaults to 0.03.",
66
+ help="The volume amount that frames' audio needs to surpass to be considered sounded. Defaults to 0.05.",
67
67
  )
68
68
  parser.add_argument(
69
69
  "-S",
@@ -143,6 +143,22 @@ def _launch_gui(argv: Sequence[str]) -> bool:
143
143
  return bool(gui_main(list(argv)))
144
144
 
145
145
 
146
+ def _launch_server(argv: Sequence[str]) -> bool:
147
+ """Attempt to launch the Gradio web server with the provided arguments."""
148
+
149
+ try:
150
+ server_module = import_module(".server", __package__)
151
+ except ImportError:
152
+ return False
153
+
154
+ server_main = getattr(server_module, "main", None)
155
+ if server_main is None:
156
+ return False
157
+
158
+ server_main(list(argv))
159
+ return True
160
+
161
+
146
162
  def main(argv: Optional[Sequence[str]] = None) -> None:
147
163
  """Entry point for the command line interface.
148
164
 
@@ -154,6 +170,12 @@ def main(argv: Optional[Sequence[str]] = None) -> None:
154
170
  else:
155
171
  argv_list = list(argv)
156
172
 
173
+ if argv_list and argv_list[0] in {"server", "serve"}:
174
+ if not _launch_server(argv_list[1:]):
175
+ print("Gradio server mode is unavailable.", file=sys.stderr)
176
+ sys.exit(1)
177
+ return
178
+
157
179
  if not argv_list:
158
180
  if _launch_gui(argv_list):
159
181
  return
@@ -200,7 +222,6 @@ def main(argv: Optional[Sequence[str]] = None) -> None:
200
222
  option_kwargs["sample_rate"] = int(local_options["sample_rate"])
201
223
  if "small" in local_options:
202
224
  option_kwargs["small"] = bool(local_options["small"])
203
-
204
225
  options = ProcessingOptions(**option_kwargs)
205
226
 
206
227
  try:
@@ -52,6 +52,9 @@ def find_ffmpeg() -> Optional[str]:
52
52
  "C:\\ProgramData\\chocolatey\\bin\\ffmpeg.exe",
53
53
  "C:\\Program Files\\ffmpeg\\bin\\ffmpeg.exe",
54
54
  "C:\\ffmpeg\\bin\\ffmpeg.exe",
55
+ "/usr/local/bin/ffmpeg",
56
+ "/opt/homebrew/bin/ffmpeg",
57
+ "/usr/bin/ffmpeg",
55
58
  "ffmpeg",
56
59
  ]
57
60
 
@@ -92,6 +95,9 @@ def find_ffprobe() -> Optional[str]:
92
95
  "C:\\ProgramData\\chocolatey\\bin\\ffprobe.exe",
93
96
  "C:\\Program Files\\ffmpeg\\bin\\ffprobe.exe",
94
97
  "C:\\ffmpeg\\bin\\ffprobe.exe",
98
+ "/usr/local/bin/ffprobe",
99
+ "/opt/homebrew/bin/ffprobe",
100
+ "/usr/bin/ffprobe",
95
101
  "ffprobe",
96
102
  ]
97
103
 
@@ -242,11 +248,29 @@ def run_timed_ffmpeg_command(
242
248
  if not line:
243
249
  continue
244
250
 
245
- sys.stderr.write(line)
246
- sys.stderr.flush()
247
-
248
- # Send FFmpeg output to reporter for GUI display
249
- progress_reporter.log(line.strip())
251
+ # Filter out excessive progress output, only show important lines
252
+ if any(
253
+ keyword in line.lower()
254
+ for keyword in [
255
+ "error",
256
+ "warning",
257
+ "encoded successfully",
258
+ "frame=",
259
+ "time=",
260
+ "size=",
261
+ "bitrate=",
262
+ "speed=",
263
+ ]
264
+ ):
265
+ sys.stderr.write(line)
266
+ sys.stderr.flush()
267
+
268
+ # Send FFmpeg output to reporter for GUI display (filtered)
269
+ if any(
270
+ keyword in line.lower()
271
+ for keyword in ["error", "warning", "encoded successfully", "frame="]
272
+ ):
273
+ progress_reporter.log(line.strip())
250
274
 
251
275
  match = re.search(r"frame=\s*(\d+)", line)
252
276
  if match:
@@ -365,7 +389,11 @@ def build_video_commands(
365
389
  # Use a fast software encoder instead
366
390
  video_encoder_args = ["-c:v libx264", "-preset veryfast", "-crf 23"]
367
391
 
368
- audio_parts = ["-c:a aac", f'"{output_file}"', "-loglevel info -stats -hide_banner"]
392
+ audio_parts = [
393
+ "-c:a aac",
394
+ f'"{output_file}"',
395
+ "-loglevel warning -stats -hide_banner",
396
+ ]
369
397
 
370
398
  full_command_parts = (
371
399
  global_parts + input_parts + output_parts + video_encoder_args + audio_parts