Skip to content
Projects
Groups
Snippets
Help
This project
Loading...
Sign in / Register
Toggle navigation
Y
yaoai-video
Project
Project
Details
Activity
Cycle Analytics
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Charts
Issues
0
Issues
0
List
Board
Labels
Milestones
Merge Requests
0
Merge Requests
0
CI / CD
CI / CD
Pipelines
Jobs
Schedules
Charts
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Charts
Create a new issue
Jobs
Commits
Issue Boards
Open sidebar
姚珂
yaoai-video
Commits
3cd16618
Commit
3cd16618
authored
May 11, 2026
by
yaoke.yk
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
三视图优化为一张
parent
a6819dfe
Expand all
Hide whitespace changes
Inline
Side-by-side
Showing
5 changed files
with
68 additions
and
36 deletions
+68
-36
CharacterGeneration.tsx
doc/html/src/app/pages/CharacterGeneration.tsx
+51
-32
SeedreamService.java
.../java/com/yaoai/ai/providers/service/SeedreamService.java
+5
-0
SeedreamServiceImpl.java
.../yaoai/ai/providers/service/impl/SeedreamServiceImpl.java
+6
-1
VideoTaskController.java
...in/java/com/yaoai/api/controller/VideoTaskController.java
+6
-3
AssetGenPipelineServiceImpl.java
...ai/pipeline/service/impl/AssetGenPipelineServiceImpl.java
+0
-0
No files found.
doc/html/src/app/pages/CharacterGeneration.tsx
View file @
3cd16618
...
...
@@ -76,7 +76,13 @@ function getCharacterViewUrl(character: Partial<Character>, viewType: CharacterV
return
character
.
backImageUrl
??
null
;
}
function
hasCompleteThreeViews
(
character
:
Partial
<
Character
>
)
{
/** AI 生成的角色三视图是单张拼图,存在 imageUrl 上 */
function
getCharacterSheetUrl
(
character
:
Partial
<
Character
>
):
string
|
null
{
return
character
.
imageUrl
??
null
;
}
function
hasCharacterImage
(
character
:
Partial
<
Character
>
)
{
if
(
getCharacterSheetUrl
(
character
))
return
true
;
return
CHARACTER_VIEWS
.
every
((
view
)
=>
!!
getCharacterViewUrl
(
character
,
view
.
type
));
}
...
...
@@ -120,7 +126,7 @@ export function CharacterGeneration() {
supporting
:
"配角"
,
};
const
generatedCount
=
characters
.
filter
((
character
)
=>
hasC
ompleteThreeViews
(
character
)).
length
;
const
generatedCount
=
characters
.
filter
((
character
)
=>
hasC
haracterImage
(
character
)).
length
;
const
generatingCount
=
characters
.
filter
((
character
)
=>
character
.
status
===
"generating"
).
length
;
const
statusBadge
=
(
status
:
string
)
=>
{
...
...
@@ -395,7 +401,7 @@ export function CharacterGeneration() {
<
div
className=
"flex items-center justify-between mb-3"
>
<
div
>
<
span
className=
"text-xs text-muted-foreground font-medium"
>
角色三视图
</
span
>
<
p
className=
"text-[11px] text-muted-foreground mt-0.5"
>
正面 + 侧面 + 背面,用于完整展示角色造型
。
</
p
>
<
p
className=
"text-[11px] text-muted-foreground mt-0.5"
>
大头像 + 正/侧/背全身拼图,用于角色一致性参考
。
</
p
>
</
div
>
<
button
onClick=
{
()
=>
handleGenerateImage
(
character
)
}
...
...
@@ -403,43 +409,56 @@ export function CharacterGeneration() {
className=
"px-3 py-1.5 rounded-md border border-border bg-card text-foreground hover:bg-muted transition-colors text-xs flex items-center gap-1.5 disabled:opacity-50"
>
{
isGenerating
?
<
Loader2
className=
"w-3 h-3 animate-spin"
/>
:
<
RefreshCw
className=
"w-3 h-3"
/>
}
{
hasC
ompleteThreeViews
(
character
)
?
"重新生成三视图"
:
"AI生成三视图"
}
{
hasC
haracterImage
(
character
)
?
"重新生成三视图"
:
"AI生成三视图"
}
</
button
>
</
div
>
<
div
className=
"grid grid-cols-3 gap-3"
>
{
CHARACTER_VIEWS
.
map
((
view
)
=>
{
const
imageUrl
=
getCharacterViewUrl
(
character
,
view
.
type
);
{
(()
=>
{
const
sheetUrl
=
getCharacterSheetUrl
(
character
);
if
(
sheetUrl
)
{
return
(
<
div
key=
{
view
.
type
}
>
<
div
className=
"text-[11px] text-muted-foreground mb-1 text-center"
>
{
view
.
label
}
</
div
>
<
div
className=
"aspect-[3/4] rounded-lg overflow-hidden bg-white border border-border"
>
{
imageUrl
?
(
<
img
src=
{
imageUrl
}
alt=
{
`${character.name}-${view.label}`
}
className=
"w-full h-full object-cover"
/>
)
:
(
<
div
className=
"w-full h-full flex flex-col items-center justify-center gap-2"
>
{
isGenerating
?
(
<>
<
Loader2
className=
"w-6 h-6 text-primary animate-spin"
/>
<
span
className=
"text-xs text-muted-foreground"
>
生成中
</
span
>
</>
<
div
className=
"rounded-lg overflow-hidden bg-white border border-border"
>
<
img
src=
{
sheetUrl
}
alt=
{
`${character.name}-角色三视图`
}
className=
"w-full h-auto object-contain"
/>
</
div
>
);
}
return
(
<
div
className=
"grid grid-cols-3 gap-3"
>
{
CHARACTER_VIEWS
.
map
((
view
)
=>
{
const
imageUrl
=
getCharacterViewUrl
(
character
,
view
.
type
);
return
(
<
div
key=
{
view
.
type
}
>
<
div
className=
"text-[11px] text-muted-foreground mb-1 text-center"
>
{
view
.
label
}
</
div
>
<
div
className=
"aspect-[3/4] rounded-lg overflow-hidden bg-white border border-border"
>
{
imageUrl
?
(
<
img
src=
{
imageUrl
}
alt=
{
`${character.name}-${view.label}`
}
className=
"w-full h-full object-cover"
/>
)
:
(
<>
<
ImageIcon
className=
"w-6 h-6 text-muted-foreground"
/>
<
span
className=
"text-xs text-muted-foreground"
>
待补充
</
span
>
</>
<
div
className=
"w-full h-full flex flex-col items-center justify-center gap-2"
>
{
isGenerating
?
(
<>
<
Loader2
className=
"w-6 h-6 text-primary animate-spin"
/>
<
span
className=
"text-xs text-muted-foreground"
>
生成中
</
span
>
</>
)
:
(
<>
<
ImageIcon
className=
"w-6 h-6 text-muted-foreground"
/>
<
span
className=
"text-xs text-muted-foreground"
>
待补充
</
span
>
</>
)
}
</
div
>
)
}
</
div
>
)
}
</
div
>
</
div
>
);
})
}
</
div
>
</
div
>
);
})
}
</
div
>
);
})()
}
{
character
.
imagePrompt
&&
(
<
p
className=
"mt-3 text-xs text-muted-foreground line-clamp-3"
>
{
character
.
imagePrompt
}
</
p
>
)
}
</
div
>
</
div
>
);
...
...
yaoai-comic-studio/yaoai-ai-providers/src/main/java/com/yaoai/ai/providers/service/SeedreamService.java
View file @
3cd16618
...
...
@@ -10,6 +10,11 @@ public interface SeedreamService {
*/
String
generateImage
(
String
prompt
);
/**
* 文生图:自定义画布尺寸(如 "2048x1152" 用于 16:9 横版角色三视图)
*/
String
generateImage
(
String
prompt
,
String
size
);
/** 当前使用的 Seedream 模型 ID,用于计费明细 */
String
getModelId
();
...
...
yaoai-comic-studio/yaoai-ai-providers/src/main/java/com/yaoai/ai/providers/service/impl/SeedreamServiceImpl.java
View file @
3cd16618
...
...
@@ -36,11 +36,16 @@ public class SeedreamServiceImpl implements SeedreamService {
@Override
public
String
generateImage
(
String
prompt
)
{
return
generateImage
(
prompt
,
"2048x2048"
);
}
@Override
public
String
generateImage
(
String
prompt
,
String
size
)
{
Map
<
String
,
Object
>
body
=
Map
.
of
(
"model"
,
properties
.
getImageModel
(),
"prompt"
,
prompt
,
"n"
,
1
,
"size"
,
"2048x2048"
,
"size"
,
size
,
"response_format"
,
"url"
);
...
...
yaoai-comic-studio/yaoai-api/src/main/java/com/yaoai/api/controller/VideoTaskController.java
View file @
3cd16618
...
...
@@ -42,9 +42,12 @@ public class VideoTaskController {
}
List
<
String
>
characterKeys
=
req
.
getCharacterImageKeys
();
if
((
characterKeys
==
null
||
characterKeys
.
isEmpty
())
&&
(
req
.
getCharacterImageKey
()
==
null
||
req
.
getCharacterImageKey
().
isBlank
()))
{
throw
new
BizException
(
ErrorCode
.
INVALID_PARAM
,
"请至少选择一个出镜角色"
);
boolean
hasCharacter
=
(
characterKeys
!=
null
&&
!
characterKeys
.
isEmpty
())
||
(
req
.
getCharacterImageKey
()
!=
null
&&
!
req
.
getCharacterImageKey
().
isBlank
());
boolean
hasScene
=
req
.
getSceneImageKey
()
!=
null
&&
!
req
.
getSceneImageKey
().
isBlank
();
boolean
hasProp
=
req
.
getPropImageKeys
()
!=
null
&&
!
req
.
getPropImageKeys
().
isEmpty
();
if
(!
hasCharacter
&&
!
hasScene
&&
!
hasProp
)
{
throw
new
BizException
(
ErrorCode
.
INVALID_PARAM
,
"请至少选择一张参考图(角色/场景/道具任一)"
);
}
Long
tenantId
=
TenantContext
.
get
();
...
...
yaoai-comic-studio/yaoai-pipeline/src/main/java/com/yaoai/pipeline/service/impl/AssetGenPipelineServiceImpl.java
View file @
3cd16618
This diff is collapsed.
Click to expand it.
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment