better-ffmpeg-progress 2.5.3__tar.gz → 2.5.5__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.5.3
3
+ Version: 2.5.5
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
@@ -171,3 +171,5 @@ The `run` method takes the following **optional** arguments:
171
171
  [12/11/2024]
172
172
  - [v2.5.2] Drain any remaining FFmpeg stderr after the process ends.
173
173
  - [v2.5.3] Write FFmpeg stderr to the log file in real time.
174
+ - [v2.5.4] Include progress info in stderr if the duration of the input file cannot be detected.
175
+ - [v2.5.5] Print detected errors in the terminal and only set `shell=True` if shell operators are detected.
@@ -152,4 +152,6 @@ The `run` method takes the following **optional** arguments:
152
152
 
153
153
  [12/11/2024]
154
154
  - [v2.5.2] Drain any remaining FFmpeg stderr after the process ends.
155
- - [v2.5.3] Write FFmpeg stderr to the log file in real time.
155
+ - [v2.5.3] Write FFmpeg stderr to the log file in real time.
156
+ - [v2.5.4] Include progress info in stderr if the duration of the input file cannot be detected.
157
+ - [v2.5.5] Print detected errors in the terminal and only set `shell=True` if shell operators are detected.
@@ -58,8 +58,6 @@ class FfmpegProcess:
58
58
 
59
59
  # -progress pipe:1 sends progress metrics to stdout
60
60
  # -stats_period sets the period at which encoding progress/statistics are updated
61
- # -nostats ensures that progress information is not sent to stderr as this info is not needed in the log file, e.g.
62
- # frame= 1381 fps=254 q=18.0 size= 46592KiB time=00:00:46.07 bitrate=8283.1kbits/s speed=8.47x
63
61
  command.extend(
64
62
  [
65
63
  "-loglevel",
@@ -68,7 +66,6 @@ class FfmpegProcess:
68
66
  "pipe:1",
69
67
  "-stats_period",
70
68
  "0.1",
71
- "-nostats",
72
69
  ]
73
70
  )
74
71
 
@@ -80,6 +77,7 @@ class FfmpegProcess:
80
77
  self._duration_secs: Optional[float] = None
81
78
  self._current_size: int = 0
82
79
  self._ffmpeg_log_file: Optional[Path] = None
80
+ self._error_messages: list[str] = []
83
81
 
84
82
  self._get_input_file_duration()
85
83
 
@@ -97,6 +95,9 @@ class FfmpegProcess:
97
95
  print(
98
96
  f"The duration of {self._input_filepath.name} has been detected as {self._duration_secs} seconds"
99
97
  )
98
+ # -nostats ensures that progress information is not sent to stderr as this info is not needed in the log file, e.g.
99
+ # frame= 1381 fps=254 q=18.0 size= 46592KiB time=00:00:46.07 bitrate=8283.1kbits/s speed=8.47x
100
+ self._ffmpeg_command.extend(["-nostats"])
100
101
  except Exception:
101
102
  print(
102
103
  f"Could not detect the duration of '{self._input_filepath.name}'. Percentage progress, ETA and estimated filesize will be unavailable.\n",
@@ -166,6 +167,11 @@ class FfmpegProcess:
166
167
  finally:
167
168
  pipe.close()
168
169
 
170
+ def _contains_shell_operators(self, command: List[str]) -> bool:
171
+ """Check if the command contains shell operators."""
172
+ shell_operators = {"|", ">", "<", ">>", "&&", "||"}
173
+ return any(op in command for op in shell_operators)
174
+
169
175
  def _start_process(
170
176
  self,
171
177
  progress_bar: Optional[Progress],
@@ -174,16 +180,22 @@ class FfmpegProcess:
174
180
  ) -> int:
175
181
  creationflags = subprocess.CREATE_NEW_PROCESS_GROUP if os.name == "nt" else 0
176
182
 
183
+ # If command contains shell operators, turn the list into a string.
184
+ if self._contains_shell_operators(self._ffmpeg_command):
185
+ final_command = " ".join(self._ffmpeg_command)
186
+ else:
187
+ final_command = self._ffmpeg_command
188
+
177
189
  self._write_to_log_file(
178
- f"This file contains the log for the following command:\n{' '.join(self._ffmpeg_command)}\n",
190
+ f"This file contains the log for the following command:\n{final_command if isinstance(final_command, str) else ' '.join(final_command)}\n",
179
191
  )
180
192
 
181
193
  process = subprocess.Popen(
182
- self._ffmpeg_command,
194
+ final_command,
183
195
  stdout=subprocess.PIPE,
184
196
  stderr=subprocess.PIPE,
185
197
  text=True,
186
- shell=True,
198
+ shell=isinstance(final_command, str),
187
199
  creationflags=creationflags,
188
200
  )
189
201
 
@@ -195,15 +207,22 @@ class FfmpegProcess:
195
207
  target=self._handle_pipe, args=(process.stderr, stderr_queue), daemon=True
196
208
  ).start()
