Merge branch 'main' of https://gitee.com/wg123/video-gen
This commit is contained in:
@@ -0,0 +1,37 @@
|
||||
"""2026070901_add_credits_ratio_增加上传图片积分规则
|
||||
|
||||
Revision ID: 2026070901
|
||||
Revises: 6c1aaf036f43
|
||||
Create Date: 2026-07-01 00:00:00.000000
|
||||
|
||||
该文件包含 2026-07-01 的数据库迁移内容:
|
||||
1. 积分规则表增加传入视频计费字段(input_video_ratio, input_video_base_credits, input_video_per_second_credits)
|
||||
"""
|
||||
from typing import Sequence, Union
|
||||
|
||||
from alembic import op
|
||||
import sqlalchemy as sa
|
||||
|
||||
|
||||
revision: str = '2026070901'
|
||||
down_revision: Union[str, None] = '6c1aaf036f43'
|
||||
branch_labels: Union[str, Sequence[str], None] = None
|
||||
depends_on: Union[str, Sequence[str], None] = None
|
||||
|
||||
|
||||
def upgrade() -> None:
|
||||
# ========================================
|
||||
# 2026-07-01 - 积分规则表增加传入图片计费字段
|
||||
# ========================================
|
||||
op.add_column('credit_ratios', sa.Column('input_image_ratio', sa.Float(), server_default='1.0', nullable=False))
|
||||
op.add_column('credit_ratios', sa.Column('input_image_base_credits', sa.Float(), server_default='0.0', nullable=False))
|
||||
op.add_column('credit_ratios', sa.Column('input_image_per_image_credits', sa.Float(), server_default='0.5', nullable=False))
|
||||
|
||||
|
||||
def downgrade() -> None:
|
||||
# ========================================
|
||||
# 2026-07-01 - 积分规则表增加传入图片计费字段(回滚)
|
||||
# ========================================
|
||||
op.drop_column('credit_ratios', 'input_image_per_image_credits')
|
||||
op.drop_column('credit_ratios', 'input_image_base_credits')
|
||||
op.drop_column('credit_ratios', 'input_image_ratio')
|
||||
@@ -1383,6 +1383,7 @@ async def create_credit_ratio(
|
||||
ensure_ascii=False,
|
||||
),
|
||||
)
|
||||
await db.commit()
|
||||
return ratio
|
||||
|
||||
|
||||
@@ -1422,6 +1423,7 @@ async def update_credit_ratio(
|
||||
ensure_ascii=False,
|
||||
),
|
||||
)
|
||||
await db.commit()
|
||||
return ratio
|
||||
|
||||
|
||||
@@ -1455,6 +1457,7 @@ async def delete_credit_ratio(
|
||||
ensure_ascii=False,
|
||||
),
|
||||
)
|
||||
await db.commit()
|
||||
return {"message": "ok"}
|
||||
|
||||
|
||||
|
||||
@@ -29,7 +29,7 @@ async def lifespan(app: FastAPI):
|
||||
os.makedirs(settings.UPLOAD_LOCAL_PATH, exist_ok=True)
|
||||
await init_database()
|
||||
await init_redis()
|
||||
await _seed_data()
|
||||
# await _seed_data()
|
||||
|
||||
# Start task queue (handles both video and image generation)
|
||||
from app.services.video_queue import task_queue
|
||||
|
||||
@@ -25,3 +25,6 @@ class CreditRatio(Base, TimestampMixin):
|
||||
input_video_ratio: Mapped[float] = mapped_column(Float, default=1.0)
|
||||
input_video_base_credits: Mapped[float] = mapped_column(Float, default=0.0)
|
||||
input_video_per_second_credits: Mapped[float] = mapped_column(Float, default=0.5)
|
||||
input_image_ratio: Mapped[float] = mapped_column(Float, default=1.0)
|
||||
input_image_base_credits: Mapped[float] = mapped_column(Float, default=0.0)
|
||||
input_image_per_image_credits: Mapped[float] = mapped_column(Float, default=0.0)
|
||||
|
||||
@@ -61,6 +61,24 @@ class CreditRatioCreate(BaseModel):
|
||||
description="传入视频每秒积分。视频生成时,用户上传参考视频每秒消耗的积分",
|
||||
examples=[0.5],
|
||||
)
|
||||
input_image_ratio: float = Field(
|
||||
default=1.0,
|
||||
ge=0,
|
||||
description="传入图片积分倍率。图片生成时,用户上传参考图片的额外积分倍率",
|
||||
examples=[1.0],
|
||||
)
|
||||
input_image_base_credits: float = Field(
|
||||
default=0.0,
|
||||
ge=0,
|
||||
description="传入图片基础积分。图片生成时,用户上传参考图片的基础积分",
|
||||
examples=[0.0],
|
||||
)
|
||||
input_image_per_image_credits: float = Field(
|
||||
default=0.0,
|
||||
ge=0,
|
||||
description="传入图片每张积分。图片生成时,用户上传参考图片每张消耗的积分",
|
||||
examples=[0.0],
|
||||
)
|
||||
|
||||
|
||||
class CreditRatioOut(CreditRatioCreate):
|
||||
|
||||
@@ -66,6 +66,7 @@ async def calc_video_credits(
|
||||
resolution: str,
|
||||
engine_id: str | None = None,
|
||||
input_video_duration: float | None = None,
|
||||
input_image_count: int | None = None,
|
||||
) -> float:
|
||||
"""Calculate video credits using CreditRatio table, with fallback to hardcoded.
|
||||
|
||||
@@ -75,6 +76,7 @@ async def calc_video_credits(
|
||||
3. 原硬编码默认算法。
|
||||
|
||||
input_video_duration: 用户上传的参考视频总时长(秒),不为空时额外计费
|
||||
input_image_count: 用户上传的参考图片数量,不为空时额外计费
|
||||
"""
|
||||
if not engine_id:
|
||||
video_engines_result = await db.execute(
|
||||
@@ -97,6 +99,11 @@ async def calc_video_credits(
|
||||
ratio.input_video_base_credits + ratio.input_video_per_second_credits * input_video_duration
|
||||
) * ratio.input_video_ratio
|
||||
base_cost += input_video_cost
|
||||
if input_image_count and input_image_count > 0:
|
||||
input_image_cost = (
|
||||
ratio.input_image_base_credits + ratio.input_image_per_image_credits * input_image_count
|
||||
) * ratio.input_image_ratio
|
||||
base_cost += input_image_cost
|
||||
return round(base_cost, 2)
|
||||
|
||||
base = 60.0
|
||||
@@ -105,6 +112,8 @@ async def calc_video_credits(
|
||||
total = (base + duration_cost) * multiplier
|
||||
if input_video_duration and input_video_duration > 0:
|
||||
total += input_video_duration * 0.5 * multiplier
|
||||
if input_image_count and input_image_count > 0:
|
||||
total += input_image_count * 0.5 * multiplier
|
||||
return round(total, 2)
|
||||
|
||||
|
||||
@@ -120,6 +129,7 @@ async def calc_image_credits(
|
||||
db: AsyncSession,
|
||||
image_size: str,
|
||||
engine_id: str | None = None,
|
||||
input_image_count: int | None = None,
|
||||
) -> float:
|
||||
"""Calculate image credits using CreditRatio table, with fallback to hardcoded.
|
||||
|
||||
@@ -127,6 +137,8 @@ async def calc_image_credits(
|
||||
1. gen_type=image + engine_id + image_size 精确规则;
|
||||
2. gen_type=image + image_size 下 base_credits/per_second_credits 最高规则;
|
||||
3. 原硬编码默认算法。
|
||||
|
||||
input_image_count: 用户上传的参考图片数量,不为空时额外计费
|
||||
"""
|
||||
# 如果engine_id为空,默认查询权重最高的图片引擎积分规则
|
||||
if not engine_id:
|
||||
@@ -144,12 +156,21 @@ async def calc_image_credits(
|
||||
engine_id=engine_id,
|
||||
)
|
||||
if ratio:
|
||||
return round(ratio.base_credits * ratio.ratio, 2)
|
||||
base_cost = ratio.base_credits * ratio.ratio
|
||||
if input_image_count and input_image_count > 0:
|
||||
input_image_cost = (
|
||||
ratio.input_image_base_credits + ratio.input_image_per_image_credits * input_image_count
|
||||
) * ratio.input_image_ratio
|
||||
base_cost += input_image_cost
|
||||
return round(base_cost, 2)
|
||||
|
||||
# Fallback
|
||||
multiplier = {"4K": 2.0, "2K": 1.0}.get(image_size, 1.0)
|
||||
base_cost = 4.0
|
||||
return round(base_cost * multiplier, 2)
|
||||
total = base_cost * multiplier
|
||||
if input_image_count and input_image_count > 0:
|
||||
total += input_image_count * 0.5 * multiplier
|
||||
return round(total, 2)
|
||||
|
||||
|
||||
async def _get_existing_credit_record_by_biz_key(
|
||||
|
||||
Reference in New Issue
Block a user