Skip to content
Projects
Groups
Snippets
Help
Loading...
Sign in
Toggle navigation
T
text2video-frontend
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
周成波
text2video-frontend
Commits
2db83afd
Commit
2db83afd
authored
Feb 24, 2024
by
周成波
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
拆分成简单任务
parent
f6a8833c
Hide whitespace changes
Inline
Side-by-side
Showing
3 changed files
with
625 additions
and
85 deletions
+625
-85
useManyValues.ts
src/views/home/compositions/useManyValues.ts
+3
-14
index-bak20240224.vue
src/views/home/index-bak20240224.vue
+540
-0
index.vue
src/views/home/index.vue
+82
-71
No files found.
src/views/home/compositions/useManyValues.ts
View file @
2db83afd
...
...
@@ -173,20 +173,9 @@ export const useManyValues = () => {
const
vertical_data
=
{
task_id
:
"20240220181602687"
,
chatgpt_prompt
:
``
,
chatgpt_answer
:
`从前,有一个叫花果王的猴王,身手敏捷,机智过人。他生活在一片美丽的猴子园里,那里有无数的猴子,它们和谐相处,过着无忧无虑的生活。花果王是这片猴子园的领袖,他深受猴子的尊敬和喜爱。 有一天,花果王听说附近的人类村庄正在遭受一场大灾难。原来,是一只凶猛的妖邪之作正在祸害人类。花果王决定带领猴群去解救人类,拯救村子。他组织了一支强大的猴军,他们勇敢地踏上了征程。 经过艰苦的跋涉,猴军终于来到了人类村庄。他们看到村民们惊恐失措,生活在水深火热之中。于是,花果王毫不犹豫地挥舞金箍棒,击败了妖邪之作。人类村民们见状,纷纷拜谢猴王,将他们视为救世主。 从此,花果王和猴军的名声远扬,他们继续在人类与猴子之间传播友谊与和谐,成为了永恒的传说。`
,
chatgpt_answer_roles
:
[{
"角色"
:
"花果王"
,
"角色关键词"
:
"性别:雄性, 年龄:成年, 肤色:棕色(猴毛颜色), 衣服:无(自然皮毛), 发型:蓬松猴鬃, 发色:金色(象征其力量与地位的金箍棒颜色), 脸色:生动活泼的猴脸, 五官特点:炯炯有神的眼睛,机敏狡黠的表情, 领导力强, 勇敢且富有智慧"
},
{
"角色"
:
"猴群"
,
"角色关键词"
:
"性别各异, 年龄各异, 肤色:多种(根据自然猴种不同), 衣服:无(自然皮毛), 发型:自然猴毛发型各异, 发色:各自品种特征色, 脸色:生动活泼的猴脸, 五官特点:机灵好奇, 忠诚团结"
},
{
"角色"
:
"人类村民"
,
"角色关键词"
:
"性别各异, 年龄各异, 肤色:黄种人肤色, 衣服:传统农耕服饰, 发型:古代农夫、妇女常见发型, 发色:黑发, 脸色:因灾难而显得苍白恐慌, 五官特点:感激涕零, 对救星充满敬仰"
},
{
"角色"
:
"妖邪之作"
,
"角色关键词"
:
"性别:不明, 年龄:不明, 肤色:暗黑或异色, 衣服:可能为神秘或恐怖风格的装饰, 发型:怪异扭曲, 发色:可能是深红、墨黑或其他邪恶象征的颜色, 脸色:阴森可怖, 五官特点:狰狞可怕, 充满恶意和破坏力"
}]
,
chatgpt_prompt
:
`生成一个100字的科幻小故事,阿凡达系列`
,
chatgpt_answer
:
``
,
chatgpt_answer_roles
:
[],
adapt_result_json
:
[
],
final_video
:
``
,
...
...
src/views/home/index-bak20240224.vue
0 → 100644
View file @
2db83afd
<
script
setup
lang=
"ts"
>
import
{
onMounted
,
reactive
,
ref
}
from
"vue"
;
import
{
Sunny
,
UploadFilled
}
from
"@element-plus/icons-vue"
;
import
{
ElMessage
,
genFileId
,
type
UploadInstance
,
type
UploadProps
,
type
UploadRawFile
}
from
"element-plus"
;
import
text2videoService
from
"@/api/service/text2videoService"
;
import
utils
from
"@/utils/utils"
;
import
{
useManyValues
}
from
'./compositions/useManyValues'
const
debug
=
ref
(
import
.
meta
.
env
.
MODE
===
'production'
?
false
:
true
);
const
loading
=
ref
(
false
);
const
dialogVisible
=
ref
(
false
);
const
dialogData
=
ref
(
""
);
const
default_data
=
useManyValues
();
const
form
=
reactive
({
screen
:
default_data
.
screen
,
if_need_subtitle
:
default_data
.
if_need_subtitle
,
chatgpt_prompt
:
""
,
chatgpt_answer
:
""
,
chatgpt_answer_roles
:
<
Wm
.
RolesItem
[]
>
[],
adapt_result_json
:
<
Wm
.
ScriptsItem
[]
>
[],
task_id
:
""
,
final_video
:
""
,
});
const
sd_prompt_prefix
=
default_data
.
sd_prompt_prefix
;
const
sd_negative_prompt_prefix
=
default_data
.
sd_negative_prompt_prefix
;
const
wenan_llm
=
"tyqw"
const
wenan_llm_name
=
"通义千问"
const
role_llm
=
"tyqw"
const
role_llm_name
=
"通义千问"
const
tuili_llm
=
"langchain"
const
tuili_llm_name
=
"baichuan2-7b"
const
fanyi_llm
=
"langchain"
const
fanyi_llm_name
=
"baichuan2-7b"
onMounted
(()
=>
{
// 初始化示例数据
onChangeScreen
(
form
.
screen
);
});
const
onSubmitGpt
=
()
=>
{
text2videoService
.
submitGpt
(
form
.
chatgpt_prompt
,
wenan_llm
)
.
then
((
result
:
string
)
=>
{
console
.
log
(
form
.
chatgpt_prompt
);
console
.
log
(
result
);
form
.
chatgpt_answer
=
result
;
})
.
catch
((
error
:
any
)
=>
{
// console.error(error);
ElMessage
({
message
:
error
,
type
:
"error"
,
});
});
};
const
onAdaptRoles
=
async
()
=>
{
if
(
!
form
.
chatgpt_answer
||
form
.
chatgpt_answer
.
length
==
0
)
{
ElMessage
({
message
:
"文案不能为空"
,
type
:
"error"
,
});
return
;
}
loading
.
value
=
true
;
// 推理角色
try
{
const
adapt_restrict
=
`
指令:
请理解这个故事,给出这个故事的所有角色、角色关键词(性别(可以发挥想象进行补充,但一定要明确),年龄(可以发挥想象进行补充,但一定要明确),
肤色(可以发挥想象进行补充,但一定要明确),衣服(可以发挥想象进行补充,但一定要明确),发型(可以发挥想象进行补充,但一定要明确),发色(可以发挥想象进行补充,但一定要明确),
脸色(可以发挥想象进行补充,但一定要明确),五官特点(可以发挥想象进行补充,但一定要明确))。\n
要求:
角色和角色关键词要对应。
严格以如下格式返回:[{"角色":"","角色关键词":""}]`
;
const
keywords
=
await
text2videoService
.
submitGpt
(
form
.
chatgpt_answer
+
"
\n
"
+
adapt_restrict
,
role_llm
);
console
.
log
(
keywords
)
const
keywords_obj
=
utils
.
formatJsonObj
(
keywords
.
replace
(
/```json/g
,
''
).
replace
(
/```/g
,
''
))
console
.
log
(
keywords_obj
)
form
.
chatgpt_answer_roles
=
[]
if
(
'error'
in
keywords_obj
)
{
ElMessage
({
message
:
"未解析到角色"
,
type
:
"error"
,
});
}
else
{
for
(
let
item
of
keywords_obj
)
{
let
newObjItem
=
{
"角色"
:
JSON
.
stringify
(
item
[
"角色"
]).
replace
(
/"/g
,
''
),
"角色关键词"
:
JSON
.
stringify
(
item
[
"角色关键词"
]).
replace
(
/"/g
,
''
)
};
form
.
chatgpt_answer_roles
.
push
(
newObjItem
);
}
console
.
log
(
form
.
chatgpt_answer_roles
)
}
}
catch
(
error
)
{
ElMessage
({
message
:
String
(
error
),
type
:
"error"
,
});
}
finally
{
// 最终关闭loading(无论成功或失败)
loading
.
value
=
false
;
}
};
const
onAdapt
=
async
()
=>
{
if
(
!
form
.
chatgpt_answer
||
form
.
chatgpt_answer
.
length
==
0
)
{
ElMessage
({
message
:
"文案不能为空"
,
type
:
"error"
,
});
return
;
}
loading
.
value
=
true
;
form
.
task_id
=
utils
.
genDateTimeStr
();
console
.
log
(
form
.
task_id
)
// 按标点拆分成分镜
const
sentences
=
utils
.
splitText
(
form
.
chatgpt_answer
);
console
.
log
(
sentences
.
length
)
// 分镜
form
.
adapt_result_json
=
[]
for
(
let
i
=
0
;
i
<
sentences
.
length
;
i
++
)
{
form
.
adapt_result_json
.
push
({
"编号"
:
(
i
+
1
).
toString
(),
"场景描述"
:
sentences
[
i
].
trim
(),
"场景关键词"
:
""
,
"角色"
:
""
,
"角色关键词"
:
""
,
"画面描述词"
:
""
,
"本镜配图"
:
""
,
"local_image_path"
:
""
,
});
}
console
.
log
(
form
.
adapt_result_json
)
const
delay
=
(
ms
:
any
)
=>
new
Promise
(
res
=>
setTimeout
(
res
,
ms
));
async
function
processScenes
()
{
for
(
const
item
of
form
.
adapt_result_json
)
{
await
onAdaptOne
(
item
);
await
delay
(
100
);
await
onDrawOne
(
item
);
}
}
try
{
await
processScenes
();
ElMessage
({
message
:
"all scene ok"
,
type
:
"success"
});
console
.
log
(
form
.
adapt_result_json
);
}
catch
(
error
)
{
ElMessage
({
message
:
String
(
error
),
type
:
"error"
});
}
finally
{
loading
.
value
=
false
;
// 最终关闭loading(无论成功或失败)
}
};
const
onAdaptOne
=
async
(
item
:
any
)
=>
{
if
(
!
item
.
场景描述
)
{
ElMessage
({
message
:
"分镜场景描述不能为空"
,
type
:
"error"
,
});
return
;
}
// 推理关键词
try
{
const
adapt_restrict
=
`
指令:
请理解这个故事,针对其中的这个场景:“
${
item
.
场景描述
}
”,给出这个场景的:
场景关键词(年代,空间,时间段,地理环境,天气,物品,人物,镜头角度)、
角色(从所有角色中选择本场景的角色)。
要求:
角色和角色关键词要对应。
严格以如下格式返回:[{"场景关键词":"(多个词以逗号分隔)","角色":"(角色以逗号分隔)"}]
除了按格式返回的内容之外,不要添加其他的任何说明。`
;
const
keywords
=
await
text2videoService
.
submitGpt
(
"故事:
\n
"
+
form
.
chatgpt_answer
+
"
\n
所有角色:
\n
"
+
JSON
.
stringify
(
form
.
chatgpt_answer_roles
)
+
"
\n
"
+
adapt_restrict
,
tuili_llm
);
// console.log(keywords)
const
keywords_obj
=
utils
.
formatJsonObj
(
keywords
.
replace
(
/```json/g
,
''
).
replace
(
/```/g
,
''
))
// console.log(keywords_obj)
if
(
'error'
in
keywords_obj
)
{
ElMessage
({
message
:
`分镜
${
item
.
编号
}
推理关键词失败,请重试`
,
type
:
"error"
,
});
}
else
{
item
.
场景关键词
=
JSON
.
stringify
(
keywords_obj
[
0
].
场景关键词
).
replace
(
/"/g
,
''
);
if
(
form
.
chatgpt_answer_roles
.
length
===
0
)
{
// 总角色为空
item
.
角色
=
''
;
item
.
角色关键词
=
''
;
}
else
{
// 总角色不为空
// item.角色 = JSON.stringify(keywords_obj[0].角色).replace(/"/g, '');
// item.角色关键词 = JSON.stringify(keywords_obj[0].角色关键词).replace(/"/g, '');
const
item_roles
=
JSON
.
stringify
(
keywords_obj
[
0
].
角色
).
replace
(
/"/g
,
''
);
item
.
角色
=
item_roles
;
let
role_kws
=
""
const
item_roles_arr
=
item_roles
.
split
(
/
[
,,
]
/
);
item_roles_arr
.
forEach
(
one_item_role
=>
{
// 人工指定角色关键词,包含则取
form
.
chatgpt_answer_roles
.
forEach
(
i
=>
{
if
(
i
[
"角色"
].
includes
(
one_item_role
.
trim
())
||
one_item_role
.
includes
(
i
[
"角色"
].
trim
()))
{
role_kws
=
`
${
role_kws
}
【
${
i
[
"角色"
]}
:
${
i
[
"角色关键词"
]}
】`
}
})
})
item
.
角色关键词
=
role_kws
;
}
}
}
catch
(
error
)
{
ElMessage
({
message
:
String
(
error
),
type
:
"error"
,
});
}
};
const
onDrawOne
=
async
(
item
:
any
)
=>
{
if
(
!
item
.
场景描述
&&
!
item
.
场景关键词
)
{
ElMessage
({
message
:
"场景描述和场景关键词不能都为空"
,
type
:
"error"
,
});
return
;
}
// 翻译+画图
if
(
!
form
.
task_id
)
{
form
.
task_id
=
utils
.
genDateTimeStr
();
console
.
log
(
form
.
task_id
)
}
try
{
let
temp_prompt
=
""
if
(
item
.
场景描述
)
{
temp_prompt
=
temp_prompt
+
`场景描述为:
${
item
.
场景描述
}
\n`
};
if
(
item
.
场景关键词
)
{
temp_prompt
=
temp_prompt
+
`场景关键词为:
${
item
.
场景关键词
}
\n`
};
if
(
item
.
角色
)
{
temp_prompt
=
temp_prompt
+
`场景中的角色有:
${
item
.
角色
}
\n`
};
if
(
item
.
角色关键词
)
{
temp_prompt
=
temp_prompt
+
`角色关键词为:
${
item
.
角色关键词
}
\n`
};
const
sd_describe
=
await
text2videoService
.
submitGpt
(
`
${
temp_prompt
}
指令:
请理解以上内容,并返回一段英文的描述。`
,
fanyi_llm
);
item
.
画面描述词
=
sd_describe
;
const
sd_prompt
=
item
.
画面描述词
+
","
+
sd_prompt_prefix
;
let
width
=
"960"
;
let
height
=
"540"
;
if
(
form
.
screen
==
"竖屏"
)
{
width
=
"540"
;
height
=
"960"
;
}
// console.log(sd_prompt);
// console.log(sd_negative_prompt_prefix);
const
sd_img
=
await
text2videoService
.
submitSD
(
form
.
task_id
,
item
.
编号
,
sd_prompt
,
sd_negative_prompt_prefix
,
width
,
height
);
item
.
本镜配图
=
sd_img
.
domain_image_path
+
"?v="
+
utils
.
genDateTimeStr
();
item
.
local_image_path
=
sd_img
.
local_image_path
;
}
catch
(
error
)
{
ElMessage
({
message
:
String
(
error
),
type
:
"error"
,
});
}
};
const
onGenVideo
=
()
=>
{
if
(
!
form
.
adapt_result_json
||
form
.
adapt_result_json
.
length
==
0
)
{
ElMessage
({
message
:
"必要信息不能为空,请重新执行"
,
type
:
"error"
,
});
return
;
}
let
is_all_ok
=
true
;
form
.
adapt_result_json
.
map
(
item
=>
{
if
(
item
.
编号
==
""
||
item
.
场景描述
==
""
||
item
.
local_image_path
==
""
)
{
ElMessage
({
message
:
`分镜
${
item
.
编号
}
的必要信息为空,请重新执行`
,
type
:
"error"
,
});
is_all_ok
=
false
;
}
});
if
(
!
is_all_ok
)
return
;
console
.
log
(
form
.
adapt_result_json
);
const
video_param_detail
=
form
.
adapt_result_json
.
map
(
item
=>
{
return
{
idx
:
item
.
编号
,
text
:
item
.
场景描述
,
img_path
:
item
.
local_image_path
};
});
const
video_param
=
{
task_id
:
form
.
task_id
,
if_need_subtitle
:
form
.
if_need_subtitle
,
task_info
:
video_param_detail
,
}
text2videoService
.
submitGenVideo
(
video_param
)
.
then
((
result
:
string
)
=>
{
console
.
log
(
result
);
form
.
final_video
=
""
;
form
.
final_video
=
result
+
"?v="
+
utils
.
genDateTimeStr
();
})
.
catch
((
error
:
any
)
=>
{
// console.error(error);
ElMessage
({
message
:
error
,
type
:
"error"
,
});
});
};
const
clean_demo
=
()
=>
{
form
.
chatgpt_prompt
=
""
;
form
.
chatgpt_answer
=
""
;
form
.
chatgpt_answer_roles
=
<
Wm
.
RolesItem
[]
>
[];
form
.
adapt_result_json
=
<
Wm
.
ScriptsItem
[]
>
[];
form
.
task_id
=
""
;
form
.
final_video
=
""
;
}
const
clean_roles
=
()
=>
{
form
.
chatgpt_answer_roles
=
<
Wm
.
RolesItem
[]
>
[];
}
const
onChangeScreen
=
(
val
:
string
)
=>
{
if
(
debug
.
value
==
true
)
{
if
(
val
==
"横屏"
)
{
form
.
task_id
=
default_data
.
horizontal_data
.
task_id
;
form
.
chatgpt_prompt
=
default_data
.
horizontal_data
.
chatgpt_prompt
;
form
.
chatgpt_answer
=
default_data
.
horizontal_data
.
chatgpt_answer
;
form
.
chatgpt_answer_roles
=
default_data
.
horizontal_data
.
chatgpt_answer_roles
;
form
.
adapt_result_json
=
default_data
.
horizontal_data
.
adapt_result_json
;
form
.
final_video
=
default_data
.
horizontal_data
.
final_video
;
}
else
{
form
.
task_id
=
default_data
.
vertical_data
.
task_id
;
form
.
chatgpt_prompt
=
default_data
.
vertical_data
.
chatgpt_prompt
;
form
.
chatgpt_answer
=
default_data
.
vertical_data
.
chatgpt_answer
;
form
.
chatgpt_answer_roles
=
default_data
.
vertical_data
.
chatgpt_answer_roles
;
form
.
adapt_result_json
=
default_data
.
vertical_data
.
adapt_result_json
;
form
.
final_video
=
default_data
.
vertical_data
.
final_video
;
}
}
}
const
showsdprompt
=
(
item
:
any
)
=>
{
// alert(item.画面描述词)
dialogData
.
value
=
item
.
画面描述词
+
","
+
sd_prompt_prefix
+
'===== negative ====='
+
sd_negative_prompt_prefix
;
dialogVisible
.
value
=
true
;
// 打开对话框
}
const
upload
=
ref
<
UploadInstance
>
()
const
actionUrl
=
ref
(
import
.
meta
.
env
.
MODE
===
'production'
?
'/file'
:
import
.
meta
.
env
.
VITE_APP_BASE_API
+
'/file'
)
const
handleUploadSuccess
=
(
val
:
Wm
.
UploadResult
)
=>
{
if
(
val
.
code
==
0
){
// console.log(val)
const
id
=
parseInt
(
val
.
message
)
-
1
;
form
.
adapt_result_json
[
id
].
本镜配图
=
val
.
data
[
0
].
url
+
"?v="
+
utils
.
genDateTimeStr
();
form
.
adapt_result_json
[
id
].
local_image_path
=
val
.
data
[
0
].
path
;
ElMessage
({
message
:
'上传成功'
,
type
:
'success'
})
}
else
{
ElMessage
({
message
:
'上传失败'
,
type
:
'error'
})
}
}
const
handleExceed
:
UploadProps
[
'onExceed'
]
=
(
files
)
=>
{
upload
.
value
!
.
clearFiles
()
const
file
=
files
[
0
]
as
UploadRawFile
file
.
uid
=
genFileId
()
upload
.
value
!
.
handleStart
(
file
)
upload
.
value
!
.
submit
()
}
</
script
>
<
template
>
<main
class=
"home-container"
>
<!-- 标题 -->
<el-divider
content-position=
"left"
>
text2video
</el-divider>
<el-form
:model=
"form"
label-width=
"114px"
v-loading=
"loading"
>
<el-form-item>
<div>
<el-radio-group
v-model=
"form.screen"
@
change=
"onChangeScreen"
>
<el-radio
label=
"横屏"
size=
"large"
border
/>
<el-radio
label=
"竖屏"
size=
"large"
border
/>
</el-radio-group>
</div>
</el-form-item>
<el-form-item>
<el-button
type=
"success"
@
click=
"clean_demo"
>
清除所有数据
</el-button>
</el-form-item>
<!-- Prompt到文案 -->
<el-form-item
label=
"Prompt"
>
<el-input
v-model=
"form.chatgpt_prompt"
:autosize=
"true"
type=
"textarea"
/>
</el-form-item>
<el-form-item>
<el-button
type=
"primary"
@
click=
"onSubmitGpt"
>
生成文案(
{{
wenan_llm_name
}}
)
</el-button>
</el-form-item>
<el-form-item
label=
"文案"
>
<el-input
v-model=
"form.chatgpt_answer"
:autosize=
"true"
type=
"textarea"
/>
</el-form-item>
<!-- 角色 -->
<el-form-item>
<el-button
type=
"primary"
@
click=
"onAdaptRoles"
>
推理所有角色(
{{
role_llm_name
}}
)
</el-button>
<el-button
plain
@
click=
"clean_roles"
>
清空总角色列表
</el-button>
</el-form-item>
<el-form-item
label=
"角色"
>
<el-table
:data=
"form.chatgpt_answer_roles"
border
style=
"width: 100%; z-index: calc(var(--el-table-index) -1)"
>
<el-table-column
prop=
"角色"
label=
"角色"
>
<template
v-slot=
"scope"
>
<el-input
v-model=
"scope.row.角色"
:autosize=
"true"
type=
"textarea"
></el-input>
</
template
>
</el-table-column>
<el-table-column
prop=
"角色关键词"
label=
"角色关键词"
>
<
template
v-slot=
"scope"
>
<el-input
v-model=
"scope.row.角色关键词"
:autosize=
"true"
type=
"textarea"
></el-input>
</
template
>
</el-table-column>
</el-table>
</el-form-item>
<!-- 分镜 -->
<el-form-item>
<el-button
type=
"primary"
@
click=
"onAdapt"
>
分镜、推理关键词({{tuili_llm_name}})、翻译({{fanyi_llm_name}})、绘图
</el-button>
</el-form-item>
<el-form-item
label=
"分镜"
>
<el-table
:data=
"form.adapt_result_json"
border
style=
"width: 100%; z-index: calc(var(--el-table-index) -1)"
>
<el-table-column
prop=
"编号"
label=
"编号"
width=
"60"
/>
<el-table-column
prop=
"场景描述"
label=
"场景描述"
>
<
template
v-slot=
"scope"
>
<el-input
v-model=
"scope.row.场景描述"
:autosize=
"true"
type=
"textarea"
></el-input>
</
template
>
</el-table-column>
<el-table-column
prop=
"场景关键词"
label=
"场景关键词"
>
<
template
v-slot=
"scope"
>
<el-input
v-model=
"scope.row.场景关键词"
:autosize=
"true"
type=
"textarea"
></el-input>
</
template
>
</el-table-column>
<el-table-column
prop=
"角色"
label=
"角色"
>
<
template
v-slot=
"scope"
>
<el-input
v-model=
"scope.row.角色"
:autosize=
"true"
type=
"textarea"
></el-input>
</
template
>
</el-table-column>
<el-table-column
prop=
"角色关键词"
label=
"角色关键词"
>
<
template
v-slot=
"scope"
>
<el-input
v-model=
"scope.row.角色关键词"
:autosize=
"true"
type=
"textarea"
></el-input>
</
template
>
</el-table-column>
<el-table-column
prop=
"本镜配图"
label=
"本镜配图"
width=
"300"
>
<
template
v-slot=
"scope"
>
<div>
<el-image
:src=
"scope.row.本镜配图"
:zoom-rate=
"1.2"
:max-scale=
"1.5"
:min-scale=
"0.5"
:preview-src-list=
"[scope.row.本镜配图]"
fit=
"cover"
:hide-on-click-modal=
"true"
/>
</div>
</
template
>
</el-table-column>
<el-table-column
width=
"120"
label=
"操作"
align=
"center"
>
<!--
<template v-slot:header>
<el-button type="danger" size="default" @click="">批量绘制所有图片</el-button>
</template>
-->
<
template
v-slot=
"scope"
>
<div
style=
"margin: 10px 0"
><el-button
type=
"primary"
size=
"default"
@
click=
"onAdaptOne(scope.row)"
>
推理关键词
</el-button></div>
<div
style=
"margin: 10px 0"
><el-button
type=
"primary"
size=
"default"
@
click=
"onDrawOne(scope.row)"
>
翻译、绘图
</el-button></div>
<el-upload
class=
"upload-demo"
ref=
"upload"
list-type=
"picture"
:show-file-list=
"false"
:limit=
"1"
:action=
"actionUrl"
:on-success=
"handleUploadSuccess"
:on-exceed=
"handleExceed"
:data=
"
{item_id: scope.row.编号}"
>
<el-button
type=
"primary"
>
上传图片
</el-button>
</el-upload>
<div
style=
"margin: 10px 0"
><el-button
plain
@
click=
"showsdprompt(scope.row)"
>
debug
</el-button></div>
<el-dialog
v-model=
dialogVisible
width=
"80%"
>
<p>
{{
dialogData
}}
</p>
<template
#
footer
>
<div
class=
"dialog-footer"
>
<el-button
type=
"primary"
@
click=
"dialogVisible = false"
>
ok
</el-button>
</div>
</
template
>
</el-dialog>
</template>
</el-table-column>
</el-table>
</el-form-item>
<!-- 生成视频 -->
<el-form-item>
<el-button
type=
"primary"
@
click=
"onGenVideo"
>
生成视频
</el-button>
</el-form-item>
<el-form-item>
<video
:src=
"form.final_video"
controls
></video>
</el-form-item>
</el-form>
</main>
</template>
<
style
lang=
"scss"
scoped
>
.home-container
{
width
:
100%
;
}
</
style
>
<
style
lang=
"scss"
>
.home-container
{
.el-table
.el-table__cell
{
z-index
:
calc
(
var
(
--
el-table-index
)
-1
);
}
}
</
style
>
src/views/home/index.vue
View file @
2db83afd
...
...
@@ -27,14 +27,20 @@ const form = reactive({
const
sd_prompt_prefix
=
default_data
.
sd_prompt_prefix
;
const
sd_negative_prompt_prefix
=
default_data
.
sd_negative_prompt_prefix
;
const
wenan_llm
=
"langchain"
const
wenan_llm_name
=
"baichuan2-7b"
const
role_llm
=
"langchain"
const
role_llm_name
=
"baichuan2-7b"
const
tuili_llm
=
"langchain"
const
tuili_llm_name
=
"baichuan2-7b"
const
fanyi_llm
=
"langchain"
const
fanyi_llm_name
=
"baichuan2-7b"
const
tyqw
=
{
'api'
:
'tyqw'
,
'name'
:
'通义千问'
};
const
baichuan
=
{
'api'
:
'langchain'
,
'name'
:
'baichuan2-7b'
};
const
qwen
=
{
'api'
:
'langchain'
,
'name'
:
'Qwen-7B-Chat'
};
const
wenan_llm
=
qwen
.
api
const
wenan_llm_name
=
qwen
.
name
const
role_llm
=
tyqw
.
api
const
role_llm_name
=
tyqw
.
name
const
role_keywords_llm
=
qwen
.
api
const
role_keywords_llm_name
=
qwen
.
name
const
tuili_llm
=
qwen
.
api
const
tuili_llm_name
=
qwen
.
name
const
fanyi_llm
=
qwen
.
api
const
fanyi_llm_name
=
qwen
.
name
onMounted
(()
=>
{
...
...
@@ -42,6 +48,8 @@ onMounted(() => {
onChangeScreen
(
form
.
screen
);
});
const
delay
=
(
ms
:
any
)
=>
new
Promise
(
res
=>
setTimeout
(
res
,
ms
));
const
onSubmitGpt
=
()
=>
{
text2videoService
.
submitGpt
(
form
.
chatgpt_prompt
,
wenan_llm
)
...
...
@@ -69,34 +77,46 @@ const onAdaptRoles = async () => {
}
loading
.
value
=
true
;
// 推理角色
form
.
chatgpt_answer_roles
=
[];
try
{
const
adapt_restrict
=
`
指令:
请理解这个故事,给出这个故事的所有角色、角色关键词(性别(可以发挥想象进行补充,但一定要明确),年龄(可以发挥想象进行补充,但一定要明确),
肤色(可以发挥想象进行补充,但一定要明确),衣服(可以发挥想象进行补充,但一定要明确),发型(可以发挥想象进行补充,但一定要明确),发色(可以发挥想象进行补充,但一定要明确),
脸色(可以发挥想象进行补充,但一定要明确),五官特点(可以发挥想象进行补充,但一定要明确))。\n
要求:
角色和角色关键词要对应。
严格以如下格式返回:[{"角色":"","角色关键词":""}]`
;
const
keywords
=
await
text2videoService
.
submitGpt
(
form
.
chatgpt_answer
+
"
\n
"
+
adapt_restrict
,
role_llm
);
console
.
log
(
keywords
)
const
keywords_obj
=
utils
.
formatJsonObj
(
keywords
.
replace
(
/```json/g
,
''
).
replace
(
/```/g
,
''
))
console
.
log
(
keywords_obj
)
form
.
chatgpt_answer_roles
=
[]
if
(
'error'
in
keywords_obj
)
{
ElMessage
({
message
:
"未解析到角色"
,
type
:
"error"
,
});
}
else
{
for
(
let
item
of
keywords_obj
)
{
let
newObjItem
=
{
"角色"
:
JSON
.
stringify
(
item
[
"角色"
]).
replace
(
/"/g
,
''
),
"角色关键词"
:
JSON
.
stringify
(
item
[
"角色关键词"
]).
replace
(
/"/g
,
''
)
};
form
.
chatgpt_answer_roles
.
push
(
newObjItem
);
请理解这个故事,给出这个故事中的所有角色,多个角色以逗号分隔`
;
let
roles
=
await
text2videoService
.
submitGpt
(
"故事:
\n
"
+
form
.
chatgpt_answer
+
"
\n
"
+
adapt_restrict
,
role_llm
);
roles
=
roles
.
replace
(
/。/g
,
''
).
replace
(
/、/g
,
','
)
console
.
log
(
roles
)
const
roles_arr
=
roles
.
split
(
/
[
,,
]
/
);
console
.
log
(
roles_arr
)
async
function
processRoles
()
{
for
(
const
one_role
of
roles_arr
)
{
await
delay
(
100
);
const
adapt_keyword_restrict
=
`
指令:
请理解这个故事,给出这个角色“
${
one_role
.
trim
()}
”的关键词(性别(可以发挥想象进行补充,但一定要有),年龄(可以发挥想象进行补充,但一定要有),
肤色(可以发挥想象进行补充,但一定要有),衣服(可以发挥想象进行补充,但一定要有),发型(可以发挥想象进行补充,但一定要有),
发色(可以发挥想象进行补充,但一定要有),脸色(可以发挥想象进行补充,但一定要有),五官特点(可以发挥想象进行补充,但一定要有))。
要求:
关键词以逗号分隔。
只要返回关键词,不需要其他的说明文字。`
;
let
keywords
=
await
text2videoService
.
submitGpt
(
form
.
chatgpt_answer
+
"
\n
"
+
adapt_keyword_restrict
,
role_keywords_llm
);
keywords
=
keywords
.
replace
(
/。/g
,
''
).
replace
(
/、/g
,
','
)
form
.
chatgpt_answer_roles
.
push
({
"角色"
:
one_role
.
trim
(),
"角色关键词"
:
keywords
.
trim
()
});
}
}
try
{
await
processRoles
();
console
.
log
(
form
.
chatgpt_answer_roles
)
}
catch
(
error
)
{
ElMessage
({
message
:
String
(
error
),
type
:
"error"
});
}
finally
{
loading
.
value
=
false
;
// 最终关闭loading(无论成功或失败)
}
}
catch
(
error
)
{
ElMessage
({
...
...
@@ -139,8 +159,6 @@ const onAdapt = async () => {
}
console
.
log
(
form
.
adapt_result_json
)
const
delay
=
(
ms
:
any
)
=>
new
Promise
(
res
=>
setTimeout
(
res
,
ms
));
async
function
processScenes
()
{
for
(
const
item
of
form
.
adapt_result_json
)
{
await
onAdaptOne
(
item
);
...
...
@@ -179,46 +197,39 @@ const onAdaptOne = async (item: any) => {
try
{
const
adapt_restrict
=
`
指令:
请理解这个故事,
针对其中的这个场景:“
${
item
.
场景描述
}
”,给出这个场景的:
场景关键词(年代,空间,时间段,地理环境,天气,物品,人物,镜头角度)、
角色(从所有角色中选择本场景的角色)
。
请理解这个故事,
给出这个场景“
${
item
.
场景描述
}
”的关键词(年代(可以发挥想象进行补充,但一定要有),空间(可以发挥想象进行补充,但一定要有),
时间段(可以发挥想象进行补充,但一定要有),地理环境(可以发挥想象进行补充,但一定要有),天气(可以发挥想象进行补充,但一定要有),
物品(可以发挥想象进行补充,但一定要有),人物(可以发挥想象进行补充,但一定要有),镜头角度(可以发挥想象进行补充,但一定要有))
。
要求:
角色和角色关键词要对应。
严格以如下格式返回:[{"场景关键词":"(多个词以逗号分隔)","角色":"(角色以逗号分隔)"}]
除了按格式返回的内容之外,不要添加其他的任何说明。`
;
const
keywords
=
await
text2videoService
.
submitGpt
(
"故事:
\n
"
+
form
.
chatgpt_answer
+
"
\n
所有角色:
\n
"
+
JSON
.
stringify
(
form
.
chatgpt_answer_roles
)
+
"
\n
"
+
adapt_restrict
,
tuili_llm
);
关键词以逗号分隔。
只要返回关键词,不需要其他的说明文字。`
;
const
keywords
=
await
text2videoService
.
submitGpt
(
"故事:
\n
"
+
form
.
chatgpt_answer
+
"
\n
"
+
adapt_restrict
,
tuili_llm
);
// console.log(keywords)
const
keywords_obj
=
utils
.
formatJsonObj
(
keywords
.
replace
(
/```json/g
,
''
).
replace
(
/```/g
,
''
))
// console.log(keywords_obj)
if
(
'error'
in
keywords_obj
)
{
ElMessage
({
message
:
`分镜
${
item
.
编号
}
推理关键词失败,请重试`
,
type
:
"error"
,
});
item
.
场景关键词
=
keywords
;
const
adapt_role_restrict
=
`
指令:
请理解这个故事,针对其中的这个场景:“
${
item
.
场景描述
}
”,从所有角色中选择本场景的角色,多个角色以逗号分隔。`
;
const
item_roles
=
await
text2videoService
.
submitGpt
(
"故事:
\n
"
+
form
.
chatgpt_answer
+
"
\n
所有角色:
\n
"
+
JSON
.
stringify
(
form
.
chatgpt_answer_roles
)
+
"
\n
"
+
adapt_role_restrict
,
tuili_llm
);
// console.log(role_keywords)
if
(
form
.
chatgpt_answer_roles
.
length
===
0
)
{
// 总角色为空
item
.
角色
=
''
;
item
.
角色关键词
=
''
;
}
else
{
item
.
场景关键词
=
JSON
.
stringify
(
keywords_obj
[
0
].
场景关键词
).
replace
(
/"/g
,
''
);
if
(
form
.
chatgpt_answer_roles
.
length
===
0
)
{
// 总角色为空
item
.
角色
=
''
;
item
.
角色关键词
=
''
;
}
else
{
// 总角色不为空
// item.角色 = JSON.stringify(keywords_obj[0].角色).replace(/"/g, '');
// item.角色关键词 = JSON.stringify(keywords_obj[0].角色关键词).replace(/"/g, '');
const
item_roles
=
JSON
.
stringify
(
keywords_obj
[
0
].
角色
).
replace
(
/"/g
,
''
);
item
.
角色
=
item_roles
;
let
role_kws
=
""
const
item_roles_arr
=
item_roles
.
split
(
/
[
,,
]
/
);
item_roles_arr
.
forEach
(
one_item_role
=>
{
// 人工指定角色关键词,包含则取
form
.
chatgpt_answer_roles
.
forEach
(
i
=>
{
if
(
i
[
"角色"
].
includes
(
one_item_role
.
trim
())
||
one_item_role
.
includes
(
i
[
"角色"
].
trim
()))
{
role_kws
=
`
${
role_kws
}
【
${
i
[
"角色"
]}
:
${
i
[
"角色关键词"
]}
】`
}
})
// 总角色不为空
item
.
角色
=
item_roles
;
let
role_kws
=
""
const
item_roles_arr
=
item_roles
.
split
(
/
[
,,
]
/
);
item_roles_arr
.
forEach
(
one_item_role
=>
{
// 人工指定角色关键词,包含则取
form
.
chatgpt_answer_roles
.
forEach
(
i
=>
{
if
(
i
[
"角色"
].
includes
(
one_item_role
.
trim
())
||
one_item_role
.
includes
(
i
[
"角色"
].
trim
()))
{
role_kws
=
`
${
role_kws
}
【
${
i
[
"角色"
]}
:
${
i
[
"角色关键词"
]}
】`
}
})
item
.
角色关键词
=
role_kws
;
}
})
item
.
角色关键词
=
role_kws
;
}
}
catch
(
error
)
{
ElMessage
({
...
...
@@ -423,7 +434,7 @@ const handleExceed: UploadProps['onExceed'] = (files) => {
</el-form-item>
<!-- 角色 -->
<el-form-item>
<el-button
type=
"primary"
@
click=
"onAdaptRoles"
>
推理
所有角色(
{{
role
_llm_name
}}
)
</el-button>
<el-button
type=
"primary"
@
click=
"onAdaptRoles"
>
推理
角色(
{{
role_llm_name
}}
)、推理角色关键词(
{{
role_keywords
_llm_name
}}
)
</el-button>
<el-button
plain
@
click=
"clean_roles"
>
清空总角色列表
</el-button>
</el-form-item>
<el-form-item
label=
"角色"
>
...
...
@@ -442,7 +453,7 @@ const handleExceed: UploadProps['onExceed'] = (files) => {
</el-form-item>
<!-- 分镜 -->
<el-form-item>
<el-button
type=
"primary"
@
click=
"onAdapt"
>
分镜、推理
关键词({{tuili_llm_name}})、翻译
({{fanyi_llm_name}})、绘图
</el-button>
<el-button
type=
"primary"
@
click=
"onAdapt"
>
分镜、推理
场景关键词({{tuili_llm_name}})、英文描述
({{fanyi_llm_name}})、绘图
</el-button>
</el-form-item>
<el-form-item
label=
"分镜"
>
<el-table
:data=
"form.adapt_result_json"
border
style=
"width: 100%; z-index: calc(var(--el-table-index) -1)"
>
...
...
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