| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195 |
- """
- DecodeVideo 模型
- 对应数据库表 decode_videos 的 ORM 模型
- """
- from enum import IntEnum
- from typing import Optional
- from sqlalchemy import Column, String, BigInteger, Integer, Text, DateTime
- from sqlalchemy.sql import func
- from src.models.database import Base
- from src.utils.logger import get_logger
- logger = get_logger(__name__)
- class DecodeStatus(IntEnum):
- """解码状态枚举
-
- 对应数据库字段 status 的值:
- - PENDING: 0 - 待执行
- - EXECUTING: 1 - 执行中
- - SUCCESS: 2 - 执行成功
- - FAILED: 3 - 执行失败
- """
- PENDING = 0
- EXECUTING = 1
- SUCCESS = 2
- FAILED = 3
-
- @classmethod
- def get_description(cls, status: int) -> str:
- """获取状态描述
-
- Args:
- status: 状态值
-
- Returns:
- str: 状态描述
- """
- descriptions = {
- cls.PENDING: "待执行",
- cls.EXECUTING: "执行中",
- cls.SUCCESS: "执行成功",
- cls.FAILED: "执行失败",
- }
- return descriptions.get(status, "未知状态")
- class DecodeVideo(Base):
- """解码视频模型
-
- 对应数据库表: decode_videos
-
- 字段说明:
- - video_id: 视频ID (varchar(100), nullable)
- - task_id: 任务ID (bigint, not null)
- - result: 解码结果 (mediumtext, nullable)
- - decode_result_v2: 解码结果V2 (mediumtext, nullable) - ScriptWorkflowV2分支的结果
- - search_keywords: 搜索关键词 (text, nullable) - 字符串数组的JSON格式
- - status: 状态 (int, nullable) - 0:待执行 / 1:执行中 / 2:执行成功 / 3:执行失败
- - error_reason: 失败原因 (mediumtext, nullable)
- """
-
- __tablename__ = "decode_videos"
-
- # 主键:使用 task_id 作为主键(根据业务需求,可能需要调整)
- task_id = Column(BigInteger, primary_key=True, nullable=False, comment="任务ID")
-
- # 视频ID
- video_id = Column(String(100), nullable=True, index=True, comment="视频ID")
-
- # 解码结果(JSON 格式)
- result = Column(Text, nullable=True, comment="解码结果")
-
- # 解码结果V2(分支2的结果,JSON 格式)
- decode_result_v2 = Column(Text, nullable=True, comment="解码结果V2(ScriptWorkflowV2分支结果)")
-
- # 搜索关键词(字符串数组的JSON格式)
- search_keywords = Column(Text, nullable=True, comment="搜索关键词(字符串数组的JSON格式)")
-
- # 状态
- status = Column(Integer, nullable=True, default=int(DecodeStatus.PENDING), index=True, comment="状态: 0:待执行 / 1:执行中 / 2:执行成功 / 3:执行失败")
-
- # 失败原因
- error_reason = Column(Text, nullable=True, comment="失败原因")
-
- # 时间戳字段(可选,用于记录创建和更新时间)
- created_at = Column(DateTime, nullable=True, server_default=func.now(), comment="创建时间")
- updated_at = Column(DateTime, nullable=True, server_default=func.now(), onupdate=func.now(), comment="更新时间")
-
- def __repr__(self) -> str:
- """对象字符串表示"""
- return f"<DecodeVideo(task_id={self.task_id}, video_id={self.video_id}, status={self.status})>"
-
- def to_dict(self) -> dict:
- """转换为字典
-
- Returns:
- dict: 模型数据字典
- """
- return {
- "task_id": self.task_id,
- "video_id": self.video_id,
- "result": self.result,
- "decode_result_v2": self.decode_result_v2,
- "search_keywords": self.search_keywords,
- "status": self.status,
- "error_reason": self.error_reason,
- "created_at": self.created_at.isoformat() if self.created_at else None,
- "updated_at": self.updated_at.isoformat() if self.updated_at else None,
- }
-
- @classmethod
- def create(
- cls,
- task_id: int,
- video_id: Optional[str] = None,
- status: Optional[int] = None,
- result: Optional[str] = None,
- decode_result_v2: Optional[str] = None,
- error_reason: Optional[str] = None
- ) -> "DecodeVideo":
- """创建新的解码视频记录
-
- Args:
- task_id: 任务ID
- video_id: 视频ID
- status: 状态(默认: PENDING)
- result: 解码结果
- decode_result_v2: 解码结果V2(ScriptWorkflowV2分支结果)
- error_reason: 失败原因
-
- Returns:
- DecodeVideo: 新创建的模型实例
- """
- # 统一将枚举转换为整型值
- if status is None:
- status_value = int(DecodeStatus.PENDING)
- else:
- try:
- # 支持传入 IntEnum 或具体的整数
- status_value = int(status)
- except Exception:
- status_value = int(DecodeStatus.PENDING)
- return cls(
- task_id=task_id,
- video_id=video_id,
- status=status_value,
- created_at=func.now(),
- result=result,
- decode_result_v2=decode_result_v2,
- error_reason=error_reason
- )
-
- def update_status(self, status: DecodeStatus, error_reason: Optional[str] = None):
- """更新状态
-
- Args:
- status: 新状态
- error_reason: 失败原因(仅在失败时使用)
- """
- self.status = status.value
- if status == DecodeStatus.FAILED and error_reason:
- self.error_reason = error_reason
- elif status != DecodeStatus.FAILED:
- self.error_reason = None
-
- def update_result(self, result: str):
- """更新解码结果
-
- Args:
- result: 解码结果(JSON 字符串)
- """
- self.result = result
- if self.status == DecodeStatus.EXECUTING:
- self.update_status(DecodeStatus.SUCCESS)
-
- def update_result_v2(self, result_v2: str):
- """更新解码结果V2(ScriptWorkflowV2分支结果)
-
- Args:
- result_v2: 解码结果V2(JSON 字符串)
- """
- self.decode_result_v2 = result_v2
-
- def update_search_keywords(self, search_keywords: str):
- """更新搜索关键词(字符串数组的JSON格式)
-
- Args:
- search_keywords: 搜索关键词(字符串数组的JSON格式,如:["关键词1", "关键词2"])
- """
- self.search_keywords = search_keywords
|