This commit is contained in:
stirelshka8
2026-03-24 14:38:40 +03:00
parent 6b9042bee1
commit b8211b5220
5 changed files with 565 additions and 58 deletions
+43 -9
View File
@@ -23,16 +23,20 @@ try:
import proglog
class WriteProgressLogger(proglog.ProgressBarLogger):
"""Логгер прогресса записи видео для передачи в окно выполнения."""
def __init__(self, callback):
def __init__(self, callback=None, cancel_check=None, stage=STAGE_WRITE):
super().__init__()
self._callback = callback
self._cancel_check = cancel_check if callable(cancel_check) else (lambda: False)
self._stage = stage
def bars_callback(self, bar, attr, value, old_value=None):
if self._cancel_check():
raise CancelledError()
if not self._callback or bar not in self.bars:
return
total = self.bars[bar].get("total")
if total and total > 0:
pct = value / total
self._callback(STAGE_WRITE, pct, f"Сохранение: {int(pct * 100)}%")
self._callback(self._stage, pct, f"Сохранение: {int(pct * 100)}%")
_HAS_PROGLOG = True
except Exception:
_HAS_PROGLOG = False
@@ -264,7 +268,6 @@ class VideoProcessor:
try:
keep = self._ranges_to_keep(remove_ranges, video.duration)
if not keep:
current_step += 1
continue
part_clips = []
for start, end in keep:
@@ -279,13 +282,24 @@ class VideoProcessor:
except Exception:
pass
temp_path = os.path.join(tmpdir, f"part_{i:04d}.mp4")
write_kw = {"codec": "libx264", "bitrate": self.get_bitrate(quality), "audio_codec": "aac"}
# В оконной сборке stdout/stderr могут быть None; отключаем дефолтный логгер MoviePy.
write_kw = {"codec": "libx264", "bitrate": self.get_bitrate(quality), "audio_codec": "aac", "logger": None}
if fps and fps > 0:
write_kw["fps"] = fps
if _HAS_PROGLOG and WriteProgressLogger is not None:
write_kw["logger"] = WriteProgressLogger(cancel_check=cancel_check, stage=STAGE_PREPARE)
try:
part.write_videofile(temp_path, **write_kw)
except TypeError:
part.write_videofile(temp_path, codec="libx264", bitrate=self.get_bitrate(quality), audio_codec="aac")
part.write_videofile(
temp_path,
codec="libx264",
bitrate=self.get_bitrate(quality),
audio_codec="aac",
logger=None,
)
if cancel_check():
raise CancelledError()
part.close()
temp_paths.append(temp_path)
finally:
@@ -353,20 +367,32 @@ class VideoProcessor:
if progress_callback:
progress_callback(STAGE_WRITE, 0.0, "Сохранение итогового файла...")
self.logger.log("INFO", f"Сохранение файла: {output_path}")
write_kw = {"codec": "libx264", "bitrate": self.get_bitrate(quality), "audio_codec": "aac"}
write_kw = {"codec": "libx264", "bitrate": self.get_bitrate(quality), "audio_codec": "aac", "logger": None}
if fps is not None and fps > 0:
write_kw["fps"] = fps
write_kw["preset"] = preset
write_kw["audio_bitrate"] = audio_bitrate
if _HAS_PROGLOG and progress_callback and WriteProgressLogger is not None:
write_kw["logger"] = WriteProgressLogger(progress_callback)
if _HAS_PROGLOG and WriteProgressLogger is not None:
write_kw["logger"] = WriteProgressLogger(
callback=progress_callback,
cancel_check=check,
stage=STAGE_WRITE,
)
try:
to_write.write_videofile(output_path, **write_kw)
except TypeError:
write_kw.pop("preset", None)
write_kw.pop("audio_bitrate", None)
write_kw.pop("logger", None)
write_kw["logger"] = None
to_write.write_videofile(output_path, **write_kw)
if check():
raise CancelledError()
except CancelledError:
self._remove_if_exists(output_path)
raise
except Exception:
self._remove_if_exists(output_path)
raise
if resized is not None:
try:
resized.close()
@@ -382,6 +408,14 @@ class VideoProcessor:
_write_video_metadata(output_path, meta, self.logger)
return output_path
@staticmethod
def _remove_if_exists(path):
try:
if path and os.path.isfile(path):
os.remove(path)
except OSError:
pass
def get_bitrate(self, quality):
"""Определение битрейта в зависимости от качества"""
quality_settings = {