better-ffmpeg-progress 2.3.0__tar.gz → 2.3.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.
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: better-ffmpeg-progress
3
- Version: 2.3.0
3
+ Version: 2.3.1
4
4
  Summary: Run FFmpeg & see percentage progress + ETA.
5
5
  Home-page: https://github.com/CrypticSignal/better-ffmpeg-progress
6
6
  Author: GitHub.com/CrypticSignal
@@ -13,6 +13,7 @@ Requires-Python: >=3.7
13
13
  Description-Content-Type: text/markdown
14
14
  License-File: LICENSE
15
15
  Requires-Dist: ffmpeg-python
16
+ Requires-Dist: psutil
16
17
  Requires-Dist: rich
17
18
 
18
19
  <div align="center">
@@ -166,3 +167,4 @@ The `run` method takes the following **optional** arguments:
166
167
 
167
168
  [29/10/2024]
168
169
  - [v2.3.0] Set `shell=True` to support piping.
170
+ - [v2.3.1] Kill FFmpeg process(es) on KeyboardInterrupt
@@ -148,4 +148,5 @@ The `run` method takes the following **optional** arguments:
148
148
  - [v2.2.2] Make printing the detected duration of the input file optional.
149
149
 
150
150
  [29/10/2024]
151
- - [v2.3.0] Set `shell=True` to support piping.
151
+ - [v2.3.0] Set `shell=True` to support piping.
152
+ - [v2.3.1] Kill FFmpeg process(es) on KeyboardInterrupt
@@ -1,4 +1,5 @@
1
1
  from dataclasses import dataclass
2
+ import os
2
3
  from pathlib import Path
3
4
  from queue import Empty, Queue
4
5
  import subprocess
@@ -7,6 +8,7 @@ from threading import Thread
7
8
  from typing import Callable, List, Optional, Union
8
9
 
9
10
  from ffmpeg import probe
11
+ import psutil
10
12
  from rich.progress import (
11
13
  Progress,
12
14
  TextColumn,
@@ -171,12 +173,20 @@ class FfmpegProcess:
171
173
  task_id: Optional[int],
172
174
  progress_handler: Optional[Callable],
173
175
  ) -> None:
176
+ # Windows
177
+ if os.name == "nt":
178
+ creationflags = subprocess.CREATE_NEW_PROCESS_GROUP
179
+ # macOS and Linux
180
+ else:
181
+ creationflags = 0
182
+
174
183
  process = subprocess.Popen(
175
184
  self._ffmpeg_args,
176
185
  stdout=subprocess.PIPE,
177
186
  stderr=subprocess.PIPE,
178
187
  text=True,
179
188
  shell=True,
189
+ creationflags=creationflags,
180
190
  )
181
191
 
182
192
  stdout_queue, stderr_queue = Queue(), Queue()
@@ -187,40 +197,45 @@ class FfmpegProcess:
187
197
  target=self._handle_pipe, args=(process.stderr, stderr_queue), daemon=True
188
198
  ).start()
189
199
 
190
- while process.poll() is None:
191
- try:
192
- stdout = stdout_queue.get_nowait()
193
-
194
- if stdout:
195
- metric, value = stdout.split("=")
200
+ try:
201
+ while process.poll() is None:
202
+ try:
203
+ stdout = stdout_queue.get_nowait()
196
204
 
197
- if metric in self.WANTED_METRICS and value and "N/A" not in value:
198
- self._update_metrics(stdout, metric, value, progress_handler)
205
+ if stdout:
206
+ metric, value = stdout.split("=")
199
207
 
200
208
  if (
201
- metric == "out_time_ms"
202
- and progress_bar
203
- and task_id is not None
209
+ metric in self.WANTED_METRICS
210
+ and value
211
+ and "N/A" not in value
204
212
  ):
205
- progress_bar.update(
206
- task_id,
207
- completed=self._metrics.seconds_processed,
208
- speed=self._metrics.speed,
213
+ self._update_metrics(
214
+ stdout, metric, value, progress_handler
209
215
  )
210
- except Empty:
211
- pass
212
216
 
213
- try:
214
- stderr = stderr_queue.get_nowait()
215
-
216
- if "No such file" in stderr:
217
- raise FileNotFoundError(
218
- f"Input file not found: {self._input_filepath}"
219
- )
220
-
221
- self._ffmpeg_stderr.append(stderr)
222
- except Empty:
223
- pass
217
+ if (
218
+ metric == "out_time_ms"
219
+ and progress_bar
220
+ and task_id is not None
221
+ ):
222
+ progress_bar.update(
223
+ task_id,
224
+ completed=self._metrics.seconds_processed,
225
+ speed=self._metrics.speed,
226
+ )
227
+ except Empty:
228
+ pass
229
+
230
+ try:
231
+ stderr = stderr_queue.get_nowait()
232
+ self._ffmpeg_stderr.append(stderr)
233
+ except Empty:
234
+ pass
235
+
236
+ except KeyboardInterrupt:
237
+ self._kill_process_and_children(process.pid)
238
+ sys.exit("[KeyboardInterrupt] FFmpeg process(es) killed.")
224
239
 
225
240
  return process.returncode
226
241
 
@@ -300,3 +315,13 @@ class FfmpegProcess:
300
315
  success_handler()
301
316
  else:
302
317
  print("FFmpeg process completed.")
318
+
319
+ def _kill_process_and_children(self, proc_pid):
320
+ try:
321
+ process = psutil.Process(proc_pid)
322
+ for child in process.children(recursive=True):
323
+ child.terminate()
324
+ # Terminate the main process
325
+ process.terminate()
326
+ except psutil.NoSuchProcess:
327
+ pass
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: better-ffmpeg-progress
3
- Version: 2.3.0
3
+ Version: 2.3.1
4
4
  Summary: Run FFmpeg & see percentage progress + ETA.
5
5
  Home-page: https://github.com/CrypticSignal/better-ffmpeg-progress
6
6
  Author: GitHub.com/CrypticSignal
@@ -13,6 +13,7 @@ Requires-Python: >=3.7
13
13
  Description-Content-Type: text/markdown
14
14
  License-File: LICENSE
15
15
  Requires-Dist: ffmpeg-python
16
+ Requires-Dist: psutil
16
17
  Requires-Dist: rich
17
18
 
18
19
  <div align="center">
@@ -166,3 +167,4 @@ The `run` method takes the following **optional** arguments:
166
167
 
167
168
  [29/10/2024]
168
169
  - [v2.3.0] Set `shell=True` to support piping.
170
+ - [v2.3.1] Kill FFmpeg process(es) on KeyboardInterrupt
@@ -5,7 +5,7 @@ with open("README.md", "r", encoding="utf-8") as f:
5
5
 
6
6
  setuptools.setup(
7
7
  name="better-ffmpeg-progress",
8
- version="2.3.0",
8
+ version="2.3.1",
9
9
  author="GitHub.com/CrypticSignal",
10
10
  author_email="theaudiophile@outlook.com",
11
11
  description="Run FFmpeg & see percentage progress + ETA.",
@@ -13,7 +13,7 @@ setuptools.setup(
13
13
  long_description_content_type="text/markdown",
14
14
  url="https://github.com/CrypticSignal/better-ffmpeg-progress",
15
15
  packages=["better_ffmpeg_progress"],
16
- install_requires=["ffmpeg-python", "rich"],
16
+ install_requires=["ffmpeg-python", "psutil", "rich"],
17
17
  python_requires=">=3.7",
18
18
  keywords=["ffmpeg", "progress"],
19
19
  classifiers=[