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.
- {better_ffmpeg_progress-2.3.0 → better_ffmpeg_progress-2.3.1}/PKG-INFO +3 -1
- {better_ffmpeg_progress-2.3.0 → better_ffmpeg_progress-2.3.1}/README.md +2 -1
- {better_ffmpeg_progress-2.3.0 → better_ffmpeg_progress-2.3.1}/better_ffmpeg_progress/better_ffmpeg_progress.py +53 -28
- {better_ffmpeg_progress-2.3.0 → better_ffmpeg_progress-2.3.1}/better_ffmpeg_progress.egg-info/PKG-INFO +3 -1
- {better_ffmpeg_progress-2.3.0 → better_ffmpeg_progress-2.3.1}/better_ffmpeg_progress.egg-info/requires.txt +1 -0
- {better_ffmpeg_progress-2.3.0 → better_ffmpeg_progress-2.3.1}/setup.py +2 -2
- {better_ffmpeg_progress-2.3.0 → better_ffmpeg_progress-2.3.1}/LICENSE +0 -0
- {better_ffmpeg_progress-2.3.0 → better_ffmpeg_progress-2.3.1}/better_ffmpeg_progress/__init__.py +0 -0
- {better_ffmpeg_progress-2.3.0 → better_ffmpeg_progress-2.3.1}/better_ffmpeg_progress.egg-info/SOURCES.txt +0 -0
- {better_ffmpeg_progress-2.3.0 → better_ffmpeg_progress-2.3.1}/better_ffmpeg_progress.egg-info/dependency_links.txt +0 -0
- {better_ffmpeg_progress-2.3.0 → better_ffmpeg_progress-2.3.1}/better_ffmpeg_progress.egg-info/top_level.txt +0 -0
- {better_ffmpeg_progress-2.3.0 → better_ffmpeg_progress-2.3.1}/setup.cfg +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.1
|
|
2
2
|
Name: better-ffmpeg-progress
|
|
3
|
-
Version: 2.3.
|
|
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
|
-
|
|
191
|
-
|
|
192
|
-
|
|
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
|
|
198
|
-
|
|
205
|
+
if stdout:
|
|
206
|
+
metric, value = stdout.split("=")
|
|
199
207
|
|
|
200
208
|
if (
|
|
201
|
-
metric
|
|
202
|
-
and
|
|
203
|
-
and
|
|
209
|
+
metric in self.WANTED_METRICS
|
|
210
|
+
and value
|
|
211
|
+
and "N/A" not in value
|
|
204
212
|
):
|
|
205
|
-
|
|
206
|
-
|
|
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
|
-
|
|
214
|
-
|
|
215
|
-
|
|
216
|
-
|
|
217
|
-
|
|
218
|
-
|
|
219
|
-
|
|
220
|
-
|
|
221
|
-
|
|
222
|
-
|
|
223
|
-
|
|
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.
|
|
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.
|
|
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=[
|
|
File without changes
|
{better_ffmpeg_progress-2.3.0 → better_ffmpeg_progress-2.3.1}/better_ffmpeg_progress/__init__.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|