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
a37d46f8
Commit
a37d46f8
authored
Jun 06, 2026
by
test
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
更新AI生成、分镜工作台、数据库字段
parent
0aa3bd46
Expand all
Hide whitespace changes
Inline
Side-by-side
Showing
15 changed files
with
130 additions
and
21 deletions
+130
-21
Dockerfile
doc/html/Dockerfile
+5
-2
nginx.conf
doc/html/nginx.conf
+11
-0
StoryboardWorkspace.tsx
doc/html/src/app/pages/StoryboardWorkspace.tsx
+0
-0
VideoGeneration.tsx
doc/html/src/app/pages/VideoGeneration.tsx
+0
-0
useAi.ts
doc/html/src/hooks/useAi.ts
+2
-1
ai.ts
doc/html/src/lib/api/ai.ts
+4
-2
start-dev.ps1
start-dev.ps1
+30
-1
Dockerfile
yaoai-comic-studio/Dockerfile
+15
-4
mvnw.cmd
yaoai-comic-studio/mvnw.cmd
+29
-0
StoryboardController.java
...n/java/com/yaoai/api/controller/StoryboardController.java
+3
-2
V22__widen_storyboard_camera_fields.sql
...rces/db/migration/V22__widen_storyboard_camera_fields.sql
+3
-0
AiTaskMapper.java
...n/src/main/java/com/yaoai/domain/mapper/AiTaskMapper.java
+9
-5
CharacterStateMapper.java
...in/java/com/yaoai/domain/mapper/CharacterStateMapper.java
+14
-3
StoryboardPipelineService.java
...com/yaoai/pipeline/service/StoryboardPipelineService.java
+5
-1
StoryboardPipelineServiceImpl.java
.../pipeline/service/impl/StoryboardPipelineServiceImpl.java
+0
-0
No files found.
doc/html/Dockerfile
View file @
a37d46f8
FROM
docker.m.daocloud.io/library/node:20-alpine AS builder
ARG
NODE_IMAGE=node:20-bookworm-slim
ARG
NGINX_IMAGE=nginx:alpine
FROM
${NODE_IMAGE} AS builder
WORKDIR
/app
...
...
@@ -12,7 +15,7 @@ ENV VITE_API_BASE_URL=${VITE_API_BASE_URL}
RUN
npm run build
FROM
docker.m.daocloud.io/library/nginx:1.27-alpine
FROM
${NGINX_IMAGE}
COPY
nginx.conf /etc/nginx/conf.d/default.conf
COPY
--from=builder /app/dist /usr/share/nginx/html
...
...
doc/html/nginx.conf
View file @
a37d46f8
...
...
@@ -19,7 +19,18 @@ server {
proxy_set_header
X-Forwarded-Proto
$scheme
;
}
location
=
/index.html
{
add_header
Cache-Control
"no-store,
no-cache,
must-revalidate,
proxy-revalidate"
always
;
try_files
/index.html
=
404
;
}
location
/assets/
{
add_header
Cache-Control
"no-store,
no-cache,
must-revalidate,
proxy-revalidate"
always
;
try_files
$uri
=
404
;
}
location
/
{
add_header
Cache-Control
"no-store,
no-cache,
must-revalidate,
proxy-revalidate"
always
;
try_files
$uri
$uri
/
/index.html
;
}
}
doc/html/src/app/pages/StoryboardWorkspace.tsx
View file @
a37d46f8
This diff is collapsed.
Click to expand it.
doc/html/src/app/pages/VideoGeneration.tsx
View file @
a37d46f8
This diff is collapsed.
Click to expand it.
doc/html/src/hooks/useAi.ts
View file @
a37d46f8
...
...
@@ -367,7 +367,8 @@ export function useReorderStoryboards(projectId: string, episodeId: string) {
export
function
useGenerateStoryboardPrompt
(
projectId
:
string
)
{
return
useMutation
({
mutationFn
:
(
storyboardId
:
string
)
=>
aiApi
.
generateStoryboardPrompt
(
projectId
,
storyboardId
),
mutationFn
:
({
storyboardId
,
ratio
}:
{
storyboardId
:
string
;
ratio
?:
string
})
=>
aiApi
.
generateStoryboardPrompt
(
projectId
,
storyboardId
,
ratio
),
});
}
...
...
doc/html/src/lib/api/ai.ts
View file @
a37d46f8
...
...
@@ -261,8 +261,10 @@ export const aiApi = {
reorderStoryboards
:
async
(
projectId
:
string
,
ids
:
string
[]):
Promise
<
void
>
=>
{
await
apiClient
.
put
(
`/projects/
${
projectId
}
/storyboards/reorder`
,
{
ids
});
},
generateStoryboardPrompt
:
async
(
projectId
:
string
,
storyboardId
:
string
):
Promise
<
string
>
=>
{
const
r
=
await
apiClient
.
post
(
`/projects/
${
projectId
}
/storyboards/
${
storyboardId
}
/generate-prompt`
);
generateStoryboardPrompt
:
async
(
projectId
:
string
,
storyboardId
:
string
,
ratio
?:
string
):
Promise
<
string
>
=>
{
const
r
=
await
apiClient
.
post
(
`/projects/
${
projectId
}
/storyboards/
${
storyboardId
}
/generate-prompt`
,
null
,
{
params
:
ratio
?
{
ratio
}
:
undefined
,
});
return
r
.
data
.
data
.
prompt
;
},
listShotAssets
:
async
(
projectId
:
string
,
storyboardId
:
string
):
Promise
<
ShotAsset
[]
>
=>
{
...
...
start-dev.ps1
View file @
a37d46f8
...
...
@@ -6,8 +6,35 @@ $frontendDir = Join-Path $root "doc\html"
$adminDir
=
Join-Path
$root
"yaoai-admin-web"
$mavenCmd
=
Join-Path
$root
".tools\apache-maven-3.9.6\bin\mvn.cmd"
$jdk17Candidates
=
@
(
"C:\Program Files\Eclipse Adoptium\jdk-17.0.19.10-hotspot"
,
"C:\Program Files\Eclipse Adoptium\jdk-17.0.17.10-hotspot"
,
"C:\Program Files\Eclipse Adoptium\jdk-17"
,
"C:\Program Files\Java\jdk-17"
,
"D:\Program Files\Java\jdk-17"
)
$jdk17Home
=
$jdk17Candidates
|
Where
-Object
{
Test-Path
(
Join-Path
$_
"bin\java.exe"
)
}
|
Select-Object
-First 1
if
(
-not
$jdk17Home
)
{
$jdk17Home
=
Get-ChildItem
"C:\Program Files\Eclipse Adoptium"
-Directory -Filter
"jdk-17*"
-ErrorAction SilentlyContinue |
Sort-Object
Name -Descending |
Select-Object
-First 1 -ExpandProperty FullName
}
if
(
-not
$jdk17Home
-or -not
(
Test-Path
(
Join-Path
$jdk17Home
"bin\java.exe"
)))
{
throw
"Java 17 JDK not found. Please install JDK 17 and set JAVA_HOME."
}
$env
:JAVA_HOME
=
$jdk17Home
$env
:PATH
=
"
$env
:JAVA_HOME\bin;
$env
:PATH"
if
(
-not
(
Test-Path
$mavenCmd
))
{
$chocoMaven
=
"C:\ProgramData\chocolatey\lib\maven\apache-maven-3.9.16\bin\mvn.cmd"
if
(
Test-Path
$chocoMaven
)
{
$mavenCmd
=
$chocoMaven
}
}
Push-Location
$root
try
{
Write-Host
"[dev] using JAVA_HOME=
$env
:JAVA_HOME"
Write-Host
"[dev] starting infrastructure from yaoai-comic-studio/docker-compose.yml ..."
docker compose -f
(
Join-Path
$backendDir
"docker-compose.yml"
)
up -d
...
...
@@ -24,9 +51,11 @@ try {
Write-Host
""
Write-Host
"[dev] next commands"
Write-Host
" 1. build backend"
Write-Host
"
`$
env:JAVA_HOME =
`"
$env
:JAVA_HOME
`"
"
Write-Host
"
`$
env:PATH =
`"`$
env:JAVA_HOME\bin;
`$
env:PATH
`"
"
Write-Host
" &
`"
$mavenCmd
`"
-f
`"
$backendDir
\pom.xml
`"
package -pl yaoai-bootstrap -am -DskipTests"
Write-Host
" 2. run backend"
Write-Host
"
java
-jar
`"
$backendDir
\yaoai-bootstrap\target\yaoai-bootstrap-0.1.0-SNAPSHOT.jar
`"
"
Write-Host
"
&
`"
$env
:JAVA_HOME\bin\java.exe
`"
-jar
`"
$backendDir
\yaoai-bootstrap\target\yaoai-bootstrap-0.1.0-SNAPSHOT.jar
`"
"
Write-Host
" 3. run frontend"
Write-Host
" Set-Location
`"
$frontendDir
`"
; npm install; npm run dev"
Write-Host
" 4. run admin-web"
...
...
yaoai-comic-studio/Dockerfile
View file @
a37d46f8
# ===== Stage 1: Build =====
FROM
docker.m.daocloud.io/library/maven:3.9.9-eclipse-temurin-17 AS builder
ARG
MAVEN_IMAGE=maven:3.9-eclipse-temurin-17-alpine
ARG
RUNTIME_IMAGE=eclipse-temurin:17-jre-alpine
FROM
${MAVEN_IMAGE} AS builder
WORKDIR
/workspace
...
...
@@ -47,7 +50,7 @@ COPY . .
RUN
mvn
-s
/root/.m2/settings.xml package
-pl
yaoai-bootstrap
-am
-DskipTests
-B
-ntp
# ===== Stage 2: Runtime =====
FROM
docker.m.daocloud.io/library/eclipse-temurin:17-jre-jammy
FROM
${RUNTIME_IMAGE}
LABEL
maintainer="YaoAI Team <yaoke251@gmail.com>"
LABEL
org.opencontainers.image.title="YaoAI Comic Studio"
...
...
@@ -60,6 +63,7 @@ ENV LANG=C.UTF-8 \
ARG
APT_MIRROR=https://mirrors.tuna.tsinghua.edu.cn/ubuntu
RUN
set
-eux
;
\
if
command
-v
apt-get
>
/dev/null 2>&1
;
then
\
if
[
-f
/etc/apt/sources.list
]
;
then
\
sed
-i
"s|http://archive.ubuntu.com/ubuntu|
${
APT_MIRROR
}
|g; s|http://security.ubuntu.com/ubuntu|
${
APT_MIRROR
}
|g"
/etc/apt/sources.list
;
\
fi
;
\
...
...
@@ -68,10 +72,17 @@ RUN set -eux; \
fi
;
\
apt-get
-o
Acquire::Retries
=
5 update
\
&&
DEBIAN_FRONTEND
=
noninteractive apt-get
install
-y
--no-install-recommends
ffmpeg
\
&&
rm
-rf
/var/lib/apt/lists/
*
&&
rm
-rf
/var/lib/apt/lists/
*
;
\
elif
command
-v
apk
>
/dev/null 2>&1
;
then
\
apk add
--no-cache
ffmpeg
;
\
fi
# Non-root user
RUN
groupadd
-r
yaoai
&&
useradd
-r
-g
yaoai yaoai
RUN if
command
-v
groupadd
>
/dev/null 2>&1
;
then
\
groupadd
-r
yaoai
&&
useradd
-r
-g
yaoai yaoai
;
\
else
\
addgroup
-S
yaoai
&&
adduser
-S
-G
yaoai yaoai
;
\
fi
WORKDIR
/app
...
...
yaoai-comic-studio/mvnw.cmd
View file @
a37d46f8
...
...
@@ -5,9 +5,30 @@
@setlocal
@REM ==== START VALIDATION ====
@REM Prefer Java 17 even when PATH or JAVA_HOME points to an older JDK.
for /d %%J in ("C:\Program Files\Eclipse Adoptium\jdk-17*") do (
if exist "%%~fJ\bin\java.exe" (
set "JAVA_HOME=%%~fJ"
)
)
for /d %%J in ("C:\Program Files\Java\jdk-17*") do (
if exist "%%~fJ\bin\java.exe" (
set "JAVA_HOME=%%~fJ"
)
)
for /d %%J in ("D:\Program Files\Java\jdk-17*") do (
if exist "%%~fJ\bin\java.exe" (
set "JAVA_HOME=%%~fJ"
)
)
if not "%JAVA_HOME%"=="" goto OkJHome
@REM Try common Java 17 locations on this machine
if exist "C:\Program Files\Eclipse Adoptium\jdk-17.0.19.10-hotspot\bin\java.exe" (
set "JAVA_HOME=C:\Program Files\Eclipse Adoptium\jdk-17.0.19.10-hotspot"
goto OkJHome
)
if exist "D:\Program Files\Java\jdk-17\bin\java.exe" (
set "JAVA_HOME=D:\Program Files\Java\jdk-17"
goto OkJHome
...
...
@@ -40,6 +61,14 @@ set _JAVACMD=%JAVA_HOME%\bin\java.exe
set MAVEN_WRAPPER_JAR=%~dp0.mvn\wrapper\maven-wrapper.jar
set MAVEN_WRAPPER_PROPERTIES=%~dp0.mvn\wrapper\maven-wrapper.properties
@REM Use locally installed Maven when the wrapper jar is not checked in.
if not exist "%MAVEN_WRAPPER_JAR%" (
if exist "C:\ProgramData\chocolatey\lib\maven\apache-maven-3.9.16\bin\mvn.cmd" (
call "C:\ProgramData\chocolatey\lib\maven\apache-maven-3.9.16\bin\mvn.cmd" %*
exit /B %ERRORLEVEL%
)
)
@REM Download wrapper jar if missing
if not exist "%MAVEN_WRAPPER_JAR%" (
echo Downloading Maven Wrapper...
...
...
yaoai-comic-studio/yaoai-api/src/main/java/com/yaoai/api/controller/StoryboardController.java
View file @
a37d46f8
...
...
@@ -150,9 +150,10 @@ public class StoryboardController {
@Operation
(
summary
=
"AI 生成分镜视频描述提示词"
)
@PostMapping
(
"/storyboards/{storyboardId}/generate-prompt"
)
public
ApiResponse
<
Map
<
String
,
String
>>
generatePrompt
(
@PathVariable
Long
projectId
,
@PathVariable
Long
storyboardId
)
{
@PathVariable
Long
storyboardId
,
@RequestParam
(
required
=
false
)
String
ratio
)
{
Long
tenantId
=
TenantContext
.
get
();
Map
<
String
,
String
>
body
=
Map
.
of
(
"prompt"
,
storyboardService
.
generatePrompt
(
storyboardId
,
tenantId
));
Map
<
String
,
String
>
body
=
Map
.
of
(
"prompt"
,
storyboardService
.
generatePrompt
(
storyboardId
,
tenantId
,
ratio
));
return
ApiResponse
.
success
(
body
);
}
...
...
yaoai-comic-studio/yaoai-bootstrap/src/main/resources/db/migration/V22__widen_storyboard_camera_fields.sql
0 → 100644
View file @
a37d46f8
ALTER
TABLE
storyboards
MODIFY
COLUMN
camera_direction
TEXT
DEFAULT
NULL
,
MODIFY
COLUMN
composition_guide
TEXT
DEFAULT
NULL
;
yaoai-comic-studio/yaoai-domain/src/main/java/com/yaoai/domain/mapper/AiTaskMapper.java
View file @
a37d46f8
...
...
@@ -3,6 +3,7 @@ package com.yaoai.domain.mapper;
import
com.baomidou.mybatisplus.core.mapper.BaseMapper
;
import
com.yaoai.domain.entity.AiTask
;
import
org.apache.ibatis.annotations.Mapper
;
import
org.apache.ibatis.annotations.Param
;
import
org.apache.ibatis.annotations.Select
;
import
java.util.List
;
...
...
@@ -11,10 +12,10 @@ import java.util.List;
public
interface
AiTaskMapper
extends
BaseMapper
<
AiTask
>
{
@Select
(
"SELECT * FROM ai_tasks WHERE project_id=#{projectId} AND tenant_id=#{tenantId} ORDER BY created_at DESC"
)
List
<
AiTask
>
findByProject
(
Long
projectId
,
Long
tenantId
);
List
<
AiTask
>
findByProject
(
@Param
(
"projectId"
)
Long
projectId
,
@Param
(
"tenantId"
)
Long
tenantId
);
@Select
(
"SELECT * FROM ai_tasks WHERE episode_id=#{episodeId} ORDER BY created_at DESC LIMIT 1"
)
AiTask
findLatestByEpisode
(
Long
episodeId
);
AiTask
findLatestByEpisode
(
@Param
(
"episodeId"
)
Long
episodeId
);
@Select
(
"""
SELECT t.* FROM ai_tasks t
...
...
@@ -25,7 +26,7 @@ public interface AiTaskMapper extends BaseMapper<AiTask> {
AND t.result_video_url IS NOT NULL
ORDER BY COALESCE(s.sequence_num, 9999), t.created_at
"""
)
List
<
AiTask
>
findSucceededByEpisodeOrdered
(
Long
episodeId
,
Long
tenantId
);
List
<
AiTask
>
findSucceededByEpisodeOrdered
(
@Param
(
"episodeId"
)
Long
episodeId
,
@Param
(
"tenantId"
)
Long
tenantId
);
/** 待轮询的视频任务:已提交 Ark 且未到终态。limit 控制单轮处理上限,避免单次扫描挤占线程。 */
@Select
(
"""
...
...
@@ -35,7 +36,7 @@ public interface AiTaskMapper extends BaseMapper<AiTask> {
ORDER BY created_at ASC
LIMIT #{limit}
"""
)
List
<
AiTask
>
findPollableVideoTasks
(
int
limit
);
List
<
AiTask
>
findPollableVideoTasks
(
@Param
(
"limit"
)
int
limit
);
@Select
(
"""
SELECT * FROM ai_tasks
...
...
@@ -47,5 +48,8 @@ public interface AiTaskMapper extends BaseMapper<AiTask> {
ORDER BY created_at DESC
LIMIT 1
"""
)
AiTask
findLatestSucceededVideoByStoryboard
(
Long
storyboardId
,
Long
tenantId
);
AiTask
findLatestSucceededVideoByStoryboard
(
@Param
(
"storyboardId"
)
Long
storyboardId
,
@Param
(
"tenantId"
)
Long
tenantId
);
}
yaoai-comic-studio/yaoai-domain/src/main/java/com/yaoai/domain/mapper/CharacterStateMapper.java
View file @
a37d46f8
...
...
@@ -4,6 +4,7 @@ import com.baomidou.mybatisplus.core.mapper.BaseMapper;
import
com.yaoai.domain.entity.CharacterState
;
import
org.apache.ibatis.annotations.Delete
;
import
org.apache.ibatis.annotations.Mapper
;
import
org.apache.ibatis.annotations.Param
;
import
org.apache.ibatis.annotations.Select
;
import
java.util.List
;
...
...
@@ -18,7 +19,10 @@ public interface CharacterStateMapper extends BaseMapper<CharacterState> {
WHERE cs.project_id=#{projectId} AND cs.tenant_id=#{tenantId}
ORDER BY c.created_at ASC, cs.created_at ASC
"""
)
List
<
CharacterState
>
findByProject
(
Long
projectId
,
Long
tenantId
);
List
<
CharacterState
>
findByProject
(
@Param
(
"projectId"
)
Long
projectId
,
@Param
(
"tenantId"
)
Long
tenantId
);
@Select
(
"""
SELECT cs.*, c.name AS character_name
...
...
@@ -29,8 +33,15 @@ public interface CharacterStateMapper extends BaseMapper<CharacterState> {
AND cs.tenant_id=#{tenantId}
ORDER BY cs.created_at ASC
"""
)
List
<
CharacterState
>
findByCharacter
(
Long
projectId
,
Long
characterId
,
Long
tenantId
);
List
<
CharacterState
>
findByCharacter
(
@Param
(
"projectId"
)
Long
projectId
,
@Param
(
"characterId"
)
Long
characterId
,
@Param
(
"tenantId"
)
Long
tenantId
);
@Delete
(
"DELETE FROM character_states WHERE character_id=#{characterId} AND tenant_id=#{tenantId}"
)
int
deleteByCharacter
(
Long
characterId
,
Long
tenantId
);
int
deleteByCharacter
(
@Param
(
"characterId"
)
Long
characterId
,
@Param
(
"tenantId"
)
Long
tenantId
);
}
yaoai-comic-studio/yaoai-pipeline/src/main/java/com/yaoai/pipeline/service/StoryboardPipelineService.java
View file @
a37d46f8
...
...
@@ -29,7 +29,11 @@ public interface StoryboardPipelineService {
/**
* AI 根据分镜剧本信息生成视频描述提示词(分时段影视风格)
*/
String
generatePrompt
(
Long
storyboardId
,
Long
tenantId
);
default
String
generatePrompt
(
Long
storyboardId
,
Long
tenantId
)
{
return
generatePrompt
(
storyboardId
,
tenantId
,
null
);
}
String
generatePrompt
(
Long
storyboardId
,
Long
tenantId
,
String
videoRatio
);
List
<
Storyboard
>
populateMissingVideoPromptsByEpisode
(
Long
episodeId
,
Long
tenantId
);
}
yaoai-comic-studio/yaoai-pipeline/src/main/java/com/yaoai/pipeline/service/impl/StoryboardPipelineServiceImpl.java
View file @
a37d46f8
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