a8c19e132d
统一编辑器标准绿幕提示词和本地绿幕透明化后处理 生成标准绿幕资产前保存源图到 OSS 并下沉字节级抠绿到 platform-image 将手动去背景接入外部生成队列与画布任务侧栏 修复任务侧栏分页、滚动、计时、焦点与完成信息展示 补充右键菜单关闭和素材复制下载交互 同步编辑器相关文档和项目记忆
109 lines
4.1 KiB
Rust
109 lines
4.1 KiB
Rust
use axum::http::StatusCode;
|
|
use serde::Serialize;
|
|
use serde_json::json;
|
|
use shared_contracts::external_generation::{
|
|
ExternalGenerationJobStatus, ExternalGenerationJobStatusRecord,
|
|
};
|
|
use shared_kernel::{build_prefixed_uuid_id, offset_datetime_to_unix_micros};
|
|
use spacetime_client::{ExternalGenerationJobEnqueueRecordInput, ExternalGenerationJobRecord};
|
|
|
|
use crate::{http_error::AppError, request_context::RequestContext, state::AppState};
|
|
|
|
pub(crate) const EDITOR_IMAGE_GENERATION_JOB_KIND: &str = "editor_image_generation";
|
|
pub(crate) const EDITOR_IMAGE_EDIT_JOB_KIND: &str = "editor_image_edit";
|
|
pub(crate) const EDITOR_BACKGROUND_REMOVAL_JOB_KIND: &str = "editor_background_removal";
|
|
pub(crate) const EDITOR_ICON_SPRITESHEET_GENERATION_JOB_KIND: &str =
|
|
"editor_icon_spritesheet_generation";
|
|
pub(crate) const EDITOR_UI_DESIGN_ASSET_EXTRACTION_JOB_KIND: &str =
|
|
"editor_ui_design_asset_extraction";
|
|
pub(crate) const EDITOR_CHARACTER_ANIMATION_GENERATION_JOB_KIND: &str =
|
|
"editor_character_animation_generation";
|
|
pub(crate) const EDITOR_VIDEO_GENERATION_JOB_KIND: &str = "editor_video_generation";
|
|
pub(crate) const EDITOR_SOUND_EFFECT_GENERATION_JOB_KIND: &str = "editor_sound_effect_generation";
|
|
pub(crate) const EDITOR_BACKGROUND_MUSIC_GENERATION_JOB_KIND: &str =
|
|
"editor_background_music_generation";
|
|
|
|
pub(crate) const EDITOR_GENERATION_QUEUE_SOURCE_MODULE: &str = "editor-canvas";
|
|
const EDITOR_GENERATION_QUEUE_PROVIDER: &str = "editor-generation-worker";
|
|
|
|
#[derive(Debug, Serialize)]
|
|
#[serde(rename_all = "camelCase")]
|
|
pub(crate) struct EditorGenerationQueuedResponse {
|
|
pub(crate) queue_state: ExternalGenerationJobStatusRecord,
|
|
}
|
|
|
|
pub(crate) async fn enqueue_editor_generation_job<T>(
|
|
state: &AppState,
|
|
_request_context: &RequestContext,
|
|
owner_user_id: &str,
|
|
job_kind: &str,
|
|
source_entity_id: impl Into<String>,
|
|
request_label: impl Into<String>,
|
|
price_mud_points: u64,
|
|
payload: &T,
|
|
) -> Result<ExternalGenerationJobRecord, AppError>
|
|
where
|
|
T: Serialize,
|
|
{
|
|
let job_id = build_prefixed_uuid_id("extgen-");
|
|
let request_payload_json = serde_json::to_string(payload).map_err(|error| {
|
|
AppError::from_status(StatusCode::INTERNAL_SERVER_ERROR).with_details(json!({
|
|
"provider": EDITOR_GENERATION_QUEUE_PROVIDER,
|
|
"message": format!("编辑器 worker 任务参数序列化失败:{error}"),
|
|
}))
|
|
})?;
|
|
let now_micros = current_utc_micros();
|
|
state
|
|
.spacetime_client()
|
|
.enqueue_external_generation_job(ExternalGenerationJobEnqueueRecordInput {
|
|
dedupe_key: format!("editor-canvas:{job_kind}:{job_id}"),
|
|
job_id,
|
|
job_kind: job_kind.to_string(),
|
|
owner_user_id: owner_user_id.to_string(),
|
|
source_module: EDITOR_GENERATION_QUEUE_SOURCE_MODULE.to_string(),
|
|
source_entity_id: source_entity_id.into(),
|
|
request_label: request_label.into(),
|
|
request_payload_json,
|
|
max_attempts: 1,
|
|
available_at_micros: now_micros,
|
|
created_at_micros: now_micros,
|
|
price_mud_points,
|
|
})
|
|
.await
|
|
.map_err(|error| {
|
|
AppError::from_status(StatusCode::BAD_GATEWAY).with_details(json!({
|
|
"provider": EDITOR_GENERATION_QUEUE_PROVIDER,
|
|
"message": error.to_string(),
|
|
}))
|
|
})
|
|
}
|
|
|
|
pub(crate) fn editor_generation_queue_state(
|
|
job: ExternalGenerationJobRecord,
|
|
) -> ExternalGenerationJobStatusRecord {
|
|
ExternalGenerationJobStatusRecord {
|
|
operation_id: job.job_id,
|
|
status: ExternalGenerationJobStatus::Queued,
|
|
phase_label: job.request_label,
|
|
phase_detail: "排队中。".to_string(),
|
|
progress: 8,
|
|
error: job.last_error_message,
|
|
updated_at_micros: job.updated_at_micros,
|
|
}
|
|
}
|
|
|
|
pub(crate) fn editor_generation_source_entity_id(
|
|
project_id: Option<&str>,
|
|
fallback: &str,
|
|
) -> String {
|
|
project_id
|
|
.map(str::trim)
|
|
.filter(|value| !value.is_empty())
|
|
.unwrap_or(fallback)
|
|
.to_string()
|
|
}
|
|
|
|
fn current_utc_micros() -> i64 {
|
|
offset_datetime_to_unix_micros(time::OffsetDateTime::now_utc())
|
|
}
|