测试极速成片
This commit is contained in:
@@ -8,7 +8,7 @@ from django.http import HttpResponse, JsonResponse, StreamingHttpResponse
|
||||
from django.utils import timezone
|
||||
from rest_framework import status
|
||||
from rest_framework.decorators import action
|
||||
from rest_framework.exceptions import ValidationError
|
||||
from rest_framework.exceptions import APIException, ValidationError
|
||||
from rest_framework.parsers import FormParser, MultiPartParser
|
||||
from rest_framework.renderers import BaseRenderer
|
||||
from rest_framework.response import Response
|
||||
@@ -95,6 +95,12 @@ from .tasks import poll_video_segment_task
|
||||
logger = logging.getLogger(__name__)
|
||||
|
||||
|
||||
class QuickCreateInProgress(APIException):
|
||||
status_code = status.HTTP_409_CONFLICT
|
||||
default_detail = "该项目正在极速成片中,请到极速成片页查看进度"
|
||||
default_code = "quick_create_running"
|
||||
|
||||
|
||||
class ServerSentEventRenderer(BaseRenderer):
|
||||
"""让 DRF 内容协商接受 Accept: text/event-stream(否则流式端点直接 406)。
|
||||
实际响应由视图返回 StreamingHttpResponse 直接下发,这个 renderer 只用于通过协商。"""
|
||||
@@ -235,7 +241,7 @@ def settle_video_completion(project: Project) -> bool:
|
||||
|
||||
|
||||
class ProjectViewSet(TeamScopedViewSetMixin, ModelViewSet):
|
||||
queryset = Project.objects.select_related("product", "timeline").prefetch_related(
|
||||
queryset = Project.objects.select_related("product", "timeline", "quick_create_job").prefetch_related(
|
||||
"stages",
|
||||
"video_segments",
|
||||
"video_segments__adopted_version__asset__files",
|
||||
@@ -339,7 +345,7 @@ class ProjectViewSet(TeamScopedViewSetMixin, ModelViewSet):
|
||||
# ——原列表把每个项目的 阶段/片段/故事板/时间线/资产文件全拉出,20 个项目实测 ~2s。
|
||||
if self.action == "list":
|
||||
qs = (
|
||||
Project.objects.select_related("product", "product__cover_asset", "timeline")
|
||||
Project.objects.select_related("product", "product__cover_asset", "timeline", "quick_create_job")
|
||||
.prefetch_related(
|
||||
"product__cover_asset__files",
|
||||
# 成片地址(final_video_url)只需要「成功的导出任务」,预取到位后列表不再逐项目查库
|
||||
@@ -363,6 +369,21 @@ class ProjectViewSet(TeamScopedViewSetMixin, ModelViewSet):
|
||||
).order_by("-updated_at")
|
||||
return super().get_queryset().filter(is_deleted=False, purged_at__isnull=True)
|
||||
|
||||
def initial(self, request, *args, **kwargs):
|
||||
super().initial(request, *args, **kwargs)
|
||||
if request.method in ("GET", "HEAD", "OPTIONS"):
|
||||
return
|
||||
if self.action in {"create", "destroy"}:
|
||||
return
|
||||
pk = kwargs.get("pk")
|
||||
if not pk:
|
||||
return
|
||||
if QuickCreateJob.objects.filter(
|
||||
project_id=pk,
|
||||
status__in=[QuickCreateJob.Status.QUEUED, QuickCreateJob.Status.RUNNING],
|
||||
).exists():
|
||||
raise QuickCreateInProgress()
|
||||
|
||||
def perform_destroy(self, instance):
|
||||
instance.is_deleted = True
|
||||
instance.save(update_fields=["is_deleted", "updated_at"])
|
||||
@@ -730,30 +751,19 @@ class ProjectViewSet(TeamScopedViewSetMixin, ModelViewSet):
|
||||
job = self._quick_job_queryset().get(id=job.id)
|
||||
return Response(QuickCreateJobSerializer(job).data)
|
||||
|
||||
@action(detail=False, methods=["post"], url_path=r"quick-create-retry/(?P<job_id>[^/.]+)")
|
||||
def quick_create_retry(self, request, job_id=None):
|
||||
job = self._quick_job_queryset().filter(id=job_id).first()
|
||||
if job is None:
|
||||
return Response({"detail": "极速成片任务不存在"}, status=status.HTTP_404_NOT_FOUND)
|
||||
if job.status == QuickCreateJob.Status.SUCCEEDED:
|
||||
return Response({"detail": "任务已经完成"}, status=status.HTTP_400_BAD_REQUEST)
|
||||
if job.status == QuickCreateJob.Status.CANCELLED:
|
||||
return Response({"detail": "已取消的任务请重新开始"}, status=status.HTTP_400_BAD_REQUEST)
|
||||
from .services.quick_create import resume_quick_create
|
||||
|
||||
resume_quick_create(job)
|
||||
job = self._quick_job_queryset().get(id=job.id)
|
||||
return Response(QuickCreateJobSerializer(job).data)
|
||||
|
||||
@action(detail=False, methods=["get"], url_path="quick-create-history")
|
||||
def quick_create_history(self, request):
|
||||
from .services.quick_create import restore_false_failed_quick_creates
|
||||
|
||||
restore_false_failed_quick_creates(self.get_team())
|
||||
# 进行中的任务看上方状态卡;列表要能找回失败后去专业模式继续的项目。
|
||||
# 进行中 / 未完成的任务回填上方表单;过往列表只放已完成成片。
|
||||
jobs = (
|
||||
self._quick_job_queryset()
|
||||
.exclude(status__in=[QuickCreateJob.Status.QUEUED, QuickCreateJob.Status.RUNNING])
|
||||
.filter(
|
||||
project__is_deleted=False,
|
||||
project__purged_at__isnull=True,
|
||||
status=QuickCreateJob.Status.SUCCEEDED,
|
||||
)
|
||||
.order_by("-created_at")
|
||||
)
|
||||
return Response({
|
||||
@@ -975,8 +985,9 @@ class ProjectViewSet(TeamScopedViewSetMixin, ModelViewSet):
|
||||
prompt=request.data.get("prompt", ""),
|
||||
label=request.data.get("label", ""),
|
||||
reference_asset_id=request.data.get("reference_asset_id") or None,
|
||||
# 角色立绘不再自动接力三视图;三视图只由角色详情里的显式按钮生成。
|
||||
auto_triview=False,
|
||||
# 用户点击角色 AI 生成 = 生成立绘并在完成后自动接力三视图。
|
||||
# 三视图任务由 worker 创建,页面刷新或离开也不会漏掉。
|
||||
auto_triview=kind == BaseAssetGroup.Kind.PERSON,
|
||||
)
|
||||
except ValueError as exc: # 无可用模型 / 余额不足等,立即反馈
|
||||
internal_kind = "user_credit_insufficient" if str(exc).strip().lower() == "insufficient credit" else ""
|
||||
@@ -1453,7 +1464,14 @@ class ProjectViewSet(TeamScopedViewSetMixin, ModelViewSet):
|
||||
# 火山/中转报错(如人脸需走素材库的 InputImageSensitiveContentDetected)→ 返回真实报错的 JSON,
|
||||
# 任务仍保留原始错误供排障,但普通用户仅收到安全错误对象,不让 500 HTML 导致前端白屏。
|
||||
try:
|
||||
submit_video_segment(video_segment=segment, user=request.user, prompt=request.data.get("prompt", ""))
|
||||
submit_video_segment(
|
||||
video_segment=segment,
|
||||
user=request.user,
|
||||
prompt=request.data.get("prompt", ""),
|
||||
model_config_id=request.data.get("model_config_id") or None,
|
||||
aspect_ratio=request.data.get("aspect_ratio") or None,
|
||||
resolution=request.data.get("resolution") or None,
|
||||
)
|
||||
except Exception as exc: # noqa: BLE001
|
||||
public_error = classify_generation_error(exc, operation="video_generate")
|
||||
return Response(
|
||||
|
||||
Reference in New Issue
Block a user