diff --git a/app/services/clip_video.py b/app/services/clip_video.py index 72f57e2..29b126b 100644 --- a/app/services/clip_video.py +++ b/app/services/clip_video.py @@ -167,13 +167,25 @@ def clip_video( logger.info(f"裁剪视频片段: {timestamp} -> {ffmpeg_start_time}到{ffmpeg_end_time}") # logger.debug(f"执行命令: {' '.join(ffmpeg_cmd)}") - process = subprocess.run( - ffmpeg_cmd, - stdout=subprocess.PIPE, - stderr=subprocess.PIPE, - text=True, - check=True - ) + # 在Windows系统上使用UTF-8编码处理输出,避免GBK编码错误 + is_windows = os.name == 'nt' + if is_windows: + process = subprocess.run( + ffmpeg_cmd, + stdout=subprocess.PIPE, + stderr=subprocess.PIPE, + encoding='utf-8', # 明确指定编码为UTF-8 + text=True, + check=True + ) + else: + process = subprocess.run( + ffmpeg_cmd, + stdout=subprocess.PIPE, + stderr=subprocess.PIPE, + text=True, + check=True + ) result[_id] = output_path diff --git a/app/services/material.py b/app/services/material.py index 1d4913a..9a3c289 100644 --- a/app/services/material.py +++ b/app/services/material.py @@ -418,13 +418,25 @@ def save_clip_video(timestamp: str, origin_video: str, save_dir: str = "") -> st # logger.info(f"裁剪视频片段: {timestamp} -> {ffmpeg_start_time}到{ffmpeg_end_time}") # logger.debug(f"执行命令: {' '.join(ffmpeg_cmd)}") - process = subprocess.run( - ffmpeg_cmd, - stdout=subprocess.PIPE, - stderr=subprocess.PIPE, - text=True, - check=False # 不抛出异常,我们会检查返回码 - ) + # 在Windows系统上使用UTF-8编码处理输出,避免GBK编码错误 + is_windows = os.name == 'nt' + if is_windows: + process = subprocess.run( + ffmpeg_cmd, + stdout=subprocess.PIPE, + stderr=subprocess.PIPE, + encoding='utf-8', # 明确指定编码为UTF-8 + text=True, + check=False # 不抛出异常,我们会检查返回码 + ) + else: + process = subprocess.run( + ffmpeg_cmd, + stdout=subprocess.PIPE, + stderr=subprocess.PIPE, + text=True, + check=False # 不抛出异常,我们会检查返回码 + ) # 检查是否成功 if process.returncode != 0: @@ -437,7 +449,11 @@ def save_clip_video(timestamp: str, origin_video: str, save_dir: str = "") -> st if os.path.exists(video_path) and os.path.getsize(video_path) > 0: # 检查视频是否可播放 probe_cmd = ["ffprobe", "-v", "error", video_path] - validate_result = subprocess.run(probe_cmd, stdout=subprocess.PIPE, stderr=subprocess.PIPE) + # 在Windows系统上使用UTF-8编码 + if is_windows: + validate_result = subprocess.run(probe_cmd, stdout=subprocess.PIPE, stderr=subprocess.PIPE, encoding='utf-8') + else: + validate_result = subprocess.run(probe_cmd, stdout=subprocess.PIPE, stderr=subprocess.PIPE) if validate_result.returncode == 0: logger.info(f"视频剪辑成功: {video_path}") diff --git a/app/utils/ffmpeg_utils.py b/app/utils/ffmpeg_utils.py index 0425054..58ae83d 100644 --- a/app/utils/ffmpeg_utils.py +++ b/app/utils/ffmpeg_utils.py @@ -26,7 +26,12 @@ def check_ffmpeg_installation() -> bool: bool: 如果安装则返回True,否则返回False """ try: - subprocess.run(['ffmpeg', '-version'], stdout=subprocess.PIPE, stderr=subprocess.PIPE, check=True) + # 在Windows系统上使用UTF-8编码 + is_windows = os.name == 'nt' + if is_windows: + subprocess.run(['ffmpeg', '-version'], stdout=subprocess.PIPE, stderr=subprocess.PIPE, encoding='utf-8', check=True) + else: + subprocess.run(['ffmpeg', '-version'], stdout=subprocess.PIPE, stderr=subprocess.PIPE, check=True) return True except (subprocess.SubprocessError, FileNotFoundError): logger.error("ffmpeg未安装或不在系统PATH中,请安装ffmpeg") @@ -57,10 +62,18 @@ def detect_hardware_acceleration() -> Dict[str, Union[bool, str, List[str], None # 获取FFmpeg支持的硬件加速器列表 try: - hwaccels_cmd = subprocess.run( - ['ffmpeg', '-hide_banner', '-hwaccels'], - stdout=subprocess.PIPE, stderr=subprocess.PIPE, text=True - ) + # 在Windows系统上使用UTF-8编码 + is_windows = os.name == 'nt' + if is_windows: + hwaccels_cmd = subprocess.run( + ['ffmpeg', '-hide_banner', '-hwaccels'], + stdout=subprocess.PIPE, stderr=subprocess.PIPE, encoding='utf-8', text=True + ) + else: + hwaccels_cmd = subprocess.run( + ['ffmpeg', '-hide_banner', '-hwaccels'], + stdout=subprocess.PIPE, stderr=subprocess.PIPE, text=True + ) supported_hwaccels = hwaccels_cmd.stdout.lower() except Exception as e: logger.error(f"获取FFmpeg硬件加速器列表失败: {str(e)}") @@ -141,18 +154,18 @@ def _detect_windows_acceleration(supported_hwaccels: str) -> None: # 添加调试日志 logger.debug(f"Windows检测到NVIDIA显卡,尝试CUDA加速") try: - # 先检查NVENC编码器是否可用 + # 先检查NVENC编码器是否可用,使用UTF-8编码 encoders_cmd = subprocess.run( ["ffmpeg", "-hide_banner", "-encoders"], - stderr=subprocess.PIPE, stdout=subprocess.PIPE, text=True, check=False + stderr=subprocess.PIPE, stdout=subprocess.PIPE, encoding='utf-8', text=True, check=False ) has_nvenc = "h264_nvenc" in encoders_cmd.stdout.lower() logger.debug(f"NVENC编码器检测结果: {'可用' if has_nvenc else '不可用'}") - # 测试CUDA硬件加速 + # 测试CUDA硬件加速,使用UTF-8编码 test_cmd = subprocess.run( ["ffmpeg", "-hwaccel", "cuda", "-i", "NUL", "-f", "null", "-t", "0.1", "-"], - stderr=subprocess.PIPE, stdout=subprocess.PIPE, text=True, check=False + stderr=subprocess.PIPE, stdout=subprocess.PIPE, encoding='utf-8', text=True, check=False ) # 记录详细的返回信息以便调试 @@ -167,10 +180,10 @@ def _detect_windows_acceleration(supported_hwaccels: str) -> None: _FFMPEG_HW_ACCEL_INFO["is_dedicated_gpu"] = True return - # 如果上面的测试失败,尝试另一种方式 + # 如果上面的测试失败,尝试另一种方式,使用UTF-8编码 test_cmd2 = subprocess.run( ["ffmpeg", "-hide_banner", "-loglevel", "error", "-hwaccel", "cuda", "-hwaccel_output_format", "cuda", "-i", "NUL", "-f", "null", "-t", "0.1", "-"], - stderr=subprocess.PIPE, stdout=subprocess.PIPE, text=True, check=False + stderr=subprocess.PIPE, stdout=subprocess.PIPE, encoding='utf-8', text=True, check=False ) if test_cmd2.returncode == 0: @@ -206,7 +219,7 @@ def _detect_windows_acceleration(supported_hwaccels: str) -> None: try: test_cmd = subprocess.run( ["ffmpeg", "-hwaccel", "d3d11va", "-i", "NUL", "-f", "null", "-t", "0.1", "-"], - stderr=subprocess.PIPE, stdout=subprocess.PIPE, text=True, check=False + stderr=subprocess.PIPE, stdout=subprocess.PIPE, encoding='utf-8', text=True, check=False ) # 记录详细的返回信息以便调试 @@ -228,7 +241,7 @@ def _detect_windows_acceleration(supported_hwaccels: str) -> None: try: test_cmd = subprocess.run( ["ffmpeg", "-hwaccel", "dxva2", "-i", "NUL", "-f", "null", "-t", "0.1", "-"], - stderr=subprocess.PIPE, stdout=subprocess.PIPE, text=True, check=False + stderr=subprocess.PIPE, stdout=subprocess.PIPE, encoding='utf-8', text=True, check=False ) # 记录详细的返回信息以便调试 @@ -248,18 +261,18 @@ def _detect_windows_acceleration(supported_hwaccels: str) -> None: if 'nvidia' in gpu_info.lower(): logger.debug("Windows检测到NVIDIA显卡,尝试直接使用NVENC编码器") try: - # 检查NVENC编码器是否可用 + # 检查NVENC编码器是否可用,使用UTF-8编码 encoders_cmd = subprocess.run( ["ffmpeg", "-hide_banner", "-encoders"], - stderr=subprocess.PIPE, stdout=subprocess.PIPE, text=True, check=False + stderr=subprocess.PIPE, stdout=subprocess.PIPE, encoding='utf-8', text=True, check=False ) if "h264_nvenc" in encoders_cmd.stdout.lower(): logger.debug("NVENC编码器可用,尝试直接使用") - # 测试NVENC编码器 + # 测试NVENC编码器,使用UTF-8编码 test_cmd = subprocess.run( ["ffmpeg", "-f", "lavfi", "-i", "color=c=black:s=640x360:r=30", "-c:v", "h264_nvenc", "-t", "0.1", "-f", "null", "-"], - stderr=subprocess.PIPE, stdout=subprocess.PIPE, text=True, check=False + stderr=subprocess.PIPE, stdout=subprocess.PIPE, encoding='utf-8', text=True, check=False ) logger.debug(f"NVENC编码器测试返回码: {test_cmd.returncode}") @@ -365,17 +378,17 @@ def _get_windows_gpu_info() -> str: str: 显卡信息字符串 """ try: - # 使用PowerShell获取更可靠的显卡信息 + # 使用PowerShell获取更可靠的显卡信息,并使用UTF-8编码 gpu_info = subprocess.run( ['powershell', '-Command', "Get-WmiObject Win32_VideoController | Select-Object Name | Format-List"], - stdout=subprocess.PIPE, stderr=subprocess.PIPE, text=True, check=False + stdout=subprocess.PIPE, stderr=subprocess.PIPE, encoding='utf-8', text=True, check=False ) # 如果PowerShell失败,尝试使用wmic if not gpu_info.stdout.strip(): gpu_info = subprocess.run( ['wmic', 'path', 'win32_VideoController', 'get', 'name'], - stdout=subprocess.PIPE, stderr=subprocess.PIPE, text=True, check=False + stdout=subprocess.PIPE, stderr=subprocess.PIPE, encoding='utf-8', text=True, check=False ) # 记录详细的显卡信息以便调试 diff --git a/webui.py b/webui.py index 4180824..9d82838 100644 --- a/webui.py +++ b/webui.py @@ -189,17 +189,23 @@ def render_generate_button(): logger.info(tr("视频生成完成")) +# 全局变量,记录是否已经打印过硬件加速信息 +_HAS_LOGGED_HWACCEL_INFO = False + def main(): """主函数""" + global _HAS_LOGGED_HWACCEL_INFO init_log() init_global_state() - # 检测FFmpeg硬件加速 + # 检测FFmpeg硬件加速,但只打印一次日志 hwaccel_info = ffmpeg_utils.detect_hardware_acceleration() - if hwaccel_info["available"]: - logger.info(f"FFmpeg硬件加速检测结果: 可用 | 类型: {hwaccel_info['type']} | 编码器: {hwaccel_info['encoder']} | 独立显卡: {hwaccel_info['is_dedicated_gpu']} | 参数: {hwaccel_info['hwaccel_args']}") - else: - logger.warning(f"FFmpeg硬件加速不可用: {hwaccel_info['message']}, 将使用CPU软件编码") + if not _HAS_LOGGED_HWACCEL_INFO: + if hwaccel_info["available"]: + logger.info(f"FFmpeg硬件加速检测结果: 可用 | 类型: {hwaccel_info['type']} | 编码器: {hwaccel_info['encoder']} | 独立显卡: {hwaccel_info['is_dedicated_gpu']} | 参数: {hwaccel_info['hwaccel_args']}") + else: + logger.warning(f"FFmpeg硬件加速不可用: {hwaccel_info['message']}, 将使用CPU软件编码") + _HAS_LOGGED_HWACCEL_INFO = True # 仅初始化基本资源,避免过早地加载依赖PyTorch的资源 # 检查是否能分解utils.init_resources()为基本资源和高级资源(如依赖PyTorch的资源)