d8dd2f1857
移除外部OpenAPI中的API Key管理接口暴露 补齐编辑器项目列表、最近项目、重命名和删除外部接口 补齐素材直传凭证、素材对象确认和签名读取外部接口 复用站内编辑器生成、素材库和项目资源链路并按API Key账号归属 更新外部OpenAPI、后端契约和项目共享记忆文档
235 lines
8.8 KiB
Rust
235 lines
8.8 KiB
Rust
/// 图片画布编辑器生成类能力的泥点配置。
|
|
///
|
|
/// 中文注释:先用 api-server 静态配置收口价格事实源,避免继续把价格散落在
|
|
/// 前端常量和具体 handler 内;后续若接后台配置,可只替换本模块读取来源。
|
|
const EDITOR_IMAGE_MODEL_GPT_IMAGE_2: &str = "gpt-image-2";
|
|
const EDITOR_IMAGE_MODEL_NANOBANANA2: &str = "gemini-3.1-flash-image-preview";
|
|
const EDITOR_IMAGE_MODEL_NANOBANANA2_DISPLAY_ALIAS: &str = "nanobanana2";
|
|
const EDITOR_IMAGE_MODEL_NANOBANANA_LEGACY_ALIAS: &str = "nano-banana";
|
|
const EDITOR_IMAGE_MODEL_GENERATION_MUD_POINTS: u32 = 12;
|
|
const EDITOR_IMAGE_MODEL_GPT_IMAGE_2_MUD_POINTS: u32 = 20;
|
|
const EDITOR_SPEC_MODEL_GPT_IMAGE_2_MUD_POINTS: u32 = 5;
|
|
|
|
pub(crate) const EDITOR_VIDEO_GENERATION_480P_MUD_POINTS_PER_SECOND: u32 = 10;
|
|
pub(crate) const EDITOR_VIDEO_GENERATION_720P_MUD_POINTS_PER_SECOND: u32 = 20;
|
|
|
|
pub(crate) const EDITOR_CHARACTER_ANIMATION_480P_MUD_POINTS_PER_SECOND: u32 = 10;
|
|
pub(crate) const EDITOR_CHARACTER_ANIMATION_720P_MUD_POINTS_PER_SECOND: u32 = 20;
|
|
|
|
const EDITOR_VIDEO_MODEL_SEEDANCE_2: &str = "seedance2.0";
|
|
const EDITOR_VIDEO_MODEL_SEEDANCE_2_FAST: &str = "seedance2.0-fast";
|
|
const EDITOR_VIDEO_MODEL_KLING_3: &str = "kling3.0";
|
|
const EDITOR_VIDEO_MODEL_KLING_3_OMNI: &str = "kling3.0-omni";
|
|
const EDITOR_VIDEO_MODEL_VEO_3_1: &str = "veo3.1";
|
|
const EDITOR_VIDEO_MODEL_VEO_3_1_FAST: &str = "veo3.1-fast";
|
|
const EDITOR_CHARACTER_ANIMATION_MODEL_SEEDANCE_2_FAST: &str = "seedance2.0-fast";
|
|
pub(crate) const EDITOR_SOUND_EFFECT_MODEL_VIDU: &str = "audio1.0";
|
|
pub(crate) const EDITOR_BACKGROUND_MUSIC_MODEL_SUNO: &str = "chirp-v5";
|
|
const EDITOR_SOUND_EFFECT_MODEL_VIDU_MUD_POINTS: u32 = 10;
|
|
const EDITOR_BACKGROUND_MUSIC_MODEL_SUNO_MUD_POINTS: u32 = 5;
|
|
|
|
pub(crate) fn editor_image_model_generation_mud_points(model: Option<&str>) -> u32 {
|
|
match model.map(str::trim).filter(|value| !value.is_empty()) {
|
|
Some(EDITOR_IMAGE_MODEL_GPT_IMAGE_2) => EDITOR_IMAGE_MODEL_GPT_IMAGE_2_MUD_POINTS,
|
|
Some(EDITOR_IMAGE_MODEL_NANOBANANA2)
|
|
| Some(EDITOR_IMAGE_MODEL_NANOBANANA2_DISPLAY_ALIAS)
|
|
| Some(EDITOR_IMAGE_MODEL_NANOBANANA_LEGACY_ALIAS) => {
|
|
EDITOR_IMAGE_MODEL_GENERATION_MUD_POINTS
|
|
}
|
|
_ => EDITOR_IMAGE_MODEL_GENERATION_MUD_POINTS,
|
|
}
|
|
}
|
|
|
|
pub(crate) fn editor_spec_model_generation_mud_points(model: Option<&str>) -> u32 {
|
|
match model.map(str::trim).filter(|value| !value.is_empty()) {
|
|
Some(EDITOR_IMAGE_MODEL_GPT_IMAGE_2) => EDITOR_SPEC_MODEL_GPT_IMAGE_2_MUD_POINTS,
|
|
_ => EDITOR_SPEC_MODEL_GPT_IMAGE_2_MUD_POINTS,
|
|
}
|
|
}
|
|
|
|
pub(crate) fn editor_image_generation_mud_points(kind: Option<&str>, model: Option<&str>) -> u32 {
|
|
match kind.map(str::trim) {
|
|
Some("spec") => editor_spec_model_generation_mud_points(model),
|
|
Some("character" | "icon" | "ui-design" | "publication-material") => {
|
|
editor_image_model_generation_mud_points(model)
|
|
}
|
|
_ => editor_image_model_generation_mud_points(model),
|
|
}
|
|
}
|
|
|
|
fn editor_video_model_resolution_mud_points_per_second(
|
|
model: Option<&str>,
|
|
resolution: &str,
|
|
) -> u32 {
|
|
let normalized_model = match model.map(str::trim).filter(|value| !value.is_empty()) {
|
|
Some(
|
|
EDITOR_VIDEO_MODEL_SEEDANCE_2
|
|
| EDITOR_VIDEO_MODEL_SEEDANCE_2_FAST
|
|
| EDITOR_VIDEO_MODEL_KLING_3
|
|
| EDITOR_VIDEO_MODEL_KLING_3_OMNI
|
|
| EDITOR_VIDEO_MODEL_VEO_3_1
|
|
| EDITOR_VIDEO_MODEL_VEO_3_1_FAST,
|
|
) => model.unwrap_or_default().trim(),
|
|
_ => EDITOR_VIDEO_MODEL_SEEDANCE_2_FAST,
|
|
};
|
|
let (rate_480p, rate_720p) = match normalized_model {
|
|
EDITOR_VIDEO_MODEL_SEEDANCE_2 => (12, 24),
|
|
EDITOR_VIDEO_MODEL_KLING_3 => (15, 30),
|
|
EDITOR_VIDEO_MODEL_KLING_3_OMNI => (20, 40),
|
|
_ => (
|
|
EDITOR_VIDEO_GENERATION_480P_MUD_POINTS_PER_SECOND,
|
|
EDITOR_VIDEO_GENERATION_720P_MUD_POINTS_PER_SECOND,
|
|
),
|
|
};
|
|
if resolution == "720p" {
|
|
rate_720p
|
|
} else {
|
|
rate_480p
|
|
}
|
|
}
|
|
|
|
pub(crate) fn editor_video_model_generation_mud_points(
|
|
model: Option<&str>,
|
|
resolution: &str,
|
|
duration_seconds: u32,
|
|
) -> u32 {
|
|
let per_second = editor_video_model_resolution_mud_points_per_second(model, resolution);
|
|
per_second * duration_seconds
|
|
}
|
|
|
|
pub(crate) fn editor_video_generation_mud_points(resolution: &str, duration_seconds: u32) -> u32 {
|
|
let per_second = editor_video_model_resolution_mud_points_per_second(None, resolution);
|
|
per_second * duration_seconds
|
|
}
|
|
|
|
pub(crate) fn editor_character_animation_model_mud_points(
|
|
model: Option<&str>,
|
|
resolution: &str,
|
|
duration_seconds: u32,
|
|
) -> u32 {
|
|
let _normalized_model = match model.map(str::trim).filter(|value| !value.is_empty()) {
|
|
Some(EDITOR_CHARACTER_ANIMATION_MODEL_SEEDANCE_2_FAST) => {
|
|
EDITOR_CHARACTER_ANIMATION_MODEL_SEEDANCE_2_FAST
|
|
}
|
|
_ => EDITOR_CHARACTER_ANIMATION_MODEL_SEEDANCE_2_FAST,
|
|
};
|
|
let per_second = if resolution == "720p" {
|
|
EDITOR_CHARACTER_ANIMATION_720P_MUD_POINTS_PER_SECOND
|
|
} else {
|
|
EDITOR_CHARACTER_ANIMATION_480P_MUD_POINTS_PER_SECOND
|
|
};
|
|
per_second * duration_seconds
|
|
}
|
|
|
|
pub(crate) fn editor_character_animation_mud_points(
|
|
resolution: &str,
|
|
duration_seconds: u32,
|
|
) -> u32 {
|
|
editor_character_animation_model_mud_points(None, resolution, duration_seconds)
|
|
}
|
|
|
|
pub(crate) fn editor_sound_effect_model_generation_mud_points(model: Option<&str>) -> u32 {
|
|
match model.map(str::trim).filter(|value| !value.is_empty()) {
|
|
Some(EDITOR_SOUND_EFFECT_MODEL_VIDU) => EDITOR_SOUND_EFFECT_MODEL_VIDU_MUD_POINTS,
|
|
_ => EDITOR_SOUND_EFFECT_MODEL_VIDU_MUD_POINTS,
|
|
}
|
|
}
|
|
|
|
pub(crate) fn editor_background_music_model_generation_mud_points(model: Option<&str>) -> u32 {
|
|
match model.map(str::trim).filter(|value| !value.is_empty()) {
|
|
Some(EDITOR_BACKGROUND_MUSIC_MODEL_SUNO) => EDITOR_BACKGROUND_MUSIC_MODEL_SUNO_MUD_POINTS,
|
|
_ => EDITOR_BACKGROUND_MUSIC_MODEL_SUNO_MUD_POINTS,
|
|
}
|
|
}
|
|
|
|
#[cfg(test)]
|
|
mod tests {
|
|
use super::*;
|
|
|
|
#[test]
|
|
fn editor_character_animation_price_uses_configured_resolution_rates() {
|
|
assert_eq!(editor_character_animation_mud_points("480p", 4), 40);
|
|
assert_eq!(editor_character_animation_mud_points("720p", 6), 120);
|
|
}
|
|
|
|
#[test]
|
|
fn editor_video_generation_price_uses_configured_resolution_rates() {
|
|
assert_eq!(editor_video_generation_mud_points("480p", 4), 40);
|
|
assert_eq!(editor_video_generation_mud_points("720p", 5), 100);
|
|
}
|
|
|
|
#[test]
|
|
fn editor_video_generation_price_uses_configured_model_rates() {
|
|
assert_eq!(
|
|
editor_video_model_generation_mud_points(Some("seedance2.0-fast"), "480p", 4),
|
|
40
|
|
);
|
|
assert_eq!(
|
|
editor_video_model_generation_mud_points(Some("seedance2.0"), "720p", 5),
|
|
120
|
|
);
|
|
assert_eq!(
|
|
editor_video_model_generation_mud_points(Some("kling3.0"), "480p", 5),
|
|
75
|
|
);
|
|
assert_eq!(
|
|
editor_video_model_generation_mud_points(Some("kling3.0-omni"), "720p", 4),
|
|
160
|
|
);
|
|
assert_eq!(
|
|
editor_video_model_generation_mud_points(Some("veo3.1"), "480p", 4),
|
|
40
|
|
);
|
|
assert_eq!(
|
|
editor_video_model_generation_mud_points(Some("veo3.1-fast"), "720p", 4),
|
|
80
|
|
);
|
|
}
|
|
|
|
#[test]
|
|
fn editor_audio_generation_price_uses_configured_model_rates() {
|
|
assert_eq!(
|
|
editor_sound_effect_model_generation_mud_points(Some("audio1.0")),
|
|
10
|
|
);
|
|
assert_eq!(
|
|
editor_background_music_model_generation_mud_points(Some("chirp-v5")),
|
|
5
|
|
);
|
|
}
|
|
|
|
#[test]
|
|
fn editor_image_generation_price_uses_configured_kind_rates() {
|
|
assert_eq!(editor_image_generation_mud_points(None, None), 12);
|
|
assert_eq!(editor_image_generation_mud_points(Some("spec"), None), 5);
|
|
assert_eq!(
|
|
editor_image_generation_mud_points(Some("character"), None),
|
|
12
|
|
);
|
|
assert_eq!(editor_image_generation_mud_points(Some("icon"), None), 12);
|
|
assert_eq!(
|
|
editor_image_generation_mud_points(Some("ui-design"), None),
|
|
12
|
|
);
|
|
assert_eq!(
|
|
editor_image_generation_mud_points(
|
|
Some("publication-material"),
|
|
Some("gemini-3.1-flash-image-preview")
|
|
),
|
|
12
|
|
);
|
|
assert_eq!(
|
|
editor_image_generation_mud_points(Some("publication-material"), Some("nanobanana2")),
|
|
12
|
|
);
|
|
assert_eq!(
|
|
editor_image_generation_mud_points(Some("publication-material"), Some("nano-banana")),
|
|
12
|
|
);
|
|
assert_eq!(
|
|
editor_image_generation_mud_points(Some("publication-material"), Some("gpt-image-2")),
|
|
20
|
|
);
|
|
}
|
|
}
|