Update app.py
Browse files
app.py
CHANGED
|
@@ -22,34 +22,64 @@ def detect_hardware_acceleration():
|
|
| 22 |
'nvidia': False,
|
| 23 |
'amd': False,
|
| 24 |
'intel': False,
|
| 25 |
-
'encoder': 'libx264' # 默认使用软件编码
|
|
|
|
| 26 |
}
|
| 27 |
|
| 28 |
try:
|
| 29 |
# 检查NVIDIA GPU
|
| 30 |
result = subprocess.run(['ffmpeg', '-encoders'], capture_output=True, text=True)
|
| 31 |
if 'h264_nvenc' in result.stdout:
|
| 32 |
-
|
| 33 |
-
|
| 34 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 35 |
|
| 36 |
# 检查AMD GPU
|
| 37 |
-
if 'h264_amf' in result.stdout:
|
| 38 |
-
|
| 39 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 40 |
hardware_accel['encoder'] = 'h264_amf'
|
| 41 |
-
|
|
|
|
|
|
|
|
|
|
| 42 |
|
| 43 |
# 检查Intel Quick Sync
|
| 44 |
-
if 'h264_qsv' in result.stdout:
|
| 45 |
-
|
| 46 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 47 |
hardware_accel['encoder'] = 'h264_qsv'
|
| 48 |
-
|
|
|
|
|
|
|
|
|
|
| 49 |
|
| 50 |
except Exception as e:
|
| 51 |
print(f"⚠️ 硬件加速检测失败: {e}")
|
| 52 |
|
|
|
|
|
|
|
|
|
|
| 53 |
return hardware_accel
|
| 54 |
|
| 55 |
# 全局硬件加速信息
|
|
@@ -268,15 +298,7 @@ def build_ffmpeg_command(input_path, start_time, duration, output_path, operatio
|
|
| 268 |
input_path = os.path.abspath(input_path)
|
| 269 |
output_path = os.path.abspath(output_path)
|
| 270 |
|
| 271 |
-
base_command = ['ffmpeg']
|
| 272 |
-
|
| 273 |
-
# 硬件加速解码 - 简化处理,避免兼容性问题
|
| 274 |
-
# if HARDWARE_ACCEL['nvidia']:
|
| 275 |
-
# base_command.extend(['-hwaccel', 'cuda'])
|
| 276 |
-
# elif HARDWARE_ACCEL['amd']:
|
| 277 |
-
# base_command.extend(['-hwaccel', 'amf'])
|
| 278 |
-
# elif HARDWARE_ACCEL['intel']:
|
| 279 |
-
# base_command.extend(['-hwaccel', 'qsv'])
|
| 280 |
|
| 281 |
base_command.extend(['-i', input_path])
|
| 282 |
|
|
@@ -284,41 +306,40 @@ def build_ffmpeg_command(input_path, start_time, duration, output_path, operatio
|
|
| 284 |
base_command.extend(['-ss', str(start_time), '-t', str(duration)])
|
| 285 |
|
| 286 |
# 编码参数
|
| 287 |
-
if
|
| 288 |
-
#
|
| 289 |
-
|
| 290 |
-
|
| 291 |
-
|
| 292 |
-
|
| 293 |
-
|
| 294 |
-
|
| 295 |
-
|
| 296 |
-
|
| 297 |
-
|
| 298 |
-
|
| 299 |
-
|
| 300 |
-
|
| 301 |
-
|
| 302 |
-
|
| 303 |
-
|
| 304 |
-
|
| 305 |
-
|
| 306 |
-
|
| 307 |
-
|
| 308 |
-
|
| 309 |
-
|
| 310 |
-
|
| 311 |
-
|
| 312 |
-
|
| 313 |
-
|
| 314 |
-
|
| 315 |
-
|
| 316 |
-
|
| 317 |
-
|
| 318 |
-
|
| 319 |
-
|
| 320 |
-
|
| 321 |
-
])
|
| 322 |
else:
|
| 323 |
# 软件编码参数 - 使用ultrafast预设
|
| 324 |
base_command.extend([
|
|
@@ -335,16 +356,39 @@ def build_ffmpeg_command(input_path, start_time, duration, output_path, operatio
|
|
| 335 |
|
| 336 |
elif operation == 'resize':
|
| 337 |
# 调整尺寸的编码参数
|
| 338 |
-
if
|
| 339 |
-
|
| 340 |
-
|
| 341 |
-
|
| 342 |
-
|
| 343 |
-
|
| 344 |
-
|
| 345 |
-
|
| 346 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 347 |
else:
|
|
|
|
| 348 |
base_command.extend([
|
| 349 |
'-c:v', 'libx264',
|
| 350 |
'-preset', 'ultrafast',
|
|
@@ -370,6 +414,22 @@ def ffmpeg_cut_video(input_path, start_time, duration, output_path):
|
|
| 370 |
|
| 371 |
if result.returncode != 0:
|
| 372 |
print(f"FFmpeg错误: {result.stderr}") # 输出错误信息
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 373 |
return False
|
| 374 |
|
| 375 |
return os.path.exists(output_path)
|
|
@@ -399,6 +459,24 @@ def ffmpeg_resize_video(input_path, output_path, target_ratio):
|
|
| 399 |
|
| 400 |
if result.returncode != 0:
|
| 401 |
print(f"FFmpeg调整错误: {result.stderr}") # 输出错误信息
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 402 |
return False
|
| 403 |
|
| 404 |
return os.path.exists(output_path)
|
|
@@ -488,7 +566,7 @@ def process_videos_with_storage(video_files, clip_duration, num_output_videos, t
|
|
| 488 |
|
| 489 |
try:
|
| 490 |
print(f"🔍 开始处理 {len(video_files)} 个视频文件...")
|
| 491 |
-
print(f"⚡ 硬件加速: {HARDWARE_ACCEL['encoder']}")
|
| 492 |
print(f"🔧 线程数: {get_optimal_threads()}")
|
| 493 |
print(f"⏱️ 切片时长: {clip_duration} 秒 | 生成数量: {num_output_videos} 个 | 比例: {target_ratio}")
|
| 494 |
|
|
@@ -579,7 +657,7 @@ def process_videos_with_storage(video_files, clip_duration, num_output_videos, t
|
|
| 579 |
- 视频数量: {len(output_files)} 个
|
| 580 |
- 视频比例: {target_ratio}
|
| 581 |
- 切片时长: {clip_duration} 秒
|
| 582 |
-
- 硬件加速: {HARDWARE_ACCEL['encoder']}
|
| 583 |
## 📁 文件列表
|
| 584 |
"""
|
| 585 |
for i, vf in enumerate(output_files, 1):
|
|
@@ -609,7 +687,7 @@ def process_videos_with_storage(video_files, clip_duration, num_output_videos, t
|
|
| 609 |
• 📐 视频比例: {target_ratio}
|
| 610 |
• 🎯 适合平台: {platform_info}
|
| 611 |
• 📦 下载包大小: {total_size:.1f}MB
|
| 612 |
-
• ⚡ 硬件加速: {HARDWARE_ACCEL['encoder']}
|
| 613 |
• 🔧 处理线程: {get_optimal_threads()}
|
| 614 |
• ⏱️ 处理耗时: {elapsed:.1f} 秒
|
| 615 |
💾 **自动储存:**
|
|
@@ -662,7 +740,7 @@ def refresh_storage_display():
|
|
| 662 |
• 总视频数量: {config['total_videos']} 个
|
| 663 |
• 总占用空间: {config['total_size_mb']}MB
|
| 664 |
• 储存位置: ~/video_storage/
|
| 665 |
-
• 硬件加速: {HARDWARE_ACCEL['encoder']}
|
| 666 |
📁 **文件列表:**
|
| 667 |
"""
|
| 668 |
|
|
@@ -712,7 +790,7 @@ def main():
|
|
| 712 |
<div style="text-align: center; padding: 20px; background: linear-gradient(135deg, #667eea 0%, #764ba2 100%); border-radius: 15px; color: white; margin-bottom: 20px;">
|
| 713 |
<h1>🎬 FFmpeg 混剪工具 + 储存管理 + 一键下载</h1>
|
| 714 |
<p style="margin: 10px 0 0 0;">长视频切片 → 智能混剪 → 比例调整 → 自动储存 → 一键下载</p>
|
| 715 |
-
<p style="margin: 5px 0 0 0; font-size: 14px; opacity: 0.9;">⚡ 硬件加速: {HARDWARE_ACCEL['encoder']}
|
| 716 |
</div>
|
| 717 |
""")
|
| 718 |
|
|
@@ -841,7 +919,7 @@ def main():
|
|
| 841 |
- 📐 支持9:16/16:9比例调整
|
| 842 |
- 📦 打包下载所有生成视频
|
| 843 |
- 💾 **自动储存到本地目录**
|
| 844 |
-
- 🚀 **硬件加速: {HARDWARE_ACCEL['encoder']}**
|
| 845 |
- 🔧 **多线程处理: {get_optimal_threads()} 线程**
|
| 846 |
|
| 847 |
**💾 储存管理功能:**
|
|
@@ -869,6 +947,7 @@ def main():
|
|
| 869 |
|
| 870 |
**⚡ 性能优化:**
|
| 871 |
- **硬件加速**: 自动检测并使用GPU加速
|
|
|
|
| 872 |
- **多线程处理**: 充分利用多核CPU
|
| 873 |
- **快速预设**: 使用ultrafast预设提升速度
|
| 874 |
- **并行处理**: 多个视频同时处理
|
|
|
|
| 22 |
'nvidia': False,
|
| 23 |
'amd': False,
|
| 24 |
'intel': False,
|
| 25 |
+
'encoder': 'libx264', # 默认使用软件编码
|
| 26 |
+
'working': False # 标记硬件加速是否实际可用
|
| 27 |
}
|
| 28 |
|
| 29 |
try:
|
| 30 |
# 检查NVIDIA GPU
|
| 31 |
result = subprocess.run(['ffmpeg', '-encoders'], capture_output=True, text=True)
|
| 32 |
if 'h264_nvenc' in result.stdout:
|
| 33 |
+
# 进一步测试NVIDIA编码器是否实际可用
|
| 34 |
+
test_result = subprocess.run([
|
| 35 |
+
'ffmpeg', '-f', 'lavfi', '-i', 'testsrc=duration=1:size=32x32:rate=1',
|
| 36 |
+
'-c:v', 'h264_nvenc', '-f', 'null', '-'
|
| 37 |
+
], capture_output=True, text=True)
|
| 38 |
+
|
| 39 |
+
if test_result.returncode == 0:
|
| 40 |
+
hardware_accel['nvidia'] = True
|
| 41 |
+
hardware_accel['encoder'] = 'h264_nvenc'
|
| 42 |
+
hardware_accel['working'] = True
|
| 43 |
+
print("✅ 检测到NVIDIA GPU硬件加速支持且工作正常")
|
| 44 |
+
else:
|
| 45 |
+
print("⚠️ 检测到NVIDIA GPU但无法使用,将回退到软件编码")
|
| 46 |
|
| 47 |
# 检查AMD GPU
|
| 48 |
+
if not hardware_accel['working'] and 'h264_amf' in result.stdout:
|
| 49 |
+
test_result = subprocess.run([
|
| 50 |
+
'ffmpeg', '-f', 'lavfi', '-i', 'testsrc=duration=1:size=32x32:rate=1',
|
| 51 |
+
'-c:v', 'h264_amf', '-f', 'null', '-'
|
| 52 |
+
], capture_output=True, text=True)
|
| 53 |
+
|
| 54 |
+
if test_result.returncode == 0:
|
| 55 |
+
hardware_accel['amd'] = True
|
| 56 |
hardware_accel['encoder'] = 'h264_amf'
|
| 57 |
+
hardware_accel['working'] = True
|
| 58 |
+
print("✅ 检测到AMD GPU硬件加速支持且工作正常")
|
| 59 |
+
else:
|
| 60 |
+
print("⚠️ 检测到AMD GPU但无法使用,将回退到软件编码")
|
| 61 |
|
| 62 |
# 检查Intel Quick Sync
|
| 63 |
+
if not hardware_accel['working'] and 'h264_qsv' in result.stdout:
|
| 64 |
+
test_result = subprocess.run([
|
| 65 |
+
'ffmpeg', '-f', 'lavfi', '-i', 'testsrc=duration=1:size=32x32:rate=1',
|
| 66 |
+
'-c:v', 'h264_qsv', '-f', 'null', '-'
|
| 67 |
+
], capture_output=True, text=True)
|
| 68 |
+
|
| 69 |
+
if test_result.returncode == 0:
|
| 70 |
+
hardware_accel['intel'] = True
|
| 71 |
hardware_accel['encoder'] = 'h264_qsv'
|
| 72 |
+
hardware_accel['working'] = True
|
| 73 |
+
print("✅ 检测到Intel Quick Sync硬件加速支持且工作正常")
|
| 74 |
+
else:
|
| 75 |
+
print("⚠️ 检测到Intel Quick Sync但无法使用,将回退到软件编码")
|
| 76 |
|
| 77 |
except Exception as e:
|
| 78 |
print(f"⚠️ 硬件加速检测失败: {e}")
|
| 79 |
|
| 80 |
+
if not hardware_accel['working']:
|
| 81 |
+
print("📌 将使用软件编码 (libx264)")
|
| 82 |
+
|
| 83 |
return hardware_accel
|
| 84 |
|
| 85 |
# 全局硬件加速信息
|
|
|
|
| 298 |
input_path = os.path.abspath(input_path)
|
| 299 |
output_path = os.path.abspath(output_path)
|
| 300 |
|
| 301 |
+
base_command = ['ffmpeg', '-threads', str(threads)]
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 302 |
|
| 303 |
base_command.extend(['-i', input_path])
|
| 304 |
|
|
|
|
| 306 |
base_command.extend(['-ss', str(start_time), '-t', str(duration)])
|
| 307 |
|
| 308 |
# 编码参数
|
| 309 |
+
if HARDWARE_ACCEL['working']:
|
| 310 |
+
# 硬件编码参数
|
| 311 |
+
if encoder == 'h264_nvenc':
|
| 312 |
+
base_command.extend([
|
| 313 |
+
'-c:v', 'h264_nvenc',
|
| 314 |
+
'-preset', 'fast',
|
| 315 |
+
'-cq', '28',
|
| 316 |
+
'-c:a', 'aac',
|
| 317 |
+
'-b:a', '128k',
|
| 318 |
+
'-movflags', '+faststart',
|
| 319 |
+
'-y', output_path
|
| 320 |
+
])
|
| 321 |
+
elif encoder == 'h264_amf':
|
| 322 |
+
base_command.extend([
|
| 323 |
+
'-c:v', 'h264_amf',
|
| 324 |
+
'-quality', 'speed',
|
| 325 |
+
'-rc', 'cqp',
|
| 326 |
+
'-cqp_i', '28',
|
| 327 |
+
'-cqp_p', '28',
|
| 328 |
+
'-c:a', 'aac',
|
| 329 |
+
'-b:a', '128k',
|
| 330 |
+
'-movflags', '+faststart',
|
| 331 |
+
'-y', output_path
|
| 332 |
+
])
|
| 333 |
+
elif encoder == 'h264_qsv':
|
| 334 |
+
base_command.extend([
|
| 335 |
+
'-c:v', 'h264_qsv',
|
| 336 |
+
'-preset', 'veryfast',
|
| 337 |
+
'-global_quality', '28',
|
| 338 |
+
'-c:a', 'aac',
|
| 339 |
+
'-b:a', '128k',
|
| 340 |
+
'-movflags', '+faststart',
|
| 341 |
+
'-y', output_path
|
| 342 |
+
])
|
|
|
|
| 343 |
else:
|
| 344 |
# 软件编码参数 - 使用ultrafast预设
|
| 345 |
base_command.extend([
|
|
|
|
| 356 |
|
| 357 |
elif operation == 'resize':
|
| 358 |
# 调整尺寸的编码参数
|
| 359 |
+
if HARDWARE_ACCEL['working']:
|
| 360 |
+
# 硬件编码参数
|
| 361 |
+
if encoder == 'h264_nvenc':
|
| 362 |
+
base_command.extend([
|
| 363 |
+
'-c:v', 'h264_nvenc',
|
| 364 |
+
'-preset', 'fast',
|
| 365 |
+
'-cq', '28',
|
| 366 |
+
'-c:a', 'copy',
|
| 367 |
+
'-movflags', '+faststart',
|
| 368 |
+
'-y', output_path
|
| 369 |
+
])
|
| 370 |
+
elif encoder == 'h264_amf':
|
| 371 |
+
base_command.extend([
|
| 372 |
+
'-c:v', 'h264_amf',
|
| 373 |
+
'-quality', 'speed',
|
| 374 |
+
'-rc', 'cqp',
|
| 375 |
+
'-cqp_i', '28',
|
| 376 |
+
'-cqp_p', '28',
|
| 377 |
+
'-c:a', 'copy',
|
| 378 |
+
'-movflags', '+faststart',
|
| 379 |
+
'-y', output_path
|
| 380 |
+
])
|
| 381 |
+
elif encoder == 'h264_qsv':
|
| 382 |
+
base_command.extend([
|
| 383 |
+
'-c:v', 'h264_qsv',
|
| 384 |
+
'-preset', 'veryfast',
|
| 385 |
+
'-global_quality', '28',
|
| 386 |
+
'-c:a', 'copy',
|
| 387 |
+
'-movflags', '+faststart',
|
| 388 |
+
'-y', output_path
|
| 389 |
+
])
|
| 390 |
else:
|
| 391 |
+
# 软件编码参数
|
| 392 |
base_command.extend([
|
| 393 |
'-c:v', 'libx264',
|
| 394 |
'-preset', 'ultrafast',
|
|
|
|
| 414 |
|
| 415 |
if result.returncode != 0:
|
| 416 |
print(f"FFmpeg错误: {result.stderr}") # 输出错误信息
|
| 417 |
+
|
| 418 |
+
# 如果硬件加速失败,尝试使用软件编码
|
| 419 |
+
if HARDWARE_ACCEL['working'] and "Cannot load libcuda.so.1" in result.stderr:
|
| 420 |
+
print("⚠️ 硬件加速失败,回退到软件编码...")
|
| 421 |
+
HARDWARE_ACCEL['working'] = False
|
| 422 |
+
HARDWARE_ACCEL['encoder'] = 'libx264'
|
| 423 |
+
|
| 424 |
+
# 重新构建命令,使用软件编码
|
| 425 |
+
command = build_ffmpeg_command(input_path, start_time, duration, output_path, 'cut')
|
| 426 |
+
print(f"重试FFmpeg命令(软件编码): {' '.join(command)}")
|
| 427 |
+
|
| 428 |
+
result = subprocess.run(command, stdout=subprocess.PIPE, stderr=subprocess.PIPE, text=True)
|
| 429 |
+
if result.returncode != 0:
|
| 430 |
+
print(f"FFmpeg软件编码错误: {result.stderr}")
|
| 431 |
+
return False
|
| 432 |
+
|
| 433 |
return False
|
| 434 |
|
| 435 |
return os.path.exists(output_path)
|
|
|
|
| 459 |
|
| 460 |
if result.returncode != 0:
|
| 461 |
print(f"FFmpeg调整错误: {result.stderr}") # 输出错误信息
|
| 462 |
+
|
| 463 |
+
# 如果硬件加速失败,尝试使用软件编码
|
| 464 |
+
if HARDWARE_ACCEL['working'] and "Cannot load libcuda.so.1" in result.stderr:
|
| 465 |
+
print("⚠️ 硬件加速失败,回退到软件编码...")
|
| 466 |
+
HARDWARE_ACCEL['working'] = False
|
| 467 |
+
HARDWARE_ACCEL['encoder'] = 'libx264'
|
| 468 |
+
|
| 469 |
+
# 重新构建命令,使用软件编码
|
| 470 |
+
command = build_ffmpeg_command(input_path, 0, 0, output_path, 'resize')
|
| 471 |
+
command.insert(-5, '-vf') # 在-y之前插入
|
| 472 |
+
command.insert(-4, filter_complex)
|
| 473 |
+
|
| 474 |
+
print(f"重试FFmpeg调整命令(软件编码): {' '.join(command)}")
|
| 475 |
+
result = subprocess.run(command, stdout=subprocess.PIPE, stderr=subprocess.PIPE, text=True)
|
| 476 |
+
if result.returncode != 0:
|
| 477 |
+
print(f"FFmpeg软件编码错误: {result.stderr}")
|
| 478 |
+
return False
|
| 479 |
+
|
| 480 |
return False
|
| 481 |
|
| 482 |
return os.path.exists(output_path)
|
|
|
|
| 566 |
|
| 567 |
try:
|
| 568 |
print(f"🔍 开始处理 {len(video_files)} 个视频文件...")
|
| 569 |
+
print(f"⚡ 硬件加速: {HARDWARE_ACCEL['encoder']} {'(工作正常)' if HARDWARE_ACCEL['working'] else '(不可用,使用软件编码)'}")
|
| 570 |
print(f"🔧 线程数: {get_optimal_threads()}")
|
| 571 |
print(f"⏱️ 切片时长: {clip_duration} 秒 | 生成数量: {num_output_videos} 个 | 比例: {target_ratio}")
|
| 572 |
|
|
|
|
| 657 |
- 视频数量: {len(output_files)} 个
|
| 658 |
- 视频比例: {target_ratio}
|
| 659 |
- 切片时长: {clip_duration} 秒
|
| 660 |
+
- 硬件加速: {HARDWARE_ACCEL['encoder']} {'(工作正常)' if HARDWARE_ACCEL['working'] else '(不可用,使用软件编码)'}
|
| 661 |
## 📁 文件列表
|
| 662 |
"""
|
| 663 |
for i, vf in enumerate(output_files, 1):
|
|
|
|
| 687 |
• 📐 视频比例: {target_ratio}
|
| 688 |
• 🎯 适合平台: {platform_info}
|
| 689 |
• 📦 下载包大小: {total_size:.1f}MB
|
| 690 |
+
• ⚡ 硬件加速: {HARDWARE_ACCEL['encoder']} {'(工作正常)' if HARDWARE_ACCEL['working'] else '(不可用,使用软件编码)'}
|
| 691 |
• 🔧 处理线程: {get_optimal_threads()}
|
| 692 |
• ⏱️ 处理耗时: {elapsed:.1f} 秒
|
| 693 |
💾 **自动储存:**
|
|
|
|
| 740 |
• 总视频数量: {config['total_videos']} 个
|
| 741 |
• 总占用空间: {config['total_size_mb']}MB
|
| 742 |
• 储存位置: ~/video_storage/
|
| 743 |
+
• 硬件加速: {HARDWARE_ACCEL['encoder']} {'(工作正常)' if HARDWARE_ACCEL['working'] else '(不可用,使用软件编码)'}
|
| 744 |
📁 **文件列表:**
|
| 745 |
"""
|
| 746 |
|
|
|
|
| 790 |
<div style="text-align: center; padding: 20px; background: linear-gradient(135deg, #667eea 0%, #764ba2 100%); border-radius: 15px; color: white; margin-bottom: 20px;">
|
| 791 |
<h1>🎬 FFmpeg 混剪工具 + 储存管理 + 一键下载</h1>
|
| 792 |
<p style="margin: 10px 0 0 0;">长视频切片 → 智能混剪 → 比例调整 → 自动储存 → 一键下载</p>
|
| 793 |
+
<p style="margin: 5px 0 0 0; font-size: 14px; opacity: 0.9;">⚡ 硬件加速: {HARDWARE_ACCEL['encoder']} {'(工作正常)' if HARDWARE_ACCEL['working'] else '(不可用,使用软件编码)'}</p>
|
| 794 |
</div>
|
| 795 |
""")
|
| 796 |
|
|
|
|
| 919 |
- 📐 支持9:16/16:9比例调整
|
| 920 |
- 📦 打包下载所有生成视频
|
| 921 |
- 💾 **自动储存到本地目录**
|
| 922 |
+
- 🚀 **硬件加速: {HARDWARE_ACCEL['encoder']} {'(工作正常)' if HARDWARE_ACCEL['working'] else '(不可用,使用软件编码)'}**
|
| 923 |
- 🔧 **多线程处理: {get_optimal_threads()} 线程**
|
| 924 |
|
| 925 |
**💾 储存管理功能:**
|
|
|
|
| 947 |
|
| 948 |
**⚡ 性能优化:**
|
| 949 |
- **硬件加速**: 自动检测并使用GPU加速
|
| 950 |
+
- **自动降级**: 硬件加速失败时自动回退到软件编码
|
| 951 |
- **多线程处理**: 充分利用多核CPU
|
| 952 |
- **快速预设**: 使用ultrafast预设提升速度
|
| 953 |
- **并行处理**: 多个视频同时处理
|