一键成片优化
This commit is contained in:
@@ -103,7 +103,70 @@ def _script_generation_inflight(project: Project) -> bool:
|
||||
).exists()
|
||||
|
||||
|
||||
def estimate_quick_create_points(
|
||||
*,
|
||||
team,
|
||||
text_model: ModelConfig,
|
||||
image_model: ModelConfig,
|
||||
video_model: ModelConfig,
|
||||
aspect_ratio: str,
|
||||
resolution: str,
|
||||
total_duration: int,
|
||||
):
|
||||
"""与前端按钮预估同口径:脚本挂牌 + 默认出图×场次 + 视频挂牌秒价×时长(无引用视频)。"""
|
||||
from decimal import Decimal
|
||||
|
||||
from apps.billing.pricing import quote_flat, quote_video_estimate
|
||||
|
||||
scene_count = max(1, int(total_duration) // 15)
|
||||
script_points = quote_flat(text_model, units=1, team=team).points
|
||||
image_points = quote_flat(image_model, units=scene_count, team=team).points
|
||||
_tokens, video_quote = quote_video_estimate(
|
||||
video_model,
|
||||
aspect_ratio=aspect_ratio,
|
||||
resolution=resolution,
|
||||
duration=int(total_duration),
|
||||
references=[],
|
||||
team=team,
|
||||
)
|
||||
return Decimal(script_points) + Decimal(image_points) + Decimal(video_quote.points)
|
||||
|
||||
|
||||
def assert_quick_create_balance(
|
||||
*,
|
||||
team,
|
||||
text_model: ModelConfig,
|
||||
image_model: ModelConfig,
|
||||
video_model: ModelConfig,
|
||||
aspect_ratio: str,
|
||||
resolution: str,
|
||||
total_duration: int,
|
||||
):
|
||||
"""提交前确认可用积分 ≥ 预估总额;不足则抛 ValueError(中文提示)。不预留,只门禁。"""
|
||||
from decimal import Decimal
|
||||
|
||||
from apps.billing.models import CreditAccount
|
||||
|
||||
needed = estimate_quick_create_points(
|
||||
team=team,
|
||||
text_model=text_model,
|
||||
image_model=image_model,
|
||||
video_model=video_model,
|
||||
aspect_ratio=aspect_ratio,
|
||||
resolution=resolution,
|
||||
total_duration=total_duration,
|
||||
)
|
||||
account = CreditAccount.objects.filter(team=team).first()
|
||||
available = (account.balance - account.reserved_balance) if account else Decimal("0")
|
||||
if available < needed:
|
||||
raise ValueError(
|
||||
f"团队余额不足,预计需要 {needed} 积分,当前可用 {available} 积分,请充值后再开始"
|
||||
)
|
||||
return needed, available
|
||||
|
||||
|
||||
def get_quick_script_model() -> ModelConfig | None:
|
||||
|
||||
"""极速成片固定复用专业创作的豆包 Seed 2.1 Pro 脚本模型。"""
|
||||
return (
|
||||
ModelConfig.objects.select_related("provider")
|
||||
|
||||
@@ -589,6 +589,22 @@ class ProjectViewSet(TeamScopedViewSetMixin, ModelViewSet):
|
||||
)
|
||||
|
||||
team = self.get_team()
|
||||
# 开工前门禁:可用积分必须盖住「脚本+出图粗估+视频」挂牌合计(与按钮预估同口径)。
|
||||
# 不在这里预留整笔,后续各阶段各自 reserve;这里只避免积不够半路挂掉。
|
||||
from .services.quick_create import assert_quick_create_balance
|
||||
|
||||
try:
|
||||
assert_quick_create_balance(
|
||||
team=team,
|
||||
text_model=text_model,
|
||||
image_model=image_model,
|
||||
video_model=video_model,
|
||||
aspect_ratio=aspect_ratio,
|
||||
resolution=resolution,
|
||||
total_duration=total_duration,
|
||||
)
|
||||
except ValueError as exc:
|
||||
return Response({"detail": str(exc)}, status=status.HTTP_400_BAD_REQUEST)
|
||||
reused_assets = []
|
||||
if source_product_id:
|
||||
try:
|
||||
|
||||
Reference in New Issue
Block a user