197
209
 
210
+ error_words = [
211
+ "error",
212
+ "failed",
213
+ "invalid",
214
+ "trailing",
215
+ "unable",
216
+ "unknown",
217
+ ]
218
+
198
219
  try:
199
220
  while process.poll() is None:
200
221
  if self._duration_secs is not None:
201
222
  try:
202
223
  stdout = stdout_queue.get_nowait()
203
-
204
224
  if stdout:
205
225
  metric, value = stdout.split("=")
206
-
207
226
  if (
208
227
  metric in self.WANTED_METRICS
209
228
  and value
@@ -212,7 +231,6 @@ class FfmpegProcess:
212
231
  self._update_metrics(
213
232
  stdout, metric, value, progress_handler
214
233
  )
215
-
216
234
  if (
217
235
  metric == "out_time_ms"
218
236
  and progress_bar
@@ -228,10 +246,12 @@ class FfmpegProcess:
228
246
 
229
247
  try:
230
248
  stderr = stderr_queue.get_nowait()
231
-
232
249
  if stderr:
233
250
  self._write_to_log_file(stderr)
234
251
 
252
+ if any(keyword in stderr.lower() for keyword in error_words):
253
+ self._error_messages.append(stderr)
254
+
235
255
  if self._duration_secs is None:
236
256
  print(
237
257
  stderr,
@@ -252,10 +272,12 @@ class FfmpegProcess:
252
272
  while True:
253
273
  try:
254
274
  stderr = stderr_queue.get_nowait()
255
-
256
275
  if stderr:
257
276
  self._write_to_log_file(stderr)
258
277
 
278
+ if any(keyword in stderr.lower() for keyword in error_words):
279
+ self._error_messages.append(stderr)
280
+
259
281
  if self._duration_secs is None:
260
282
  print(
261
283
  stderr,
@@ -338,7 +360,7 @@ class FfmpegProcess:
338
360
  error_handler()
339
361
 
340
362
  sys.exit(
341
- f"FFmpeg process failed. Check out '{self._ffmpeg_log_file}' for details."
363
+ f"FFmpeg process failed with return code {return_code}.\nError(s):\n{"\n".join(self._error_messages)}\nCheck out '{self._ffmpeg_log_file}' for more details."
342
364
  )
343
365
 
344
366
  if success_handler:
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: better-ffmpeg-progress
3
- Version: 2.5.3
3
+ Version: 2.5.5
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
@@ -171,3 +171,5 @@ The `run` method takes the following **optional** arguments:
171
171
  [12/11/2024]
172
172
  - [v2.5.2] Drain any remaining FFmpeg stderr after the process ends.
173
173
  - [v2.5.3] Write FFmpeg stderr to the log file in real time.
174
+ - [v2.5.4] Include progress info in stderr if the duration of the input file cannot be detected.
175
+ - [v2.5.5] Print detected errors in the terminal and only set `shell=True` if shell operators are detected.
@@ -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.5.3",
8
+ version="2.5.5",
9
9
  author="GitHub.com/CrypticSignal",
10
10
  author_email="theaudiophile@outlook.com",
11
11
  description="Run FFmpeg & see percentage progress + ETA.",