Files
Genarrative/server-rs/crates/shared-contracts/src/creation_audio.rs
T
kdletters e9c3dc1120 退役旧创作模板业务
保留 SpacetimeDB 历史表、迁移白名单与旧业务源码
切换前端 active 入口并解除旧创作页面和路由编译链
移除旧后端路由、worker 与纯业务 crate 依赖
收敛 SpacetimeDB 模块为历史数据壳
同步 Nginx、Pingora、验证门禁与架构文档
2026-07-17 22:07:52 +08:00

152 lines
4.8 KiB
Rust

use serde::{Deserialize, Serialize};
#[derive(Clone, Debug, Serialize, Deserialize, PartialEq, Eq)]
#[serde(rename_all = "snake_case")]
pub enum CreationAudioGenerationKind {
BackgroundMusic,
SoundEffect,
}
#[derive(Clone, Debug, Serialize, Deserialize, PartialEq, Eq)]
#[serde(rename_all = "camelCase")]
#[cfg(any())]
pub struct CreationAudioAsset {
pub task_id: String,
pub provider: String,
#[serde(default)]
pub asset_object_id: Option<String>,
#[serde(default)]
pub asset_kind: Option<String>,
pub audio_src: String,
#[serde(default)]
pub prompt: Option<String>,
#[serde(default)]
pub title: Option<String>,
#[serde(default)]
pub updated_at: Option<String>,
}
#[derive(Clone, Debug, Serialize, Deserialize, PartialEq, Eq)]
#[serde(rename_all = "camelCase")]
#[cfg(any())]
pub struct CreateBackgroundMusicRequest {
pub prompt: String,
pub title: String,
#[serde(default)]
pub tags: Option<String>,
#[serde(default)]
pub model: Option<String>,
}
#[derive(Clone, Debug, Serialize, Deserialize, PartialEq, Eq)]
#[serde(rename_all = "camelCase")]
#[cfg(any())]
pub struct CreateSoundEffectRequest {
pub prompt: String,
#[serde(default)]
pub duration: Option<u8>,
#[serde(default)]
pub seed: Option<u64>,
}
#[derive(Clone, Debug, Serialize, Deserialize, PartialEq, Eq)]
#[serde(rename_all = "camelCase")]
#[cfg(any())]
pub struct AudioGenerationTaskResponse {
pub kind: CreationAudioGenerationKind,
pub task_id: String,
pub provider: String,
pub status: String,
}
#[derive(Clone, Debug, Serialize, Deserialize, PartialEq, Eq)]
#[serde(rename_all = "snake_case")]
#[cfg(any())]
pub enum CreationAudioStoragePrefix {
PuzzleAssets,
WoodenFishAssets,
CustomWorldScenes,
}
#[derive(Clone, Debug, Serialize, Deserialize, PartialEq, Eq)]
#[serde(rename_all = "camelCase")]
#[cfg(any())]
pub struct PublishGeneratedAudioAssetRequest {
pub entity_kind: String,
pub entity_id: String,
pub slot: String,
pub asset_kind: String,
#[serde(default)]
pub profile_id: Option<String>,
#[serde(default)]
pub storage_prefix: Option<CreationAudioStoragePrefix>,
}
#[derive(Clone, Debug, Serialize, Deserialize, PartialEq, Eq)]
#[serde(rename_all = "camelCase")]
pub struct GeneratedAudioAssetResponse {
pub kind: CreationAudioGenerationKind,
pub task_id: String,
pub provider: String,
pub status: String,
#[serde(default)]
pub asset_object_id: Option<String>,
#[serde(default)]
pub object_key: Option<String>,
#[serde(default)]
pub asset_kind: Option<String>,
#[serde(default)]
pub audio_src: Option<String>,
}
#[cfg(any())]
mod tests {
use super::*;
use serde_json::json;
#[test]
fn creation_audio_contracts_use_camel_case_fields() {
let request = PublishGeneratedAudioAssetRequest {
entity_kind: "puzzle_work".to_string(),
entity_id: "puzzle-profile-1".to_string(),
slot: "background_music".to_string(),
asset_kind: "puzzle_background_music".to_string(),
profile_id: Some("profile-1".to_string()),
storage_prefix: Some(CreationAudioStoragePrefix::PuzzleAssets),
};
let payload = serde_json::to_value(request).expect("request should serialize");
assert_eq!(payload["entityKind"], json!("puzzle_work"));
assert_eq!(payload["storagePrefix"], json!("puzzle_assets"));
let asset = CreationAudioAsset {
task_id: "task-1".to_string(),
provider: "vector-engine-suno".to_string(),
asset_object_id: Some("assetobj_1".to_string()),
asset_kind: Some("puzzle_background_music".to_string()),
audio_src: "/generated-puzzle-assets/a.mp3".to_string(),
prompt: Some("轻快音乐".to_string()),
title: Some("拼图音乐".to_string()),
updated_at: Some("2026-05-11T00:00:00Z".to_string()),
};
let payload = serde_json::to_value(asset).expect("asset should serialize");
assert_eq!(payload["taskId"], json!("task-1"));
assert_eq!(payload["audioSrc"], json!("/generated-puzzle-assets/a.mp3"));
}
#[test]
fn creation_audio_contracts_support_wooden_fish_storage_prefix() {
let request = PublishGeneratedAudioAssetRequest {
entity_kind: "wooden_fish_work".to_string(),
entity_id: "wooden-fish-profile-1".to_string(),
slot: "hit_sound".to_string(),
asset_kind: "wooden_fish_hit_sound".to_string(),
profile_id: Some("wooden-fish-profile-1".to_string()),
storage_prefix: Some(CreationAudioStoragePrefix::WoodenFishAssets),
};
let payload = serde_json::to_value(request).expect("request should serialize");
assert_eq!(payload["storagePrefix"], json!("wooden_fish_assets"));
}
}