talks-reducer 0.3.2__tar.gz → 0.3.4__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 (28) hide show
  1. talks_reducer-0.3.4/PKG-INFO +71 -0
  2. talks_reducer-0.3.4/README.md +45 -0
  3. {talks_reducer-0.3.2 → talks_reducer-0.3.4}/pyproject.toml +5 -1
  4. {talks_reducer-0.3.2 → talks_reducer-0.3.4}/setup.cfg +4 -4
  5. talks_reducer-0.3.4/talks_reducer/__about__.py +5 -0
  6. {talks_reducer-0.3.2 → talks_reducer-0.3.4}/talks_reducer/__init__.py +2 -1
  7. {talks_reducer-0.3.2 → talks_reducer-0.3.4}/talks_reducer/cli.py +28 -5
  8. {talks_reducer-0.3.2 → talks_reducer-0.3.4}/talks_reducer/gui.py +49 -42
  9. {talks_reducer-0.3.2 → talks_reducer-0.3.4}/talks_reducer/models.py +3 -0
  10. {talks_reducer-0.3.2 → talks_reducer-0.3.4}/talks_reducer/pipeline.py +11 -0
  11. talks_reducer-0.3.4/talks_reducer.egg-info/PKG-INFO +71 -0
  12. {talks_reducer-0.3.2 → talks_reducer-0.3.4}/talks_reducer.egg-info/SOURCES.txt +1 -0
  13. {talks_reducer-0.3.2 → talks_reducer-0.3.4}/talks_reducer.egg-info/requires.txt +1 -0
  14. {talks_reducer-0.3.2 → talks_reducer-0.3.4}/tests/test_pipeline_service.py +9 -3
  15. talks_reducer-0.3.2/PKG-INFO +0 -156
  16. talks_reducer-0.3.2/README.md +0 -131
  17. talks_reducer-0.3.2/talks_reducer.egg-info/PKG-INFO +0 -156
  18. {talks_reducer-0.3.2 → talks_reducer-0.3.4}/LICENSE +0 -0
  19. {talks_reducer-0.3.2 → talks_reducer-0.3.4}/talks_reducer/__main__.py +0 -0
  20. {talks_reducer-0.3.2 → talks_reducer-0.3.4}/talks_reducer/audio.py +0 -0
  21. {talks_reducer-0.3.2 → talks_reducer-0.3.4}/talks_reducer/chunks.py +0 -0
  22. {talks_reducer-0.3.2 → talks_reducer-0.3.4}/talks_reducer/ffmpeg.py +0 -0
  23. {talks_reducer-0.3.2 → talks_reducer-0.3.4}/talks_reducer/progress.py +0 -0
  24. {talks_reducer-0.3.2 → talks_reducer-0.3.4}/talks_reducer.egg-info/dependency_links.txt +0 -0
  25. {talks_reducer-0.3.2 → talks_reducer-0.3.4}/talks_reducer.egg-info/entry_points.txt +0 -0
  26. {talks_reducer-0.3.2 → talks_reducer-0.3.4}/talks_reducer.egg-info/top_level.txt +0 -0
  27. {talks_reducer-0.3.2 → talks_reducer-0.3.4}/tests/test_audio.py +0 -0
  28. {talks_reducer-0.3.2 → talks_reducer-0.3.4}/tests/test_cli.py +0 -0
