fix: 修复 Windows 系统下的 Unicode 编码问题

🐛 问题修复:

1. Unicode 编码错误修复:
   - 移除所有 emoji 字符 (��, ✓, , , , 🚀, 📥, ✗)
   - 使用文本标签替代:[1/4], [成功], [运行中], [失败] 等
   - 避免 Windows GBK 编码无法处理 Unicode 字符的问题

2. Python 脚本编码优化:
   - 添加 UTF-8 编码声明 # -*- coding: utf-8 -*-
   - 改进 progress_callback 函数的错误处理
   - 添加 UnicodeEncodeError 异常捕获和备用方案

3. 进度信息标准化:
   - 视频生成器:[1/4] 上传 → [2/4] 提交 → [3/4] 等待 → [4/4] 下载
   - API 客户端:[运行中], [排队中], [完成], [失败], [超时], [未知]
   - 批量处理:[成功], [失败], [错误] 状态标识

4. 错误处理增强:
   - print 函数添加编码错误处理
   - 确保在 Windows 系统下正常输出中文
   - 保持进度信息的可读性和一致性

 修复效果:
- 解决 'gbk' codec 编码错误 ✓
- Windows 系统下正常显示中文 ✓
- 保持进度信息清晰可读 ✓
- 跨平台编码兼容性 ✓

现在 AI 视频生成功能在 Windows 系统下可以正常工作,不再出现编码错误!
This commit is contained in:
root 2025-07-10 12:38:52 +08:00
parent ed8b854755
commit 9caf551f28
3 changed files with 25 additions and 22 deletions

View File

