@danhachuel/thunderbolt 0.5.94 → 0.5.95
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.
package/hermes_ui/cuts.py
CHANGED
|
@@ -277,9 +277,11 @@ def build_clip_command(source: Path, output: Path, segment: dict[str, float], ou
|
|
|
277
277
|
"-vf",
|
|
278
278
|
_video_filter(output_format),
|
|
279
279
|
"-c:v",
|
|
280
|
-
"
|
|
280
|
+
"h264_nvenc",
|
|
281
281
|
"-preset",
|
|
282
|
-
"
|
|
282
|
+
"p1",
|
|
283
|
+
"-pix_fmt",
|
|
284
|
+
"yuv420p",
|
|
283
285
|
"-crf",
|
|
284
286
|
"22",
|
|
285
287
|
"-c:a",
|
|
@@ -295,12 +297,19 @@ def _run_ffmpeg(command: list[str], output: Path, *, source: Path, segment: dict
|
|
|
295
297
|
completed = subprocess.run(command, capture_output=True, text=True, check=False)
|
|
296
298
|
except OSError as exc:
|
|
297
299
|
raise CutsError(f"Não foi possível iniciar FFmpeg: {exc}") from exc
|
|
300
|
+
executed_command = list(command)
|
|
301
|
+
if completed.returncode != 0 and "h264_nvenc" in executed_command:
|
|
302
|
+
fallback = ["libx264" if item == "h264_nvenc" else "veryfast" if item == "p1" else item for item in executed_command]
|
|
303
|
+
if output.exists():
|
|
304
|
+
output.unlink()
|
|
305
|
+
completed = subprocess.run(fallback, capture_output=True, text=True, check=False)
|
|
306
|
+
executed_command = fallback
|
|
298
307
|
if completed.returncode != 0 or not output.is_file() or output.stat().st_size == 0:
|
|
299
308
|
if output.exists():
|
|
300
309
|
output.unlink()
|
|
301
310
|
detail = (completed.stderr or completed.stdout or "erro desconhecido").strip()
|
|
302
311
|
raise CutsError(f"O clip não pôde ser gerado: {detail[-1200:]}")
|
|
303
|
-
return {"source": str(source), "output": str(output), "command":
|
|
312
|
+
return {"source": str(source), "output": str(output), "command": executed_command, "segment": segment, "created_at": _now()}
|
|
304
313
|
|
|
305
314
|
|
|
306
315
|
def _write_manifest(record: dict[str, Any], run_dir: Path) -> Path:
|
|
@@ -150,10 +150,17 @@ def store_uploaded_asset(name: str, content: bytes, *, audio: bool = False) -> P
|
|
|
150
150
|
|
|
151
151
|
def _run(command: list[str], output: Path, operation: str, source: Path, *, extra: dict[str, Any] | None = None) -> tuple[Path, dict[str, Any]]:
|
|
152
152
|
output.parent.mkdir(parents=True, exist_ok=True)
|
|
153
|
+
executed_command = list(command)
|
|
153
154
|
try:
|
|
154
|
-
completed = subprocess.run(
|
|
155
|
+
completed = subprocess.run(executed_command, capture_output=True, text=True, check=False)
|
|
155
156
|
except OSError as exc:
|
|
156
157
|
raise PythonEditorError(f"Não foi possível iniciar FFmpeg: {exc}") from exc
|
|
158
|
+
if completed.returncode != 0 and "h264_nvenc" in executed_command:
|
|
159
|
+
fallback = ["libx264" if item == "h264_nvenc" else "veryfast" if item == "p1" else item for item in executed_command]
|
|
160
|
+
if output.exists():
|
|
161
|
+
output.unlink()
|
|
162
|
+
completed = subprocess.run(fallback, capture_output=True, text=True, check=False)
|
|
163
|
+
executed_command = fallback
|
|
157
164
|
if completed.returncode != 0 or not output.is_file() or output.stat().st_size == 0:
|
|
158
165
|
if output.exists():
|
|
159
166
|
output.unlink()
|
|
@@ -163,7 +170,7 @@ def _run(command: list[str], output: Path, operation: str, source: Path, *, extr
|
|
|
163
170
|
"operation": operation,
|
|
164
171
|
"source": str(source),
|
|
165
172
|
"output": str(output),
|
|
166
|
-
"command":
|
|
173
|
+
"command": executed_command,
|
|
167
174
|
"created_at": _now(),
|
|
168
175
|
}
|
|
169
176
|
if extra:
|
|
@@ -224,7 +231,7 @@ def resize_video(source: Path, width: int, height: int, *, ffmpeg_path: str | No
|
|
|
224
231
|
raise PythonEditorError("As dimensões do vídeo devem ser pelo menos 16x16.")
|
|
225
232
|
output = _output_path(source, "redimensionado")
|
|
226
233
|
scale = f"scale={width}:{height}:force_original_aspect_ratio=decrease,pad={width}:{height}:(ow-iw)/2:(oh-ih)/2"
|
|
227
|
-
command = [_ffmpeg(ffmpeg_path), "-y", "-hide_banner", "-loglevel", "error", "-i", str(source), "-vf", scale, "-c:v", "
|
|
234
|
+
command = [_ffmpeg(ffmpeg_path), "-y", "-hide_banner", "-loglevel", "error", "-i", str(source), "-vf", scale, "-c:v", "h264_nvenc", "-preset", "p1", "-pix_fmt", "yuv420p", "-c:a", "aac", "-movflags", "+faststart", str(output)]
|
|
228
235
|
return _run(command, output, "redimensionamento", source, extra={"width": width, "height": height})
|
|
229
236
|
|
|
230
237
|
|
|
@@ -234,7 +241,7 @@ def change_speed(source: Path, speed: float, *, ffmpeg_path: str | None = None)
|
|
|
234
241
|
if speed < 0.25 or speed > 4.0:
|
|
235
242
|
raise PythonEditorError("A velocidade deve estar entre 0,25x e 4x.")
|
|
236
243
|
output = _output_path(source, "velocidade")
|
|
237
|
-
command = [_ffmpeg(ffmpeg_path), "-y", "-hide_banner", "-loglevel", "error", "-i", str(source), "-filter:v", f"setpts=PTS/{speed:.6f}", "-filter:a", _atempo_chain(speed), "-c:v", "
|
|
244
|
+
command = [_ffmpeg(ffmpeg_path), "-y", "-hide_banner", "-loglevel", "error", "-i", str(source), "-filter:v", f"setpts=PTS/{speed:.6f}", "-filter:a", _atempo_chain(speed), "-c:v", "h264_nvenc", "-preset", "p1", "-pix_fmt", "yuv420p", "-c:a", "aac", "-movflags", "+faststart", str(output)]
|
|
238
245
|
return _run(command, output, "alteração de velocidade", source, extra={"speed": speed})
|
|
239
246
|
|
|
240
247
|
|
package/hermes_ui/storage.py
CHANGED
|
@@ -265,7 +265,7 @@ DEFAULTS: dict[str, Any] = {
|
|
|
265
265
|
"sonilo_api_key": "",
|
|
266
266
|
"subtitle_provider": "edge",
|
|
267
267
|
"ffmpeg_path": "",
|
|
268
|
-
"video_codec": "",
|
|
268
|
+
"video_codec": "h264_nvenc",
|
|
269
269
|
"material_directory": "",
|
|
270
270
|
"whisper_model_size": "large-v3",
|
|
271
271
|
"whisper_device": "cpu",
|
|
@@ -8,6 +8,8 @@ from typing import Any
|
|
|
8
8
|
from hermes_ui.languages import language_code
|
|
9
9
|
from hermes_ui.material_sources import all_material_api_keys, selected_material_source
|
|
10
10
|
|
|
11
|
+
NVENC_VIDEO_CODEC = "h264_nvenc"
|
|
12
|
+
|
|
11
13
|
try:
|
|
12
14
|
import toml
|
|
13
15
|
except ImportError: # pragma: no cover - installation fallback
|
|
@@ -118,6 +120,10 @@ def build_moneyprinter_config(settings: dict[str, Any], existing: dict[str, Any]
|
|
|
118
120
|
for settings_key, config_key in app_map.items():
|
|
119
121
|
if settings_key in settings:
|
|
120
122
|
app[config_key] = settings[settings_key]
|
|
123
|
+
# The bundled video pipeline is required to use NVIDIA NVENC. The
|
|
124
|
+
# MoneyPrinterTurbo runtime falls back to libx264 when this encoder is not
|
|
125
|
+
# available on the host, preserving a playable output instead of failing.
|
|
126
|
+
app["video_codec"] = NVENC_VIDEO_CODEC
|
|
121
127
|
# Edge TTS V1 is retained as a keyless fallback, but its default 30-second
|
|
122
128
|
# stream deadline is too short for longer scripts or slow networks.
|
|
123
129
|
try:
|
package/package.json
CHANGED