st3v3x commited on
Commit
d5c19d1
·
verified ·
1 Parent(s): dc4e700

Actualizar nodo OmniVision

Browse files
Files changed (1) hide show
  1. ffmpeg.py +71 -11
ffmpeg.py CHANGED
@@ -269,20 +269,33 @@ def normalize_thumbnail_image(src_path: str, dst_path: str) -> bool:
269
  return False
270
 
271
 
272
- def compress_with_cmd(
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
273
  input_path: str,
274
  output_path: str,
275
  settings: Dict[str, Any],
276
  wm_image_path: str,
277
- total_duration: float,
278
- on_cmd: Optional[Callable[[subprocess.Popen], None]] = None,
279
- on_progress: Optional[Callable[[Dict[str, Any]], None]] = None,
280
- is_cancelled: Optional[Callable[[], bool]] = None,
281
- ) -> None:
282
- """
283
- Ejecuta la compresión con FFmpeg reportando el progreso en vivo.
284
- Implementa el escaneo exacto de CRLF y CR de FFmpeg.
285
- """
286
  settings = sanitize_settings(settings)
287
 
288
  args = ["-y", "-i", input_path]
@@ -315,13 +328,15 @@ def compress_with_cmd(
315
 
316
  is_avi = settings.get("format", "").lower() == "avi" or output_path.lower().endswith(".avi")
317
 
 
318
  # Subtítulos de texto para contenedores no AVI
319
- if not is_avi:
320
  text_sub_streams = get_text_subtitle_streams(input_path)
321
  for idx in text_sub_streams:
322
  args.extend(["-map", f"0:{idx}"])
323
  if text_sub_streams:
324
  args.extend(["-c:s", "mov_text"])
 
325
 
326
  codec = settings.get("codec") or "libx264"
327
  args.extend(["-c:v", codec])
@@ -354,7 +369,16 @@ def compress_with_cmd(
354
  args.extend(["-movflags", "+faststart"])
355
 
356
  args.extend(["-threads", "0", output_path])
 
 
357
 
 
 
 
 
 
 
 
358
  cmd_list = ["ffmpeg"] + args
359
 
360
  proc = subprocess.Popen(
@@ -451,3 +475,39 @@ def compress_with_cmd(
451
  proc.kill()
452
  except Exception:
453
  pass
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
269
  return False
270
 
271
 
272
+ def is_subtitle_or_mux_error(err_str: str) -> bool:
273
+ """Comprueba si el error de stderr de FFmpeg está relacionado con subtítulos corruptos o fallos de muxing."""
274
+ lower = err_str.lower()
275
+ indicators = [
276
+ "application provided duration",
277
+ "mov_text",
278
+ "subtitle",
279
+ "av_interleaved_write_frame",
280
+ "invalid argument",
281
+ "error while writing stream",
282
+ "pts has no value",
283
+ "out of range for mov/mp4",
284
+ "invalid dts",
285
+ "invalid pts",
286
+ "muxing",
287
+ ]
288
+ return any(ind in lower for ind in indicators)
289
+
290
+
291
+ def build_compress_args(
292
  input_path: str,
293
  output_path: str,
294
  settings: Dict[str, Any],
295
  wm_image_path: str,
296
+ include_subtitles: bool = True,
297
+ ) -> Tuple[List[str], bool]:
298
+ """Genera la lista de argumentos para FFmpeg, permitiendo habilitar o deshabilitar subtítulos."""
 
 
 
 
 
 
299
  settings = sanitize_settings(settings)
300
 
301
  args = ["-y", "-i", input_path]
 
328
 
329
  is_avi = settings.get("format", "").lower() == "avi" or output_path.lower().endswith(".avi")
330
 
331
+ has_subtitles = False
332
  # Subtítulos de texto para contenedores no AVI
333
+ if not is_avi and include_subtitles:
334
  text_sub_streams = get_text_subtitle_streams(input_path)
335
  for idx in text_sub_streams:
336
  args.extend(["-map", f"0:{idx}"])
337
  if text_sub_streams:
338
  args.extend(["-c:s", "mov_text"])
339
+ has_subtitles = True
340
 
341
  codec = settings.get("codec") or "libx264"
342
  args.extend(["-c:v", codec])
 
369
  args.extend(["-movflags", "+faststart"])
370
 
371
  args.extend(["-threads", "0", output_path])
372
+ return args, has_subtitles
373
+
374
 
375
+ def execute_ffmpeg_cmd(
376
+ args: List[str],
377
+ total_duration: float,
378
+ on_cmd: Optional[Callable[[subprocess.Popen], None]] = None,
379
+ on_progress: Optional[Callable[[Dict[str, Any]], None]] = None,
380
+ is_cancelled: Optional[Callable[[], bool]] = None,
381
+ ) -> None:
382
  cmd_list = ["ffmpeg"] + args
383
 
384
  proc = subprocess.Popen(
 
475
  proc.kill()
476
  except Exception:
477
  pass
478
+
479
+
480
+ def compress_with_cmd(
481
+ input_path: str,
482
+ output_path: str,
483
+ settings: Dict[str, Any],
484
+ wm_image_path: str,
485
+ total_duration: float,
486
+ on_cmd: Optional[Callable[[subprocess.Popen], None]] = None,
487
+ on_progress: Optional[Callable[[Dict[str, Any]], None]] = None,
488
+ is_cancelled: Optional[Callable[[], bool]] = None,
489
+ ) -> None:
490
+ """
491
+ Ejecuta la compresión con FFmpeg reportando el progreso en vivo.
492
+ Si la compresión falla debido a subtítulos corruptos o timestamps inválidos,
493
+ reintenta automáticamente descartando los subtítulos para no fallar la tarea.
494
+ """
495
+ args, has_subtitles = build_compress_args(input_path, output_path, settings, wm_image_path, include_subtitles=True)
496
+ try:
497
+ execute_ffmpeg_cmd(args, total_duration, on_cmd, on_progress, is_cancelled)
498
+ return
499
+ except RuntimeError as e:
500
+ if is_cancelled and is_cancelled():
501
+ raise
502
+ if has_subtitles and is_subtitle_or_mux_error(str(e)):
503
+ logger.warning(f"[ffmpeg] Falló compresión con subtítulos ({e}). Reintentando sin subtítulos...")
504
+ if os.path.isfile(output_path):
505
+ try:
506
+ os.remove(output_path)
507
+ except Exception:
508
+ pass
509
+ retry_args, _ = build_compress_args(input_path, output_path, settings, wm_image_path, include_subtitles=False)
510
+ execute_ffmpeg_cmd(retry_args, total_duration, on_cmd, on_progress, is_cancelled)
511
+ logger.info("[ffmpeg] Compresión completada con éxito tras descartar subtítulos corruptos.")
512
+ return
513
+ raise