@ -1,4 +1,5 @@
#!/usr/bin/env python3
# -*- coding: utf-8 -*-
"""
API Client Module
API 客户端模块
@ -236,30 +237,30 @@ class APIClient:
result['data'] = status_result['data']
result['msg'] = 'succeeded'
if progress_callback:
progress_callback(" 视频生成完成!")
progress_callback("[完成] 视频生成完成!")
break
elif status_result['msg'] == 'running':
wait_count += 1
elapsed = wait_count * interval
remaining = max(0, timeout - elapsed)
progress_msg = f" 任务运行中,已等待{elapsed}秒,预计剩余{remaining}秒..."
progress_msg = f"[运行中] 任务运行中,已等待{elapsed}秒,预计剩余{remaining}秒..."
logger.info(progress_msg)
if progress_callback:
progress_callback(progress_msg)
time.sleep(interval)
elif status_result['msg'] == 'failed':
result['msg'] = '任务执行失败'
if progress_callback:
progress_callback(" 任务执行失败")
progress_callback("[失败] 任务执行失败")
break
elif status_result['msg'] in ['pending', 'queued']:
wait_count += 1
elapsed = wait_count * interval
remaining = max(0, timeout - elapsed)
progress_msg = f" 任务排队中,已等待{elapsed}秒,预计剩余{remaining}秒..."
progress_msg = f"[排队中] 任务排队中,已等待{elapsed}秒,预计剩余{remaining}秒..."
logger.info(progress_msg)
if progress_callback:
progress_callback(progress_msg)
@ -270,12 +271,12 @@ class APIClient:
wait_count += 1
logger.info(f"未知状态: {status_result['msg']},继续等待...")
if progress_callback:
progress_callback(f" 状态: {status_result['msg']},继续等待...")
progress_callback(f"[未知] 状态: {status_result['msg']},继续等待...")
time.sleep(interval)
if not result['status'] and result['msg'] == '':
result['msg'] = '任务超时'
if progress_callback:
progress_callback(f" 任务查询超时({timeout}秒)")
progress_callback(f"[超时] 任务查询超时({timeout}秒)")
return result

View File

@ -1,4 +1,5 @@
#!/usr/bin/env python3
# -*- coding: utf-8 -*-
"""
Video Generator Module
视频生成器模块
@ -108,7 +109,7 @@ class VideoGenerator:
# Step 1: Upload image to cloud storage
if progress_callback:
progress_callback("📤 正在上传图片到云存储...")
progress_callback("[1/4] 正在上传图片到云存储...")
logger.info(f"Uploading image to cloud storage: {image_path}")
upload_result = self.cloud_storage.upload_file(image_path)
@ -119,12 +120,12 @@ class VideoGenerator:
img_url = upload_result['data']
if progress_callback:
progress_callback(" 图片上传成功")
progress_callback("[1/4] 图片上传成功")
logger.info(f"Image uploaded successfully: {img_url}")
# Step 2: Submit video generation task
if progress_callback:
progress_callback("🚀 正在提交视频生成任务...")
progress_callback("[2/4] 正在提交视频生成任务...")
logger.info("Submitting video generation task...")
task_result = self.api_client.submit_task(prompt, img_url, duration, model_type)
@ -135,12 +136,12 @@ class VideoGenerator:
task_id = task_result['data']
if progress_callback:
progress_callback(f" 任务提交成功任务ID: {task_id}")
progress_callback(f"[2/4] 任务提交成功任务ID: {task_id}")
logger.info(f"Task submitted successfully, task ID: {task_id}")
# Step 3: Wait for task completion
if progress_callback:
progress_callback(" 正在等待视频生成完成...")
progress_callback("[3/4] 正在等待视频生成完成...")
logger.info("Waiting for video generation to complete...")
completion_result = self.api_client.wait_for_completion(
@ -162,7 +163,7 @@ class VideoGenerator:
# Step 4: Download video if save_path is provided
if save_path:
if progress_callback:
progress_callback("📥 正在下载视频到本地...")
progress_callback("[4/4] 正在下载视频到本地...")
logger.info("Downloading video to local storage...")
video_path = self.cloud_storage.download_file(video_url, save_path)
@ -171,12 +172,12 @@ class VideoGenerator:
result['video_path'] = video_path
result['msg'] = '视频生成并下载成功'
if progress_callback:
progress_callback(f" 视频下载成功: {os.path.basename(video_path)}")
progress_callback(f"[4/4] 视频下载成功: {os.path.basename(video_path)}")
logger.info(f"Video downloaded successfully: {video_path}")
else:
result['msg'] = '视频下载失败'
if progress_callback:
progress_callback(" 视频下载失败")
progress_callback("[4/4] 视频下载失败")
logger.error(result['msg'])
else:
result['status'] = True
@ -288,12 +289,12 @@ class VideoGenerator:
success_count += 1
video_path = video_result.get('video_path', '')
if progress_callback:
progress_callback(f" 视频生成成功: {os.path.basename(video_path)}")
progress_callback(f" [成功] 视频生成成功: {os.path.basename(video_path)}")
else:
failed_count += 1
error_msg = video_result.get('msg', '未知错误') if video_result else '处理失败'
if progress_callback:
progress_callback(f" 视频生成失败: {error_msg}")
progress_callback(f" [失败] 视频生成失败: {error_msg}")
result['results'].append({
'image_path': image_path,
@ -305,7 +306,7 @@ class VideoGenerator:
failed_count += 1
error_msg = str(e)
if progress_callback:
progress_callback(f" 处理图片时出错: {error_msg}")
progress_callback(f" [错误] 处理图片时出错: {error_msg}")
result['results'].append({
'image_path': image_path,
@ -356,7 +357,11 @@ def main():
generator = VideoGenerator()
def progress_callback(message):
print(message)
try:
print(message)
except UnicodeEncodeError:
# Fallback for Windows GBK encoding issues
print(message.encode('utf-8', errors='ignore').decode('utf-8', errors='ignore'))
if args.action == "single":
if not args.image or not args.prompt or not args.output:

View File

@ -157,9 +157,6 @@ const AIVideoGenerator: React.FC<AIVideoGeneratorProps> = ({ className = '' }) =
<div className={`bg-white rounded-lg shadow-sm border border-secondary-200 ${className}`}>
{/* Header */}
<div className="p-6 border-b border-secondary-200">
<h2 className="text-xl font-semibold text-secondary-900 mb-4">AI </h2>
{/* Mode Selection */}
<div className="flex items-center space-x-4 mb-6">
<button
onClick={() => setMode('single')}