mirror of
https://github.com/linyqh/NarratoAI.git
synced 2025-12-11 18:42:49 +00:00
在video_processor.py中,添加了对Windows N卡硬件加速的支持,优化了帧提取过程,改进了提取成功率的统计和错误处理。同时,在generate_script_docu.py中,增强了对硬件加速失败的处理逻辑,提供了详细的错误信息和解决建议,提升了用户体验。
285 lines
9.3 KiB
Python
285 lines
9.3 KiB
Python
"""
|
||
FFmpeg 配置管理模块
|
||
专门用于管理 FFmpeg 兼容性设置和优化参数
|
||
"""
|
||
|
||
import os
|
||
import platform
|
||
from typing import Dict, List, Optional
|
||
from dataclasses import dataclass
|
||
from loguru import logger
|
||
|
||
|
||
@dataclass
|
||
class FFmpegProfile:
|
||
"""FFmpeg 配置文件"""
|
||
name: str
|
||
description: str
|
||
hwaccel_enabled: bool
|
||
hwaccel_type: Optional[str]
|
||
encoder: str
|
||
quality_preset: str
|
||
pixel_format: str
|
||
additional_args: List[str]
|
||
compatibility_level: int # 1-5, 5为最高兼容性
|
||
|
||
|
||
class FFmpegConfigManager:
|
||
"""FFmpeg 配置管理器"""
|
||
|
||
# 预定义的配置文件
|
||
PROFILES = {
|
||
# 高性能配置(适用于现代硬件)
|
||
"high_performance": FFmpegProfile(
|
||
name="high_performance",
|
||
description="高性能配置(NVIDIA/AMD 独立显卡)",
|
||
hwaccel_enabled=True,
|
||
hwaccel_type="auto",
|
||
encoder="auto",
|
||
quality_preset="fast",
|
||
pixel_format="yuv420p",
|
||
additional_args=["-preset", "fast"],
|
||
compatibility_level=2
|
||
),
|
||
|
||
# 兼容性配置(适用于有问题的硬件)
|
||
"compatibility": FFmpegProfile(
|
||
name="compatibility",
|
||
description="兼容性配置(解决滤镜链问题)",
|
||
hwaccel_enabled=False,
|
||
hwaccel_type=None,
|
||
encoder="libx264",
|
||
quality_preset="medium",
|
||
pixel_format="yuv420p",
|
||
additional_args=["-preset", "medium", "-crf", "23"],
|
||
compatibility_level=5
|
||
),
|
||
|
||
# Windows N 卡优化配置
|
||
"windows_nvidia": FFmpegProfile(
|
||
name="windows_nvidia",
|
||
description="Windows NVIDIA 显卡优化配置",
|
||
hwaccel_enabled=True,
|
||
hwaccel_type="nvenc_pure", # 纯编码器,避免解码问题
|
||
encoder="h264_nvenc",
|
||
quality_preset="medium",
|
||
pixel_format="yuv420p",
|
||
additional_args=["-preset", "medium", "-cq", "23"],
|
||
compatibility_level=3
|
||
),
|
||
|
||
# macOS 优化配置
|
||
"macos_videotoolbox": FFmpegProfile(
|
||
name="macos_videotoolbox",
|
||
description="macOS VideoToolbox 优化配置",
|
||
hwaccel_enabled=True,
|
||
hwaccel_type="videotoolbox",
|
||
encoder="h264_videotoolbox",
|
||
quality_preset="medium",
|
||
pixel_format="yuv420p",
|
||
additional_args=["-q:v", "65"],
|
||
compatibility_level=3
|
||
),
|
||
|
||
# 通用软件配置
|
||
"universal_software": FFmpegProfile(
|
||
name="universal_software",
|
||
description="通用软件编码配置(最高兼容性)",
|
||
hwaccel_enabled=False,
|
||
hwaccel_type=None,
|
||
encoder="libx264",
|
||
quality_preset="medium",
|
||
pixel_format="yuv420p",
|
||
additional_args=["-preset", "medium", "-crf", "23"],
|
||
compatibility_level=5
|
||
)
|
||
}
|
||
|
||
@classmethod
|
||
def get_recommended_profile(cls) -> str:
|
||
"""
|
||
根据系统环境推荐最佳配置文件
|
||
|
||
Returns:
|
||
str: 推荐的配置文件名称
|
||
"""
|
||
system = platform.system().lower()
|
||
|
||
# 检测硬件加速可用性
|
||
try:
|
||
from app.utils import ffmpeg_utils
|
||
hwaccel_info = ffmpeg_utils.get_ffmpeg_hwaccel_info()
|
||
hwaccel_available = hwaccel_info.get("available", False)
|
||
hwaccel_type = hwaccel_info.get("type", "software")
|
||
gpu_vendor = hwaccel_info.get("gpu_vendor", "unknown")
|
||
except Exception as e:
|
||
logger.warning(f"无法检测硬件加速信息: {e}")
|
||
hwaccel_available = False
|
||
hwaccel_type = "software"
|
||
gpu_vendor = "unknown"
|
||
|
||
# 根据平台和硬件推荐配置
|
||
if system == "windows":
|
||
if hwaccel_available and gpu_vendor == "nvidia":
|
||
return "windows_nvidia"
|
||
elif hwaccel_available:
|
||
return "high_performance"
|
||
else:
|
||
return "compatibility"
|
||
elif system == "darwin":
|
||
if hwaccel_available and hwaccel_type == "videotoolbox":
|
||
return "macos_videotoolbox"
|
||
else:
|
||
return "universal_software"
|
||
elif system == "linux":
|
||
if hwaccel_available:
|
||
return "high_performance"
|
||
else:
|
||
return "universal_software"
|
||
else:
|
||
return "universal_software"
|
||
|
||
@classmethod
|
||
def get_profile(cls, profile_name: str) -> FFmpegProfile:
|
||
"""
|
||
获取指定的配置文件
|
||
|
||
Args:
|
||
profile_name: 配置文件名称
|
||
|
||
Returns:
|
||
FFmpegProfile: 配置文件对象
|
||
"""
|
||
if profile_name not in cls.PROFILES:
|
||
logger.warning(f"未知的配置文件: {profile_name},使用默认配置")
|
||
profile_name = "universal_software"
|
||
|
||
return cls.PROFILES[profile_name]
|
||
|
||
@classmethod
|
||
def get_extraction_command(cls,
|
||
input_path: str,
|
||
output_path: str,
|
||
timestamp: float,
|
||
profile_name: Optional[str] = None) -> List[str]:
|
||
"""
|
||
根据配置文件生成关键帧提取命令
|
||
|
||
Args:
|
||
input_path: 输入视频路径
|
||
output_path: 输出图片路径
|
||
timestamp: 时间戳
|
||
profile_name: 配置文件名称,None 表示自动选择
|
||
|
||
Returns:
|
||
List[str]: FFmpeg 命令列表
|
||
"""
|
||
if profile_name is None:
|
||
profile_name = cls.get_recommended_profile()
|
||
|
||
profile = cls.get_profile(profile_name)
|
||
|
||
# 构建基础命令
|
||
cmd = [
|
||
"ffmpeg",
|
||
"-hide_banner",
|
||
"-loglevel", "error",
|
||
]
|
||
|
||
# 添加硬件加速参数
|
||
if profile.hwaccel_enabled and profile.hwaccel_type:
|
||
if profile.hwaccel_type == "auto":
|
||
# 自动检测硬件加速
|
||
try:
|
||
from app.utils import ffmpeg_utils
|
||
hw_args = ffmpeg_utils.get_ffmpeg_hwaccel_args()
|
||
cmd.extend(hw_args)
|
||
except Exception:
|
||
pass
|
||
elif profile.hwaccel_type == "nvenc_pure":
|
||
# 纯 NVENC 编码器,不使用硬件解码
|
||
pass
|
||
else:
|
||
# 指定的硬件加速类型
|
||
cmd.extend(["-hwaccel", profile.hwaccel_type])
|
||
|
||
# 添加输入参数
|
||
cmd.extend([
|
||
"-ss", str(timestamp),
|
||
"-i", input_path,
|
||
"-vframes", "1",
|
||
])
|
||
|
||
# 添加质量和格式参数
|
||
if profile.encoder == "libx264":
|
||
cmd.extend(["-q:v", "2"])
|
||
elif profile.encoder == "h264_nvenc":
|
||
cmd.extend(["-cq", "23"])
|
||
elif profile.encoder == "h264_videotoolbox":
|
||
cmd.extend(["-q:v", "65"])
|
||
else:
|
||
cmd.extend(["-q:v", "2"])
|
||
|
||
# 添加像素格式
|
||
cmd.extend(["-pix_fmt", profile.pixel_format])
|
||
|
||
# 添加额外参数
|
||
cmd.extend(profile.additional_args)
|
||
|
||
# 添加输出参数
|
||
cmd.extend(["-y", output_path])
|
||
|
||
return cmd
|
||
|
||
@classmethod
|
||
def list_profiles(cls) -> Dict[str, str]:
|
||
"""
|
||
列出所有可用的配置文件
|
||
|
||
Returns:
|
||
Dict[str, str]: 配置文件名称到描述的映射
|
||
"""
|
||
return {name: profile.description for name, profile in cls.PROFILES.items()}
|
||
|
||
@classmethod
|
||
def get_compatibility_report(cls) -> Dict[str, any]:
|
||
"""
|
||
生成兼容性报告
|
||
|
||
Returns:
|
||
Dict: 兼容性报告
|
||
"""
|
||
recommended_profile = cls.get_recommended_profile()
|
||
profile = cls.get_profile(recommended_profile)
|
||
|
||
try:
|
||
from app.utils import ffmpeg_utils
|
||
hwaccel_info = ffmpeg_utils.get_ffmpeg_hwaccel_info()
|
||
except Exception:
|
||
hwaccel_info = {"available": False, "message": "检测失败"}
|
||
|
||
return {
|
||
"system": platform.system(),
|
||
"recommended_profile": recommended_profile,
|
||
"profile_description": profile.description,
|
||
"compatibility_level": profile.compatibility_level,
|
||
"hardware_acceleration": hwaccel_info,
|
||
"suggestions": cls._get_suggestions(profile, hwaccel_info)
|
||
}
|
||
|
||
@classmethod
|
||
def _get_suggestions(cls, profile: FFmpegProfile, hwaccel_info: Dict) -> List[str]:
|
||
"""生成优化建议"""
|
||
suggestions = []
|
||
|
||
if not hwaccel_info.get("available", False):
|
||
suggestions.append("建议更新显卡驱动以启用硬件加速")
|
||
|
||
if profile.compatibility_level >= 4:
|
||
suggestions.append("当前使用高兼容性配置,性能可能较低")
|
||
|
||
if platform.system().lower() == "windows" and "nvidia" in hwaccel_info.get("gpu_vendor", "").lower():
|
||
suggestions.append("Windows NVIDIA 用户建议使用纯编码器模式避免滤镜链问题")
|
||
|
||
return suggestions
|