GitHub Action
Deploy from GitHub Actions - Fri Jun 20 07:41:03 UTC 2025
ac251c6
Raw
History Blame Contribute Delete
5.11 kB
"""
任务数据模型
定义转换任务的数据结构
"""
from enum import Enum
from dataclasses import dataclass, field
from typing import Optional, Dict, List, Any
from datetime import datetime
import uuid
class TaskStatus(Enum):
"""任务状态枚举"""
PENDING = "pending" # 任务已创建,等待处理
QUEUED = "queued" # 任务在队列中等待
PROCESSING = "processing" # 正在处理中
CONVERTING = "converting" # 正在转换音频
UPLOADING = "uploading" # 正在上传结果
COMPLETED = "completed" # 转换完成
FAILED = "failed" # 转换失败
CANCELLED = "cancelled" # 任务已取消
@dataclass
class VoiceSettings:
"""语音设置"""
language: str = "zh-CN"
voice_name: str = "xiaoxiao"
speed: float = 1.0
pitch: int = 0
volume: float = 0.8
@dataclass
class ProcessingDetails:
"""处理详情"""
total_segments: int = 0
completed_segments: int = 0
current_segment: str = ""
audio_duration: str = "0分0秒"
error_message: Optional[str] = None
@dataclass
class AudioFile:
"""音频文件信息"""
title: str
url: str
duration: str
file_size: int = 0
chapter_id: str = ""
@dataclass
class ConversionTask:
"""转换任务模型"""
task_id: str = field(default_factory=lambda: f"audio_{uuid.uuid4()}")
status: TaskStatus = TaskStatus.PENDING
# 输入信息
file_url: str = ""
original_filename: str = ""
user_id: Optional[str] = None # 从文件URL解析的用户ID
original_task_id: Optional[str] = None # 从文件URL解析的原始任务ID
r2_file_path: Optional[str] = None # R2存储路径(新增)
# 转换配置
voice_settings: VoiceSettings = field(default_factory=VoiceSettings)
output_formats: List[str] = field(default_factory=lambda: ["mp3"])
audio_quality: str = "high"
split_by_chapter: bool = True
max_segment_length: int = 300
# 进度信息
progress: int = 0
current_stage: str = ""
queue_position: int = 0
# 时间信息
created_at: datetime = field(default_factory=datetime.now)
started_at: Optional[datetime] = None
completed_at: Optional[datetime] = None
estimated_completion: Optional[datetime] = None
# 处理详情
processing_details: ProcessingDetails = field(default_factory=ProcessingDetails)
# 结果信息
audio_files: Dict[str, Any] = field(default_factory=dict)
metadata: Dict[str, Any] = field(default_factory=dict)
# 错误信息
error_message: Optional[str] = None
retry_count: int = 0
max_retries: int = 3
def to_dict(self) -> Dict[str, Any]:
"""转换为字典格式"""
return {
"task_id": self.task_id,
"status": self.status.value,
"progress": self.progress,
"current_stage": self.current_stage,
"created_at": self.created_at.isoformat(),
"started_at": self.started_at.isoformat() if self.started_at else None,
"completed_at": (
self.completed_at.isoformat() if self.completed_at else None
),
"estimated_completion": (
self.estimated_completion.isoformat()
if self.estimated_completion
else None
),
"queue_position": self.queue_position,
"processing_details": {
"total_segments": self.processing_details.total_segments,
"completed_segments": self.processing_details.completed_segments,
"current_segment": self.processing_details.current_segment,
"audio_duration": self.processing_details.audio_duration,
},
"original_filename": self.original_filename,
"user_id": self.user_id,
"original_task_id": self.original_task_id,
"r2_file_path": self.r2_file_path,
"audio_files": self.audio_files,
"metadata": self.metadata,
"error_message": self.error_message,
}
def update_progress(self, progress: int, stage: str, segment: str = ""):
"""更新任务进度"""
self.progress = progress
self.current_stage = stage
if segment:
self.processing_details.current_segment = segment
def mark_failed(self, error_message: str):
"""标记任务失败"""
self.status = TaskStatus.FAILED
self.error_message = error_message
self.completed_at = datetime.now()
def mark_completed(self):
"""标记任务完成"""
self.status = TaskStatus.COMPLETED
self.progress = 100
self.current_stage = "转换完成"
self.completed_at = datetime.now()
def can_retry(self) -> bool:
"""检查是否可以重试"""
return self.retry_count < self.max_retries and self.status == TaskStatus.FAILED
def increment_retry(self):
"""增加重试次数"""
self.retry_count += 1
self.status = TaskStatus.PENDING
self.error_message = None