@@ -0,0 +1,71 @@
1
+ Metadata-Version: 2.4
2
+ Name: talks-reducer
3
+ Version: 0.3.4
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
+ Provides-Extra: dev
18
+ Requires-Dist: build>=1.0.0; extra == "dev"
19
+ Requires-Dist: twine>=4.0.0; extra == "dev"
20
+ Requires-Dist: pytest>=7.0.0; extra == "dev"
21
+ Requires-Dist: black>=23.0.0; extra == "dev"
22
+ Requires-Dist: isort>=5.12.0; extra == "dev"
23
+ Requires-Dist: bump-my-version>=0.5.0; extra == "dev"
24
+ Requires-Dist: pyinstaller>=6.0.0; extra == "dev"
25
+ Dynamic: license-file
26
+
27
+ # Talks Reducer
28
+ Talks Reducer shortens long-form presentations by removing silent gaps and optionally re-encoding them to smaller files. The
29
+ project was renamed from **jumpcutter** to emphasize its focus on conference talks and screencasts.
30
+
31
+ ![Main demo](docs/assets/screencast-main.gif)
32
+
33
+ ## Example
34
+ - 1h 37m, 571 MB — Original OBS video recording
35
+ - 1h 19m, 751 MB — Talks Reducer
36
+ - 1h 19m, 171 MB — Talks Reducer `--small`
37
+
38
+ ## Changelog
39
+
40
+ See [CHANGELOG.md](CHANGELOG.md).
41
+
42
+ ## Install GUI (Windows, macOS)
43
+ Go to the [releases page](https://github.com/popstas/talks-reducer/releases) and download the appropriate artifact:
44
+
45
+ - **Windows** — `talks-reducer-windows.zip`
46
+ - **macOS** — `talks-reducer.app.zip` (but it doesn't work for me)
47
+
48
+ ## Install CLI (Linux, Windows, macOS)
49
+ ```
50
+ pip install talks-reducer
51
+ ```
52
+
53
+ **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.
54
+
55
+ The `--small` preset applies a 720p video scale and 128 kbps audio bitrate, making it useful for sharing talks over constrained
56
+ connections. Without `--small`, the script aims to preserve original quality while removing silence.
57
+
58
+ Example CLI usage:
59
+
60
+ ```sh
61
+ talks-reducer --small input.mp4
62
+ ```
63
+
64
+ When CUDA-capable hardware is available the pipeline leans on GPU encoders to keep export times low, but it still runs great on
65
+ CPUs.
66
+
67
+ ## Contributing
68
+ See `CONTRIBUTION.md` for development setup details and guidance on sharing improvements.
69
+
70
+ ## License
71
+ Talks Reducer is released under the MIT License. See `LICENSE` for the full text.
@@ -0,0 +1,45 @@
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.zip`
20
+ - **macOS** — `talks-reducer.app.zip` (but it doesn't work for me)
21
+
22
+ ## Install CLI (Linux, Windows, macOS)
23
+ ```
24
+ pip install talks-reducer
25
+ ```
26
+
27
+ **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.
28
+
29
+ The `--small` preset applies a 720p video scale and 128 kbps audio bitrate, making it useful for sharing talks over constrained
30
+ connections. Without `--small`, the script aims to preserve original quality while removing silence.
31
+
32
+ Example CLI usage:
33
+
34
+ ```sh
35
+ talks-reducer --small input.mp4
36
+ ```
37
+
38
+ When CUDA-capable hardware is available the pipeline leans on GPU encoders to keep export times low, but it still runs great on
39
+ CPUs.
40
+
41
+ ## Contributing
42
+ See `CONTRIBUTION.md` for development setup details and guidance on sharing improvements.
43
+
44
+ ## License
45
+ Talks Reducer is released under the MIT License. See `LICENSE` for the full text.
@@ -4,7 +4,7 @@ build-backend = "setuptools.build_meta"
4
4
 
5
5
  [project]
6
6
  name = "talks-reducer"
7
- version = "0.3.2"
7
+ dynamic = ["version"]
8
8
  description = "CLI for speeding up long-form talks by removing silence"
9
9
  readme = "README.md"
10
10
  requires-python = ">=3.9"
@@ -29,6 +29,7 @@ dev = [
29
29
  "pytest>=7.0.0",
30
30
  "black>=23.0.0",
31
31
  "isort>=5.12.0",
32
+ "bump-my-version>=0.5.0",
32
33
  "pyinstaller>=6.0.0",
33
34
  ]
34
35
 
@@ -36,6 +37,9 @@ dev = [
36
37
  talks-reducer = "talks_reducer.cli:main"
37
38
  talks-reducer-gui = "talks_reducer.gui:main"
38
39
 
40
+ [tool.setuptools.dynamic]
41
+ version = {attr = "talks_reducer.__about__.__version__"}
42
+
39
43
  [tool.black]
40
44
  line-length = 88
41
45
  target-version = ["py39"]
@@ -1,4 +1,4 @@
1
- [egg_info]
2
- tag_build =
3
- tag_date = 0
4
-
1
+ [egg_info]
2
+ tag_build =
3
+ tag_date = 0
4
+
@@ -0,0 +1,5 @@
1
+ """Package metadata for talks_reducer."""
2
+
3
+ __all__ = ["__version__"]
4
+
5
+ __version__ = "0.3.4"
@@ -2,6 +2,7 @@
2
2
 
3
3
  from __future__ import annotations
4
4
 
5
+ from .__about__ import __version__
5
6
  from .cli import main
6
7
 
7
- __all__ = ["main"]
8
+ __all__ = ["main", "__version__"]
@@ -7,11 +7,16 @@ import os
7
7
  import sys
8
8
  import time
9
9
  from importlib import import_module
10
- from importlib.metadata import version
10
+ from importlib.metadata import PackageNotFoundError, version
11
11
  from pathlib import Path
12
12
  from typing import Dict, List, Optional, Sequence
13
13
 
14
14
  from . import audio
15
+
16
+ try:
17
+ from .__about__ import __version__ as _about_version
18
+ except Exception: # pragma: no cover - fallback if metadata file missing
19
+ _about_version = ""
15
20
  from .ffmpeg import FFmpegNotFoundError
16
21
  from .models import ProcessingOptions
17
22
  from .pipeline import speed_up_video
@@ -26,10 +31,7 @@ def _build_parser() -> argparse.ArgumentParser:
26
31
  )
27
32
 
28
33
  # Add version argument
29
- try:
30
- pkg_version = version("talks-reducer")
31
- except Exception:
32
- pkg_version = "unknown"
34
+ pkg_version = _resolve_version()
33
35
 
34
36
  parser.add_argument(
35
37
  "--version",
@@ -99,6 +101,18 @@ def _build_parser() -> argparse.ArgumentParser:
99
101
  return parser
100
102
 
101
103
 
104
+ def _resolve_version() -> str:
105
+ """Determine the package version for CLI reporting."""
106
+
107
+ if _about_version:
108
+ return _about_version
109
+
110
+ try:
111
+ return version("talks-reducer")
112
+ except (PackageNotFoundError, Exception):
113
+ return "unknown"
114
+
115
+
102
116
  def gather_input_files(paths: List[str]) -> List[str]:
103
117
  """Expand provided paths into a flat list of files that contain audio streams."""
104
118
 
@@ -196,6 +210,15 @@ def main(argv: Optional[Sequence[str]] = None) -> None:
196
210
  sys.exit(1)
197
211
 
198
212
  reporter.log(f"Completed: {result.output_file}")
213
+ summary_parts = []
214
+ time_ratio = getattr(result, "time_ratio", None)
215
+ size_ratio = getattr(result, "size_ratio", None)
216
+ if time_ratio is not None:
217
+ summary_parts.append(f"{time_ratio * 100:.0f}% time")
218
+ if size_ratio is not None:
219
+ summary_parts.append(f"{size_ratio * 100:.0f}% size")
220
+ if summary_parts:
221
+ reporter.log("Result: " + ", ".join(summary_parts))
199
222
 
200
223
  end_time = time.time()
201
224
  total_time = end_time - start_time
@@ -291,6 +291,8 @@ class TalksReducerGUI:
291
291
 
292
292
  self._processing_thread: Optional[threading.Thread] = None
293
293
  self._last_output: Optional[Path] = None
294
+ self._last_time_ratio: Optional[float] = None
295
+ self._last_size_ratio: Optional[float] = None
294
296
  self._status_state = "Idle"
295
297
  self.status_var = tk.StringVar(value=self._status_state)
296
298
  self._status_animation_job: Optional[str] = None
@@ -384,7 +386,7 @@ class TalksReducerGUI:
384
386
 
385
387
  self.drop_zone = self.tk.Label(
386
388
  input_frame,
387
- text="Drop files or folders here",
389
+ text="Drop video here",
388
390
  relief=self.tk.FLAT,
389
391
  borderwidth=0,
390
392
  padx=self.PADDING,
@@ -445,7 +447,9 @@ class TalksReducerGUI:
445
447
  variable=self.simple_mode_var,
446
448
  command=self._toggle_simple_mode,
447
449
  )
448
- self.simple_mode_check.grid(row=0, column=2, sticky="w", padx=(12, 0))
450
+ self.simple_mode_check.grid(
451
+ row=1, column=0, columnspan=3, sticky="w", pady=(8, 0)
452
+ )
449
453
 
450
454
  self.advanced_visible = self.tk.BooleanVar(value=False)
451
455
  self.advanced_button = self.ttk.Button(
@@ -980,7 +984,15 @@ class TalksReducerGUI:
980
984
  options = self._build_options(Path(file), args)
981
985
  result = speed_up_video(options, reporter=reporter)
982
986
  self._last_output = result.output_file
983
- self._append_log(f"Completed: {result.output_file}")
987
+ self._last_time_ratio = result.time_ratio
988
+ self._last_size_ratio = result.size_ratio
989
+
990
+ # Create completion message with ratios if available
991
+ completion_msg = f"Completed: {result.output_file}"
992
+ if result.time_ratio is not None and result.size_ratio is not None:
993
+ completion_msg += f" (Time: {result.time_ratio:.2%}, Size: {result.size_ratio:.2%})"
994
+
995
+ self._append_log(completion_msg)
984
996
  if open_after_convert:
985
997
  self._notify(
986
998
  lambda path=result.output_file: self._open_in_file_manager(
@@ -1135,17 +1147,22 @@ class TalksReducerGUI:
1135
1147
  def _update_status_from_message(self, message: str) -> None:
1136
1148
  normalized = message.strip().lower()
1137
1149
  if "all jobs finished successfully" in normalized:
1138
- self._set_status("Success")
1150
+ # Create status message with ratios if available
1151
+ status_msg = "Success"
1152
+ if self._last_time_ratio is not None and self._last_size_ratio is not None:
1153
+ status_msg = f"Time: {self._last_time_ratio:.0%}, Size: {self._last_size_ratio:.0%}"
1154
+
1155
+ self._set_status("success", status_msg)
1139
1156
  self._set_progress(100) # 100% on success
1140
1157
  self._video_duration_seconds = None # Reset for next video
1141
1158
  elif normalized.startswith("extracting audio"):
1142
- self._set_status("Extracting audio...")
1159
+ self._set_status("processing", "Extracting audio...")
1143
1160
  self._set_progress(0) # 0% on start
1144
1161
  self._video_duration_seconds = None # Reset for new processing
1145
1162
  elif normalized.startswith("starting processing") or normalized.startswith(
1146
1163
  "processing"
1147
1164
  ):
1148
- self._set_status("Processing")
1165
+ self._set_status("processing", "Processing")
1149
1166
  self._set_progress(0) # 0% on start
1150
1167
  self._video_duration_seconds = None # Reset for new processing
1151
1168
 
@@ -1174,10 +1191,12 @@ class TalksReducerGUI:
1174
1191
  percentage = min(
1175
1192
  100, int((current_seconds / self._video_duration_seconds) * 100)
1176
1193
  )
1177
- self._set_status(f"{time_str}, {speed_str}x ({percentage}%)")
1194
+ self._set_status(
1195
+ "processing", f"{time_str}, {speed_str}x ({percentage}%)"
1196
+ )
1178
1197
  self._set_progress(percentage) # Update progress bar
1179
1198
  else:
1180
- self._set_status(f"{time_str}, {speed_str}x")
1199
+ self._set_status("processing", f"{time_str}, {speed_str}x")
1181
1200
 
1182
1201
  def _apply_status_style(self, status: str) -> None:
1183
1202
  color = STATUS_COLORS.get(status.lower())
@@ -1185,30 +1204,40 @@ class TalksReducerGUI:
1185
1204
  self.status_label.configure(fg=color)
1186
1205
  else:
1187
1206
  # For extracting audio or FFmpeg progress messages, use processing color
1188
- if "extracting audio" in status.lower() or re.search(
1189
- r"\d{2}:\d{2}:\d{2}.*\d+\.?\d*x", status
1207
+ # Also handle the new "Time: X%, Size: Y%" format as success
1208
+ status_lower = status.lower()
1209
+ if (
1210
+ "extracting audio" in status_lower
1211
+ or re.search(r"\d{2}:\d{2}:\d{2}.*\d+\.?\d*x", status)
1212
+ or ("time:" in status_lower and "size:" in status_lower)
1190
1213
  ):
1191
- self.status_label.configure(fg=STATUS_COLORS["processing"])
1214
+ if "time:" in status_lower and "size:" in status_lower:
1215
+ # This is our new success format with ratios
1216
+ self.status_label.configure(fg=STATUS_COLORS["success"])
1217
+ else:
1218
+ self.status_label.configure(fg=STATUS_COLORS["processing"])
1192
1219
 
1193
- def _set_status(self, status: str) -> None:
1220
+ def _set_status(self, status: str, status_msg: str = "") -> None:
1194
1221
  def apply() -> None:
1195
- self._stop_status_animation()
1196
1222
  self._status_state = status
1197
- self.status_var.set(status)
1198
- self._apply_status_style(status)
1223
+ # Use status_msg if provided, otherwise use status
1224
+ display_text = status_msg if status_msg else status
1225
+ self.status_var.set(display_text)
1226
+ self._apply_status_style(
1227
+ status
1228
+ ) # Colors depend on status, not display text
1199
1229
  self._set_progress_bar_style(status)
1200
1230
  lowered = status.lower()
1201
1231
  is_processing = lowered == "processing" or "extracting audio" in lowered
1202
1232
 
1203
1233
  if is_processing:
1204
- self._start_status_animation()
1205
1234
  # Show stop button during processing
1206
1235
  if hasattr(self, "status_frame"):
1207
1236
  self.status_frame.grid()
1208
1237
  self.stop_button.grid()
1209
1238
  self.drop_hint_button.grid_remove()
1210
1239
 
1211
- if lowered == "success":
1240
+ if lowered == "success" or "time:" in lowered and "size:" in lowered:
1212
1241
  if self.simple_mode_var.get() and hasattr(self, "status_frame"):
1213
1242
  self.status_frame.grid()
1214
1243
  self.stop_button.grid_remove()
@@ -1232,30 +1261,6 @@ class TalksReducerGUI:
1232
1261
 
1233
1262
  self.root.after(0, apply)
1234
1263
 
1235
- def _start_status_animation(self) -> None:
1236
- self._status_animation_phase = 0
1237
- self._schedule_status_animation()
1238
-
1239
- def _schedule_status_animation(self) -> None:
1240
- if self._status_state.lower() != "processing":
1241
- return
1242
-
1243
- dots = self._status_animation_phase % 4
1244
- suffix = "." * dots
1245
- text = "Processing" + suffix
1246
- self.status_var.set(text)
1247
- self._status_animation_phase = (self._status_animation_phase + 1) % 4
1248
- self._status_animation_job = self.root.after(
1249
- 400, self._schedule_status_animation
1250
- )
1251
-
1252
- def _stop_status_animation(self) -> None:
1253
- if self._status_animation_job is not None:
1254
- self.root.after_cancel(self._status_animation_job)
1255
- self._status_animation_job = None
1256
- if self._status_state.lower() != "processing":
1257
- self.status_var.set(self._status_state)
1258
-
1259
1264
  def _calculate_gradient_color(self, percentage: int, darken: float = 1.0) -> str:
1260
1265
  """Calculate color gradient from red (0%) to green (100%).
1261
1266
 
@@ -1334,7 +1339,9 @@ class TalksReducerGUI:
1334
1339
  def updater() -> None:
1335
1340
  # Map status to progress bar style
1336
1341
  status_lower = status.lower()
1337
- if status_lower == "success":
1342
+ if status_lower == "success" or (
1343
+ "time:" in status_lower and "size:" in status_lower
1344
+ ):
1338
1345
  style = "Success.Horizontal.TProgressbar"
1339
1346
  elif status_lower == "error":
1340
1347
  style = "Error.Horizontal.TProgressbar"
@@ -36,6 +36,9 @@ class ProcessingResult:
36
36
  output_file: Path
37
37
  frame_rate: float
38
38
  original_duration: float
39
+ output_duration: float
39
40
  chunk_count: int
40
41
  used_cuda: bool
41
42
  max_audio_volume: float
43
+ time_ratio: Optional[float]
44
+ size_ratio: Optional[float]
@@ -270,12 +270,23 @@ def speed_up_video(
270
270
  finally:
271
271
  _delete_path(temp_path)
272
272
 
273
+ output_metadata = _extract_video_metadata(output_path, frame_rate)
274
+ output_duration = output_metadata.get("duration", 0.0)
275
+ time_ratio = output_duration / original_duration if original_duration > 0 else None
276
+
277
+ input_size = input_path.stat().st_size if input_path.exists() else 0
278
+ output_size = output_path.stat().st_size if output_path.exists() else 0
279
+ size_ratio = (output_size / input_size) if input_size > 0 else None
280
+
273
281
  return ProcessingResult(
274
282
  input_file=input_path,
275
283
  output_file=output_path,
276
284
  frame_rate=frame_rate,
277
285
  original_duration=original_duration,
286
+ output_duration=output_duration,
278
287
  chunk_count=len(chunks),
279
288
  used_cuda=use_cuda_encoder,
280
289
  max_audio_volume=max_audio_volume,
290
+ time_ratio=time_ratio,
291
+ size_ratio=size_ratio,
281
292
  )
@@ -0,0 +1,71 @@
1
+ Metadata-Version: 2.4
2
+ Name: talks-reducer
3
+ Version: 0.3.4
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
+ Provides-Extra: dev
18
+ Requires-Dist: build>=1.0.0; extra == "dev"
19
+ Requires-Dist: twine>=4.0.0; extra == "dev"
20
+ Requires-Dist: pytest>=7.0.0; extra == "dev"
21
+ Requires-Dist: black>=23.0.0; extra == "dev"
22
+ Requires-Dist: isort>=5.12.0; extra == "dev"
23
+ Requires-Dist: bump-my-version>=0.5.0; extra == "dev"
24
+ Requires-Dist: pyinstaller>=6.0.0; extra == "dev"
25
+ Dynamic: license-file
26
+
27
+ # Talks Reducer
28
+ Talks Reducer shortens long-form presentations by removing silent gaps and optionally re-encoding them to smaller files. The
29
+ project was renamed from **jumpcutter** to emphasize its focus on conference talks and screencasts.
30
+
31
+ ![Main demo](docs/assets/screencast-main.gif)
32
+
33
+ ## Example
34
+ - 1h 37m, 571 MB — Original OBS video recording
35
+ - 1h 19m, 751 MB — Talks Reducer
36
+ - 1h 19m, 171 MB — Talks Reducer `--small`
37
+
38
+ ## Changelog
39
+
40
+ See [CHANGELOG.md](CHANGELOG.md).
41
+
42
+ ## Install GUI (Windows, macOS)
43
+ Go to the [releases page](https://github.com/popstas/talks-reducer/releases) and download the appropriate artifact:
44
+
45
+ - **Windows** — `talks-reducer-windows.zip`
46
+ - **macOS** — `talks-reducer.app.zip` (but it doesn't work for me)
47
+
48
+ ## Install CLI (Linux, Windows, macOS)
49
+ ```
50
+ pip install talks-reducer
51
+ ```
52
+
53
+ **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.
54
+
55
+ The `--small` preset applies a 720p video scale and 128 kbps audio bitrate, making it useful for sharing talks over constrained
56
+ connections. Without `--small`, the script aims to preserve original quality while removing silence.
57
+
58
+ Example CLI usage:
59
+
60
+ ```sh
61
+ talks-reducer --small input.mp4
62
+ ```
63
+
64
+ When CUDA-capable hardware is available the pipeline leans on GPU encoders to keep export times low, but it still runs great on
65
+ CPUs.
66
+
67
+ ## Contributing
68
+ See `CONTRIBUTION.md` for development setup details and guidance on sharing improvements.
69
+
70
+ ## License
71
+ Talks Reducer is released under the MIT License. See `LICENSE` for the full text.
@@ -1,6 +1,7 @@
1
1
  LICENSE
2
2
  README.md
3
3
  pyproject.toml
4
+ talks_reducer/__about__.py
4
5
  talks_reducer/__init__.py
5
6
  talks_reducer/__main__.py
6
7
  talks_reducer/audio.py
@@ -12,4 +12,5 @@ twine>=4.0.0
12
12
  pytest>=7.0.0
13
13
  black>=23.0.0
14
14
  isort>=5.12.0
15
+ bump-my-version>=0.5.0
15
16
  pyinstaller>=6.0.0
@@ -87,13 +87,19 @@ def test_speed_up_video_returns_result(monkeypatch, tmp_path):
87
87
  monkeypatch.setattr(
88
88
  "talks_reducer.pipeline.chunk_utils.get_tree_expression", lambda _chunks: "X"
89
89
  )
90
- monkeypatch.setattr(
91
- "talks_reducer.pipeline.run_timed_ffmpeg_command", lambda *a, **k: None
92
- )
90
+
91
+ def fake_run(command, *args, **kwargs):
92
+ if command == "render":
93
+ options.output_file.write_bytes(b"fake")
94
+ return None
95
+
96
+ monkeypatch.setattr("talks_reducer.pipeline.run_timed_ffmpeg_command", fake_run)
93
97
 
94
98
  result = speed_up_video(options, reporter=reporter)
95
99
 
96
100
  assert isinstance(result, ProcessingResult)
97
101
  assert result.output_file == options.output_file
98
102
  assert result.chunk_count == 1
103
+ assert result.time_ratio == 1.0
104
+ assert result.size_ratio == 1.0
99
105
  assert reporter.messages # progress logs should be collected
@@ -1,156 +0,0 @@
1
- Metadata-Version: 2.4
2
- Name: talks-reducer
3
- Version: 0.3.2
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
- Provides-Extra: dev
18
- Requires-Dist: build>=1.0.0; extra == "dev"
19
- Requires-Dist: twine>=4.0.0; extra == "dev"
20
- Requires-Dist: pytest>=7.0.0; extra == "dev"
21
- Requires-Dist: black>=23.0.0; extra == "dev"
22
- Requires-Dist: isort>=5.12.0; extra == "dev"
23
- Requires-Dist: pyinstaller>=6.0.0; extra == "dev"
24
- Dynamic: license-file
25
-
26
- # Talks Reducer
27
- Talks Reducer shortens long-form presentations by removing silent gaps and optionally re-encoding them to smaller files. The
28
- project was renamed from **jumpcutter** to emphasize its focus on conference talks and screencasts.
29
-
30
- ## Example
31
- - 1h 37m, 571 MB — Original OBS video recording
32
- - 1h 19m, 751 MB — Talks Reducer
33
- - 1h 19m, 171 MB — Talks Reducer `--small`
34
-
35
- ## Changelog
36
-
37
- See [CHANGELOG.md](CHANGELOG.md).
38
-
39
- ## Install GUI (Windows, macOS)
40
- Go to the [releases page](https://github.com/popstas/talks-reducer/releases) and download the appropriate artifact:
41
-
42
- - **Windows** — `talks-reducer-gui.exe`
43
- - **macOS** — `talks-reducer-gui-macos-universal` (requires macOS 10.13 High Sierra or
44
- newer). The bundle is built as a universal (`x86_64` + `arm64`) app so it runs
45
- natively on Apple Silicon without Rosetta.
46
-
47
- ## Install CLI (Linux, Windows, macOS)
48
- ```
49
- pip install talks-reducer
50
- ```
51
-
52
- **Note:** FFmpeg is now bundled automatically with the package, so you don't need to install it separately. However, if you have FFmpeg already installed on your system, it will be used instead of the bundled version.
53
-
54
- The `--small` preset applies a 720p video scale and 128 kbps audio bitrate, making it useful for sharing talks over constrained
55
- connections. Without `--small`, the script aims to preserve original quality while removing silence.
56
-
57
- > **Tip:** The `talks-reducer` and `talks-reducer-gui` commands now behave the same way: launching them without arguments opens
58
- > the Tkinter interface, while passing regular CLI options (for example, `talks-reducer --small input.mp4`) executes the
59
- > command-line pipeline. You can keep a single shortcut for both workflows.
60
-
61
- When CUDA-capable hardware is available the pipeline leans on GPU encoders to keep export times low, but it still runs great on
62
- CPUs.
63
-
64
- ### macOS codesigning and notarization
65
-
66
- Maintainers with Apple Developer credentials can optionally sign and notarize
67
- the GUI release to avoid Gatekeeper warnings on download:
68
-
69
- 1. Export or create a keychain profile for `notarytool` (see `man
70
- notarytool`) and note the profile name.
71
- 2. Set the following environment variables before running `scripts/build-gui.sh`:
72
- - `MACOS_CODESIGN_IDENTITY` — the signing identity, for example
73
- `Developer ID Application: Example Corp (TEAMID)`.
74
- - `MACOS_CODESIGN_ENTITLEMENTS` *(optional)* — path to an entitlements plist
75
- used during codesigning.
76
- - `MACOS_NOTARIZE_PROFILE` *(optional)* — the keychain profile name to submit
77
- the archive for notarization. When present, the script zips the `.app`,
78
- submits it with `notarytool --wait`, and staples the returned ticket.
79
-
80
- The codesigning step executes only when the variables are provided, so the build
81
- continues to work unchanged for local development.
82
-
83
- ### Graphical Interface
84
-
85
- - **Simple mode** — the default experience shrinks the window to a large drop
86
- zone, hides the manual run controls and log, and automatically processes new
87
- files as soon as you drop them. Uncheck the box to return to the full layout
88
- with file pickers, the Run button, and detailed logging.
89
- - **Input drop zone** — drag files or folders from your desktop, click to open
90
- the system file picker, or add them via the Explorer/Finder dialog; duplicates
91
- are ignored.
92
- - **Small video** — toggles the `--small` preset used by the CLI.
93
- - **Open after convert** — controls whether the exported file is revealed in
94
- your system file manager as soon as each job finishes.
95
- - **Advanced** — reveals optional controls for the output path, temp folder,
96
- timing/audio knobs mirrored from the command line, and an appearance picker
97
- that can force dark or light mode or follow your operating system.
98
-
99
- Progress updates stream into the 10-line log panel while the processing runs in
100
- a background thread. Once every queued job succeeds an **Open last output**
101
- button appears so you can jump straight to the exported file in your system
102
- file manager.
103
-
104
- The GUI stores your last-used Simple mode, Small video, Open after convert, and
105
- theme preferences in a cross-platform configuration file so they persist across
106
- launches.
107
-
108
- ## Repository Structure
109
- - `talks_reducer/` — Python package that exposes the CLI and reusable pipeline:
110
- - `cli.py` parses arguments and dispatches to the pipeline.
111
- - `pipeline.py` orchestrates FFmpeg, audio processing, and temporary assets.
112
- - `audio.py` handles audio validation, volume analysis, and phase vocoder processing.
113
- - `chunks.py` builds timing metadata and FFmpeg expressions for frame selection.
114
- - `ffmpeg.py` discovers the FFmpeg binary, checks CUDA availability, and assembles command strings.
115
- - `requirements.txt` — Python dependencies for local development.
116
- - `default.nix` — reproducible environment definition for Nix users.
117
- - `CONTRIBUTION.md` — development workflow, formatting expectations, and release checklist.
118
- - `AGENTS.md` — maintainer tips and coding conventions for this repository.
119
-
120
- ## Highlights
121
- - Builds on gegell's classic jumpcutter workflow with more efficient frame and audio processing
122
- - Generates FFmpeg filter graphs instead of writing temporary frames to disk
123
- - Streams audio transformations in memory to avoid slow intermediate files
124
- - Accepts multiple inputs or directories of recordings in a single run
125
- - Provides progress feedback via `tqdm`
126
- - Automatically detects NVENC availability, so you no longer need to pass `--cuda`
127
-
128
- ## Processing Pipeline
129
- 1. Validate that each input file contains an audio stream using `ffprobe`.
130
- 2. Extract audio and calculate loudness to identify silent regions.
131
- 3. Stretch the non-silent segments with `audiotsm` to maintain speech clarity.
132
- 4. Stitch the processed audio and video together with FFmpeg, using NVENC if the GPU encoders are detected.
133
-
134
- ## Recent Updates
135
- - **October 2025** — Project renamed to *Talks Reducer* across documentation and scripts.
136
- - **October 2025** — Added `--small` preset with 720p/128 kbps defaults for bandwidth-friendly exports.
137
- - **October 2025** — Removed the `--cuda` flag; CUDA/NVENC support is now auto-detected.
138
-
139
- ## Changelog
140
- Major and minor releases are tracked in `CHANGELOG.md`. The log is generated from
141
- Conventional Commits that start with either `feat:` or `fix:`. Only tags in the
142
- form `v<major>.<minor>.0` are included so patch releases (for example,
143
- `v1.1.1`) are omitted. Regenerate the file whenever you cut a release:
144
-
145
- ```bash
146
- python scripts/generate_changelog.py
147
- ```
148
-
149
- CI will fail if the generated changelog does not match the committed version, so
150
- run the script before opening a pull request that updates release tags.
151
-
152
- ## Contributing
153
- See `CONTRIBUTION.md` for development setup details and guidance on sharing improvements.
154
-
155
- ## License
156
- Talks Reducer is released under the MIT License. See `LICENSE` for the full text.
@@ -1,131 +0,0 @@
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
- ## Example
6
- - 1h 37m, 571 MB — Original OBS video recording
7
- - 1h 19m, 751 MB — Talks Reducer
8
- - 1h 19m, 171 MB — Talks Reducer `--small`
9
-
10
- ## Changelog
11
-
12
- See [CHANGELOG.md](CHANGELOG.md).
13
-
14
- ## Install GUI (Windows, macOS)
15
- Go to the [releases page](https://github.com/popstas/talks-reducer/releases) and download the appropriate artifact:
16
-
17
- - **Windows** — `talks-reducer-gui.exe`
18
- - **macOS** — `talks-reducer-gui-macos-universal` (requires macOS 10.13 High Sierra or
19
- newer). The bundle is built as a universal (`x86_64` + `arm64`) app so it runs
20
- natively on Apple Silicon without Rosetta.
21
-
22
- ## Install CLI (Linux, Windows, macOS)
23
- ```
24
- pip install talks-reducer
25
- ```
26
-
27
- **Note:** FFmpeg is now bundled automatically with the package, so you don't need to install it separately. However, if you have FFmpeg already installed on your system, it will be used instead of the bundled version.
28
-
29
- The `--small` preset applies a 720p video scale and 128 kbps audio bitrate, making it useful for sharing talks over constrained
30
- connections. Without `--small`, the script aims to preserve original quality while removing silence.
31
-
32
- > **Tip:** The `talks-reducer` and `talks-reducer-gui` commands now behave the same way: launching them without arguments opens
33
- > the Tkinter interface, while passing regular CLI options (for example, `talks-reducer --small input.mp4`) executes the
34
- > command-line pipeline. You can keep a single shortcut for both workflows.
35
-
36
- When CUDA-capable hardware is available the pipeline leans on GPU encoders to keep export times low, but it still runs great on
37
- CPUs.
38
-
39
- ### macOS codesigning and notarization
40
-
41
- Maintainers with Apple Developer credentials can optionally sign and notarize
42
- the GUI release to avoid Gatekeeper warnings on download:
43
-
44
- 1. Export or create a keychain profile for `notarytool` (see `man
45
- notarytool`) and note the profile name.
46
- 2. Set the following environment variables before running `scripts/build-gui.sh`:
47
- - `MACOS_CODESIGN_IDENTITY` — the signing identity, for example
48
- `Developer ID Application: Example Corp (TEAMID)`.
49
- - `MACOS_CODESIGN_ENTITLEMENTS` *(optional)* — path to an entitlements plist
50
- used during codesigning.
51
- - `MACOS_NOTARIZE_PROFILE` *(optional)* — the keychain profile name to submit
52
- the archive for notarization. When present, the script zips the `.app`,
53
- submits it with `notarytool --wait`, and staples the returned ticket.
54
-
55
- The codesigning step executes only when the variables are provided, so the build
56
- continues to work unchanged for local development.
57
-
58
- ### Graphical Interface
59
-
60
- - **Simple mode** — the default experience shrinks the window to a large drop
61
- zone, hides the manual run controls and log, and automatically processes new
62
- files as soon as you drop them. Uncheck the box to return to the full layout
63
- with file pickers, the Run button, and detailed logging.
64
- - **Input drop zone** — drag files or folders from your desktop, click to open
65
- the system file picker, or add them via the Explorer/Finder dialog; duplicates
66
- are ignored.
67
- - **Small video** — toggles the `--small` preset used by the CLI.
68
- - **Open after convert** — controls whether the exported file is revealed in
69
- your system file manager as soon as each job finishes.
70
- - **Advanced** — reveals optional controls for the output path, temp folder,
71
- timing/audio knobs mirrored from the command line, and an appearance picker
72
- that can force dark or light mode or follow your operating system.
73
-
74
- Progress updates stream into the 10-line log panel while the processing runs in
75
- a background thread. Once every queued job succeeds an **Open last output**
76
- button appears so you can jump straight to the exported file in your system
77
- file manager.
78
-
79
- The GUI stores your last-used Simple mode, Small video, Open after convert, and
80
- theme preferences in a cross-platform configuration file so they persist across
81
- launches.
82
-
83
- ## Repository Structure
84
- - `talks_reducer/` — Python package that exposes the CLI and reusable pipeline:
85
- - `cli.py` parses arguments and dispatches to the pipeline.
86
- - `pipeline.py` orchestrates FFmpeg, audio processing, and temporary assets.
87
- - `audio.py` handles audio validation, volume analysis, and phase vocoder processing.
88
- - `chunks.py` builds timing metadata and FFmpeg expressions for frame selection.
89
- - `ffmpeg.py` discovers the FFmpeg binary, checks CUDA availability, and assembles command strings.
90
- - `requirements.txt` — Python dependencies for local development.
91
- - `default.nix` — reproducible environment definition for Nix users.
92
- - `CONTRIBUTION.md` — development workflow, formatting expectations, and release checklist.
93
- - `AGENTS.md` — maintainer tips and coding conventions for this repository.
94
-
95
- ## Highlights
96
- - Builds on gegell's classic jumpcutter workflow with more efficient frame and audio processing
97
- - Generates FFmpeg filter graphs instead of writing temporary frames to disk
98
- - Streams audio transformations in memory to avoid slow intermediate files
99
- - Accepts multiple inputs or directories of recordings in a single run
100
- - Provides progress feedback via `tqdm`
101
- - Automatically detects NVENC availability, so you no longer need to pass `--cuda`
102
-
103
- ## Processing Pipeline
104
- 1. Validate that each input file contains an audio stream using `ffprobe`.
105
- 2. Extract audio and calculate loudness to identify silent regions.
106
- 3. Stretch the non-silent segments with `audiotsm` to maintain speech clarity.
107
- 4. Stitch the processed audio and video together with FFmpeg, using NVENC if the GPU encoders are detected.
108
-
109
- ## Recent Updates
110
- - **October 2025** — Project renamed to *Talks Reducer* across documentation and scripts.
111
- - **October 2025** — Added `--small` preset with 720p/128 kbps defaults for bandwidth-friendly exports.
112
- - **October 2025** — Removed the `--cuda` flag; CUDA/NVENC support is now auto-detected.
113
-
114
- ## Changelog
115
- Major and minor releases are tracked in `CHANGELOG.md`. The log is generated from
116
- Conventional Commits that start with either `feat:` or `fix:`. Only tags in the
117
- form `v<major>.<minor>.0` are included so patch releases (for example,
118
- `v1.1.1`) are omitted. Regenerate the file whenever you cut a release:
119
-
120
- ```bash
121
- python scripts/generate_changelog.py
122
- ```
123
-
124
- CI will fail if the generated changelog does not match the committed version, so
125
- run the script before opening a pull request that updates release tags.
126
-
127
- ## Contributing
128
- See `CONTRIBUTION.md` for development setup details and guidance on sharing improvements.
129
-
130
- ## License
131
- Talks Reducer is released under the MIT License. See `LICENSE` for the full text.
@@ -1,156 +0,0 @@
1
- Metadata-Version: 2.4
2
- Name: talks-reducer
3
- Version: 0.3.2
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
- Provides-Extra: dev
18
- Requires-Dist: build>=1.0.0; extra == "dev"
19
- Requires-Dist: twine>=4.0.0; extra == "dev"
20
- Requires-Dist: pytest>=7.0.0; extra == "dev"
21
- Requires-Dist: black>=23.0.0; extra == "dev"
22
- Requires-Dist: isort>=5.12.0; extra == "dev"
23
- Requires-Dist: pyinstaller>=6.0.0; extra == "dev"
24
- Dynamic: license-file
25
-
26
- # Talks Reducer
27
- Talks Reducer shortens long-form presentations by removing silent gaps and optionally re-encoding them to smaller files. The
28
- project was renamed from **jumpcutter** to emphasize its focus on conference talks and screencasts.
29
-
30
- ## Example
31
- - 1h 37m, 571 MB — Original OBS video recording
32
- - 1h 19m, 751 MB — Talks Reducer
33
- - 1h 19m, 171 MB — Talks Reducer `--small`
34
-
35
- ## Changelog
36
-
37
- See [CHANGELOG.md](CHANGELOG.md).
38
-
39
- ## Install GUI (Windows, macOS)
40
- Go to the [releases page](https://github.com/popstas/talks-reducer/releases) and download the appropriate artifact:
41
-
42
- - **Windows** — `talks-reducer-gui.exe`
43
- - **macOS** — `talks-reducer-gui-macos-universal` (requires macOS 10.13 High Sierra or
44
- newer). The bundle is built as a universal (`x86_64` + `arm64`) app so it runs
45
- natively on Apple Silicon without Rosetta.
46
-
47
- ## Install CLI (Linux, Windows, macOS)
48
- ```
49
- pip install talks-reducer
50
- ```
51
-
52
- **Note:** FFmpeg is now bundled automatically with the package, so you don't need to install it separately. However, if you have FFmpeg already installed on your system, it will be used instead of the bundled version.
53
-
54
- The `--small` preset applies a 720p video scale and 128 kbps audio bitrate, making it useful for sharing talks over constrained
55
- connections. Without `--small`, the script aims to preserve original quality while removing silence.
56
-
57
- > **Tip:** The `talks-reducer` and `talks-reducer-gui` commands now behave the same way: launching them without arguments opens
58
- > the Tkinter interface, while passing regular CLI options (for example, `talks-reducer --small input.mp4`) executes the
59
- > command-line pipeline. You can keep a single shortcut for both workflows.
60
-
61
- When CUDA-capable hardware is available the pipeline leans on GPU encoders to keep export times low, but it still runs great on
62
- CPUs.
63
-
64
- ### macOS codesigning and notarization
65
-
66
- Maintainers with Apple Developer credentials can optionally sign and notarize
67
- the GUI release to avoid Gatekeeper warnings on download:
68
-
69
- 1. Export or create a keychain profile for `notarytool` (see `man
70
- notarytool`) and note the profile name.
71
- 2. Set the following environment variables before running `scripts/build-gui.sh`:
72
- - `MACOS_CODESIGN_IDENTITY` — the signing identity, for example
73
- `Developer ID Application: Example Corp (TEAMID)`.
74
- - `MACOS_CODESIGN_ENTITLEMENTS` *(optional)* — path to an entitlements plist
75
- used during codesigning.
76
- - `MACOS_NOTARIZE_PROFILE` *(optional)* — the keychain profile name to submit
77
- the archive for notarization. When present, the script zips the `.app`,
78
- submits it with `notarytool --wait`, and staples the returned ticket.
79
-
80
- The codesigning step executes only when the variables are provided, so the build
81
- continues to work unchanged for local development.
82
-
83
- ### Graphical Interface
84
-
85
- - **Simple mode** — the default experience shrinks the window to a large drop
86
- zone, hides the manual run controls and log, and automatically processes new
87
- files as soon as you drop them. Uncheck the box to return to the full layout
88
- with file pickers, the Run button, and detailed logging.
89
- - **Input drop zone** — drag files or folders from your desktop, click to open
90
- the system file picker, or add them via the Explorer/Finder dialog; duplicates
91
- are ignored.
92
- - **Small video** — toggles the `--small` preset used by the CLI.
93
- - **Open after convert** — controls whether the exported file is revealed in
94
- your system file manager as soon as each job finishes.
95
- - **Advanced** — reveals optional controls for the output path, temp folder,
96
- timing/audio knobs mirrored from the command line, and an appearance picker
97
- that can force dark or light mode or follow your operating system.
98
-
99
- Progress updates stream into the 10-line log panel while the processing runs in
100
- a background thread. Once every queued job succeeds an **Open last output**
101
- button appears so you can jump straight to the exported file in your system
102
- file manager.
103
-
104
- The GUI stores your last-used Simple mode, Small video, Open after convert, and
105
- theme preferences in a cross-platform configuration file so they persist across
106
- launches.
107
-
108
- ## Repository Structure
109
- - `talks_reducer/` — Python package that exposes the CLI and reusable pipeline:
110
- - `cli.py` parses arguments and dispatches to the pipeline.
111
- - `pipeline.py` orchestrates FFmpeg, audio processing, and temporary assets.
112
- - `audio.py` handles audio validation, volume analysis, and phase vocoder processing.
113
- - `chunks.py` builds timing metadata and FFmpeg expressions for frame selection.
114
- - `ffmpeg.py` discovers the FFmpeg binary, checks CUDA availability, and assembles command strings.
115
- - `requirements.txt` — Python dependencies for local development.
116
- - `default.nix` — reproducible environment definition for Nix users.
117
- - `CONTRIBUTION.md` — development workflow, formatting expectations, and release checklist.
118
- - `AGENTS.md` — maintainer tips and coding conventions for this repository.
119
-
120
- ## Highlights
121
- - Builds on gegell's classic jumpcutter workflow with more efficient frame and audio processing
122
- - Generates FFmpeg filter graphs instead of writing temporary frames to disk
123
- - Streams audio transformations in memory to avoid slow intermediate files
124
- - Accepts multiple inputs or directories of recordings in a single run
125
- - Provides progress feedback via `tqdm`
126
- - Automatically detects NVENC availability, so you no longer need to pass `--cuda`
127
-
128
- ## Processing Pipeline
129
- 1. Validate that each input file contains an audio stream using `ffprobe`.
130
- 2. Extract audio and calculate loudness to identify silent regions.
131
- 3. Stretch the non-silent segments with `audiotsm` to maintain speech clarity.
132
- 4. Stitch the processed audio and video together with FFmpeg, using NVENC if the GPU encoders are detected.
133
-
134
- ## Recent Updates
135
- - **October 2025** — Project renamed to *Talks Reducer* across documentation and scripts.
136
- - **October 2025** — Added `--small` preset with 720p/128 kbps defaults for bandwidth-friendly exports.
137
- - **October 2025** — Removed the `--cuda` flag; CUDA/NVENC support is now auto-detected.
138
-
139
- ## Changelog
140
- Major and minor releases are tracked in `CHANGELOG.md`. The log is generated from
141
- Conventional Commits that start with either `feat:` or `fix:`. Only tags in the
142
- form `v<major>.<minor>.0` are included so patch releases (for example,
143
- `v1.1.1`) are omitted. Regenerate the file whenever you cut a release:
144
-
145
- ```bash
146
- python scripts/generate_changelog.py
147
- ```
148
-
149
- CI will fail if the generated changelog does not match the committed version, so
150
- run the script before opening a pull request that updates release tags.
151
-
152
- ## Contributing
153
- See `CONTRIBUTION.md` for development setup details and guidance on sharing improvements.
154
-
155
- ## License
156
- Talks Reducer is released under the MIT License. See `LICENSE` for the full text.
File without changes