Ryanus commited on
Commit
fb241ba
·
verified ·
1 Parent(s): c35d15b

Update app.py

Browse files
Files changed (1) hide show
  1. app.py +150 -71
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
- hardware_accel['nvidia'] = True
33
- hardware_accel['encoder'] = 'h264_nvenc'
34
- print("✅ 检测到NVIDIA GPU硬件加速支持")
 
 
 
 
 
 
 
 
 
 
35
 
36
  # 检查AMD GPU
37
- if 'h264_amf' in result.stdout:
38
- hardware_accel['amd'] = True
39
- if hardware_accel['encoder'] == 'libx264':
 
 
 
 
 
40
  hardware_accel['encoder'] = 'h264_amf'
41
- print("✅ 检测到AMD GPU硬件加速支持")
 
 
 
42
 
43
  # 检查Intel Quick Sync
44
- if 'h264_qsv' in result.stdout:
45
- hardware_accel['intel'] = True
46
- if hardware_accel['encoder'] == 'libx264':
 
 
 
 
 
47
  hardware_accel['encoder'] = 'h264_qsv'
48
- print("✅ 检测到Intel Quick Sync硬件加速支持")
 
 
 
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 encoder == 'h264_nvenc':
288
- # NVIDIA GPU编码参数 - 简化版本
289
- base_command.extend([
290
- '-c:v', 'h264_nvenc',
291
- '-preset', 'fast', # 使用fast而不是p1,更兼容
292
- '-cq', '28', # 质量参数
293
- '-c:a', 'aac',
294
- '-b:a', '128k',
295
- '-movflags', '+faststart',
296
- '-y', output_path
297
- ])
298
- elif encoder == 'h264_amf':
299
- # AMD GPU编码参数 - 简化版本
300
- base_command.extend([
301
- '-c:v', 'h264_amf',
302
- '-quality', 'speed',
303
- '-rc', 'cqp',
304
- '-cqp_i', '28',
305
- '-cqp_p', '28',
306
- '-c:a', 'aac',
307
- '-b:a', '128k',
308
- '-movflags', '+faststart',
309
- '-y', output_path
310
- ])
311
- elif encoder == 'h264_qsv':
312
- # Intel Quick Sync编码参数 - 简化版本
313
- base_command.extend([
314
- '-c:v', 'h264_qsv',
315
- '-preset', 'veryfast',
316
- '-global_quality', '28',
317
- '-c:a', 'aac',
318
- '-b:a', '128k',
319
- '-movflags', '+faststart',
320
- '-y', output_path
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 encoder == 'h264_nvenc':
339
- base_command.extend([
340
- '-c:v', 'h264_nvenc',
341
- '-preset', 'fast',
342
- '-cq', '28',
343
- '-c:a', 'copy',
344
- '-movflags', '+faststart',
345
- '-y', output_path
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']} | 🔧 线程数: {get_optimal_threads()}</p>
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
  - **并行处理**: 多个视频同时处理