1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
<script setup lang="ts">
import { onMounted, reactive, ref } from 'vue'
import { Sunny, UploadFilled } from '@element-plus/icons-vue'
import { ElMessage, ElLoading } from 'element-plus'
import text2videoService from '@/api/service/text2videoService'
import utils from '@/utils/utils'
const loading = ref(false)
const step = ref(1)
const is_adapt_result_json = ref(1)
const form = reactive({
chatgpt_prompt: '帮我生成一个关于医生穿越到古代行侠仗义的故事,约200字左右',
chatgpt_answer:
'曾经的医生王强穿越回了古代,发现这个时代正值战乱时期。他觉得自己是时候行侠仗义,保护那些无辜受苦的人们了。王强在一个村庄里遇到了一个年轻的农民,叫李明。李明父母在战乱中被杀,他成了孤儿,并且被恶势力欺压。王强决定帮助李明。他教授李明一些基本的医术,并且帮助他恢复村庄的秩序。为了支援农民,王强到处奔走,为那些受伤的人们进行治疗。他在古代用现代医学知识,快速治愈了一些以前无法治愈的疾病。他趁机收集了一群志同道合的人,组建了一个抗击恶势力的义勇军。由于他的医术悉心教导,王强手下的队伍战斗力大增,并且开始挑战恶势力的统治。在战斗中,王强发现一支正义的侠盗团队正在保护受苦的人们。他决定与他们合作,将农民们和侠盗团队联合起来,共同对抗恶势力。最终,王强和他的队伍,还有侠盗团队成功地将恶势力赶出了村庄,恢复了和平。他们在古代留下了无穷的传奇,为人们带来了新的希望和幸福。医生王强也与李明成了好朋友,他们一起守护着村庄的和平与安宁。',
adapt_restrict:
'将上述文案改编为10个短视频分镜,给出每个分镜的场景描述、场景关键词(年代,空间,时间段,地理环境,天气,物品,人物,镜头角度)、角色、角色关键词(性别,年龄,肤色,衣服,发型,发色,脸色,五官特点,体态,情绪,肢体动作)。以如下json字符串的格式返回:{"分镜":[{"编号":"","场景描述":"","场景关键词":"","角色":"","角色关键词":""},...]}',
adapt_result: '',
// adapt_result_json: <Wm.ScriptsItem[]>[],
// adapt_result_json: [{"编号":"1","场景描述":"王强穿越回古代,来到一片战乱的村庄。","场景关键词":"古代,村庄,战乱,医生,王强","角色":"王强","角色关键词":"男性,中年,普通,白大褂,干练,自信,坚定,专注"},{"编号":"2","场景描述":"王强在村庄遇见年轻的农民李明。","场景关键词":"村庄,农民,相遇","角色":"王强,李明","角色关键词":"男性,中年,普通,白大褂,干练,自信,坚定,专注;男性,青年,普通,农民服装,干净,精明,忧伤"},{"编号":"3","场景描述":"王强教授李明基本的医术。","场景关键词":"教学,医术,基本","角色":"王强,李明","角色关键词":"男性,中年,普通,白大褂,干练,自信,坚定,专注;男性,青年,普通,农民服装,干净,精明,忧伤"},{"编号":"4","场景描述":"王强帮助李明恢复村庄秩序。","场景关键词":"村庄,恢复秩序","角色":"王强,李明","角色关键词":"男性,中年,普通,白大褂,干练,自信,坚定,专注;男性,青年,普通,农民服装,干净,精明,忧伤"},{"编号":"5","场景描述":"王强在古代使用现代医学知识治愈疾病。","场景关键词":"古代,医学知识,治愈疾病","角色":"王强","角色关键词":"男性,中年,普通,白大褂,干练,自信,坚定,专注"},{"编号":"6","场景描述":"王强组建抗击恶势力的义勇军。","场景关键词":"抗击恶势力,义勇军","角色":"王强","角色关键词":"男性,中年,普通,白大褂,干练,自信,坚定,专注"},{"编号":"7","场景描述":"王强与正义的侠盗团队合作。","场景关键词":"侠盗团队,合作","角色":"王强","角色关键词":"男性,中年,普通,白大褂,干练,自信,坚定,专注"},{"编号":"8","场景描述":"王强、李明和侠盗团队共同对抗恶势力。","场景关键词":"共同对抗,恶势力","角色":"王强,李明","角色关键词":"男性,中年,普通,白大褂,干练,自信,坚定,专注;男性,青年,普通,农民服装,干净,精明,忧伤"},{"编号":"9","场景描述":"王强和他的队伍驱逐恶势力,村庄恢复和平。","场景关键词":"驱逐恶势力,村庄和平","角色":"王强,李明","角色关键词":"男性,中年,普通,白大褂,干练,自信,坚定,专注;男性,青年,普通,农民服装,干净,精明,忧伤"},{"编号":"10","场景描述":"王强和李明成为好朋友,守护村庄的和平与安宁。","场景关键词":"好朋友,守护和平,安宁","角色":"王强,李明","角色关键词":"男性,中年,普通,白大褂,干练,自信,坚定,专注;男性,青年,普通,农民服装,干净,精明,忧伤"}],
adapt_result_json: [
{
编号: '1',
场景描述: '王强穿越回古代,来到一片战乱的村庄。',
场景关键词: '古代,村庄,战乱,医生,王强',
角色: '王强',
角色关键词: '男性,中年,普通,白大褂,干练,自信,坚定,专注'
},
{
编号: '2',
场景描述: '王强在村庄遇见年轻的农民李明。',
场景关键词: '村庄,农民,相遇',
角色: '王强,李明',
角色关键词: '男性,中年,普通,白大褂,干练,自信,坚定,专注;男性,青年,普通,农民服装,干净,精明,忧伤'
}
],
// ai_draw_json: <Wm.AiDrawItem[]>[],
ai_draw_json: [
{
编号: '1',
场景描述: '王强穿越回古代,来到一片战乱的村庄。',
画面描述词:
'Ancient, village, warfare, doctor, Wang Qiang, male, middle-aged, ordinary, white coat, capable, confident, determined, focused',
本镜配图: 'http://192.168.31.128:5001/assets/outputs/20240129175223829/1.png',
task_id: '20240129175223829'
},
{
编号: '2',
场景描述: '王强在村庄遇见年轻的农民李明。',
画面描述词:
"Village, farmer, encounter, middle-aged, ordinary, white coat, capable, confident, determined, focused; male, young, ordinary, farmer's clothing, clean, astute, sad",
本镜配图: 'http://192.168.31.128:5001/assets/outputs/20240129175223829/2.png',
task_id: '20240129175223829'
}
]
})
const sd_prompt_prefix = `best quality,masterpiece,realistic,HDR,UHD,8K,best quality,highres,absurdres,realistic,masterpiece,
Highly detailed,extreme detail description,Professional,lens_flare,cinematic_lighting,ultra-fine painting,
full body,Vivid Colors,physically-based rendering,sharp focus,wide shot,cinematic,lens_flare,reality_ray_tracing,`
const sd_negative_prompt_prefix = `multiple breasts, (mutated hands and fingers:1.5 ), (long body :1.3),
(mutation, poorly drawn :1.2) , black-white, bad anatomy, liquid body, liquid tongue, disfigured,
malformed, mutated, anatomical nonsense, malformed hands, long neck, blurred,
lowers, bad proportions, bad shadow, uncoordinated body, unnatural body, fused breasts,
bad breasts, huge breasts, poorly drawn breasts, extra breasts, liquid breasts, heavy breasts, missing breasts,
huge haunch, huge thighs, huge calf, bad hands, fused hand, missing hand, disappearing arms, disappearing thigh,
disappearing calf, disappearing legs, fused ears, bad ears, poorly drawn ears, extra ears, liquid ears, heavy ears,
missing ears, fused animal ears, bad animal ears, poorly drawn animal ears, extra animal ears, liquid animal ears,
heavy animal ears, missing animal ears, text, ui, error, missing fingers, missing limb, fused fingers,
one hand with more than 5 fingers, one hand with less than 5 fingers, one hand with more than 5 digit,
one hand with less than 5 digit, extra digit, fewer digits, fused digit, missing digit, bad digit, liquid digit,
colorful tongue, black tongue, cropped, watermark, username, blurry, JPEG artifacts, signature, 3D, 3D game,
3D game scene, 3D character, malformed feet, extra feet, bad feet, poorly drawn feet, fused feet, missing feet,
extra shoes, bad shoes, fused shoes, more than two shoes, poorly drawn shoes, bad gloves, poorly drawn gloves,
fused gloves, bad cum, poorly drawn cum, fused cum, bad hairs, poorly drawn hairs, fused hairs, big muscles, ugly,
bad face, fused face, poorly drawn face, cloned face, big face, long face, bad eyes, fused eyes poorly drawn eyes,
extra eyes, malformed limbs, more than 2 nipples, missing nipples, different nipples, fused nipples, bad nipples,
poorly drawn nipples, black nipples, colorful nipples, gross proportions. short arm, (((missing arms))), missing thighs,
missing calf, missing legs, mutation, duplicate, morbid, mutilated, poorly drawn hands, more than 1 left hand,
more than 1 right hand, deformed, (blurry), disfigured, missing legs, extra arms, extra thighs, more than 2 thighs,
extra calf, fused calf, nsfw,logo,text,extra legs, bad knee, extra knee, more than 2 legs, bad tails, bad mouth,
fused mouth, poorly drawn mouth, bad tongue, tongue within mouth, too long tongue, black tongue, big mouth, cracked mouth,
bad mouth, dirty face, dirty teeth, dirty pantie, fused pantie, poorly drawn pantie, fused cloth, poorly drawn cloth, bad pantie,
yellow teeth, thick lips, bad cameltoe, colorful cameltoe, bad asshole, poorly drawn asshole, fused asshole, missing asshole,
bad anus, bad pussy, bad crotch, bad crotch seam, fused anus, fused pussy, fused anus, fused crotch, poorly drawn crotch,
fused seam, poorly drawn anus, poorly drawn pussy, poorly drawn crotch, poorly drawn crotch seam, bad thigh gap, missing thigh gap,
fused thigh gap, liquid thigh gap, poorly drawn thigh gap, poorly drawn anus, bad collarbone, fused collarbone, missing collarbone,
liquid collarbone, obesity, worst quality, low quality, normal quality, liquid tentacles, bad tentacles, poorly drawn tentacles,
split tentacles, fused tentacles, missing clit, bad clit, fused clit, colorful clit, black clit, liquid clit, QR code, bar code, censored,
safety panties, safety knickers, beard, furry ,pony, pubic hair, mosaic, excrement, faeces, shit, futa, testis,mutated hands and fingers,
deformed,bad anatomy,disfigured,poorly drawn face,lowres,mutated,extra limb,ugly,poorly drawn hands,missing limb,floating limbs,
disconnected limbs,malformed hands,out of focus,long neck,long body,gape,`
onMounted(() => {})
const onSubmitGpt = () => {
text2videoService
.submitGpt(form.chatgpt_prompt)
.then((result: string) => {
// console.log(result);
form.chatgpt_answer = result
})
.catch((error: any) => {
// console.error(error);
ElMessage({
message: error,
type: 'error'
})
})
}
const onAdapt = () => {
if (!form.chatgpt_answer) {
ElMessage({
message: '内容不能为空',
type: 'error'
})
return
}
text2videoService
.submitGpt(form.chatgpt_answer + '\n' + form.adapt_restrict)
.then((result: string) => {
console.log(result)
try {
form.adapt_result_json = utils.formatJsonObj(result).分镜
} catch (error) {
form.adapt_result = result
is_adapt_result_json.value = 0
}
})
.catch((error: any) => {
console.error(error)
ElMessage({
message: error,
type: 'error'
})
})
}
// const drawOne = async (task_id: string, item_idx: string, sd_prompt: string, sd_negative_prompt: string) => {
// try {
// const sd_result = await text2videoService.submitSD(task_id, item_idx, sd_prompt, sd_negative_prompt);
// return sd_result
// } catch (error) {
// return ""
// }
// };
const onDraw = async () => {
form.ai_draw_json = []
loading.value = true
const task_id = utils.genDateTimeStr()
const taskPromises = form.adapt_result_json.map(async (item) => {
try {
const result = await text2videoService.submitGpt(
`请将这些内容“${item.场景关键词},${item.角色关键词}”翻译为英文`
)
const newResult = result.replaceAll('.', '').replaceAll('"', '')
try {
const sd_prompt = sd_prompt_prefix + newResult
const sd_result = await text2videoService.submitSD(
task_id,
item.编号,
sd_prompt,
sd_negative_prompt_prefix
)
return {
编号: item.编号,
场景描述: item.场景描述,
画面描述词: newResult,
本镜配图: sd_result,
task_id: task_id
}
} catch (error) {
ElMessage({
message: String(error),
type: 'error'
})
return {
编号: item.编号,
场景描述: item.场景描述,
画面描述词: newResult,
本镜配图: '',
task_id: task_id
}
}
} catch (error) {
// console.error(error);
ElMessage({
message: String(error),
type: 'error'
})
return {
编号: item.编号,
场景描述: item.场景描述,
画面描述词: '',
本镜配图: '',
task_id: task_id
}
}
})
// 所有请求都返回后,重新排序
try {
const results = await Promise.all(taskPromises)
form.ai_draw_json = results.sort((a, b) => parseInt(a.编号) - parseInt(b.编号))
} catch (error) {
// 处理错误
ElMessage({
message: String(error),
type: 'error'
})
} finally {
// 最终关闭loading(无论成功或失败)
loading.value = false
}
}
const onDrawOne = (idxStr: string) => {
const idx = parseInt(idxStr) - 1
const task_id = form.ai_draw_json[idx].task_id
// console.log(task_id)
const newResult = form.ai_draw_json[idx].画面描述词
text2videoService
.submitSD(task_id, idxStr, newResult, sd_negative_prompt_prefix)
.then((result: string) => {
// console.log(result);
form.ai_draw_json[idx].本镜配图 = ''
form.ai_draw_json[idx].本镜配图 = result
})
.catch((error: any) => {
// console.error(error);
ElMessage({
message: error,
type: 'error'
})
})
}
</script>
<template>
<main class="home-container">
<!-- 标题 -->
<el-divider content-position="left">text2video</el-divider>
<el-form :model="form" label-width="114px">
<!-- 小说到文案 -->
<el-form-item label="小说">
<el-input
v-model="form.chatgpt_prompt"
:autosize="true"
type="textarea"
placeholder="输入小说"
/>
</el-form-item>
<el-form-item>
<el-button type="primary" @click="onSubmitGpt">提交chatgpt,生成文案</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 label="分镜要求">
<el-input v-model="form.adapt_restrict" :autosize="true" type="textarea" placeholder="" />
</el-form-item>
<el-form-item>
<el-button type="primary" @click="onAdapt"
>填写或修改分镜要求,提交chatgpt,生成分镜</el-button
>
</el-form-item>
<el-form-item label="分镜结果" v-if="is_adapt_result_json === 0">
<el-input v-model="form.adapt_result" :autosize="true" type="textarea" />
</el-form-item>
<el-form-item label="分镜结果" v-if="is_adapt_result_json === 1">
<el-table :data="form.adapt_result_json" border style="width: 100%">
<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 width="100">
<template #header>
<el-button type="primary" size="small" @click="">一键推理</el-button>
</template>
<template #default="scope">
<el-button type="primary" size="small" @click="">推理</el-button>
</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 width="100">
<template #header>
<el-button type="primary" size="small" @click="">一键推理</el-button>
</template>
<template #default="scope">
<el-button type="primary" size="small" @click="">推理</el-button>
</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="onDraw">组合SD提示词并绘图</el-button>
</el-form-item>
<el-form-item label="绘图">
<el-table
:data="form.ai_draw_json"
border
style="width: 100%; z-index: calc(var(--el-table-index) -1)"
v-loading="loading"
>
<el-table-column prop="编号" label="编号" width="60" />
<el-table-column prop="场景描述" label="场景描述" />
<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">
<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="100" label="操作">
<template v-slot="scope">
<el-button type="primary" size="small" @click="onDrawOne(scope.row.编号)"
>重绘本镜</el-button
>
</template>
</el-table-column>
</el-table>
</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>