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
e9f12f92
Commit
e9f12f92
authored
Jan 25, 2024
by
Administrator
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
小改
parent
6141f9e4
Pipeline
#356
canceled with stages
Changes
7
Pipelines
1
Hide whitespace changes
Inline
Side-by-side
Showing
7 changed files
with
317 additions
and
286 deletions
+317
-286
App.vue
src/App.vue
+4
-31
text2videoService.ts
src/api/service/text2videoService.ts
+10
-0
main.css
src/assets/main.css
+2
-13
index copy.vue
src/views/home/index copy.vue
+244
-0
index.vue
src/views/home/index.vue
+43
-196
lib.wm.api.d.ts
typings/types/wm/lib.wm.api.d.ts
+13
-45
vite.config.ts
vite.config.ts
+1
-1
No files found.
src/App.vue
View file @
e9f12f92
<
script
setup
lang=
"ts"
>
<
script
setup
lang=
"ts"
>
import
{
RouterLink
,
RouterView
}
from
'vue-router'
import
{
RouterLink
,
RouterView
}
from
"vue-router"
;
import
{
ElConfigProvider
}
from
'element-plus'
import
{
ElConfigProvider
}
from
"element-plus"
;
import
zhCn
from
'element-plus/dist/locale/zh-cn.mjs'
import
zhCn
from
"element-plus/dist/locale/zh-cn.mjs"
;
const
locale
=
zhCn
const
locale
=
zhCn
;
</
script
>
</
script
>
<
template
>
<
template
>
...
@@ -46,31 +46,4 @@ nav a {
...
@@ -46,31 +46,4 @@ nav a {
nav
a
:first-of-type
{
nav
a
:first-of-type
{
border
:
0
;
border
:
0
;
}
}
@media
(
min-width
:
1024px
)
{
header
{
display
:
flex
;
place-items
:
center
;
padding-right
:
calc
(
var
(
--section-gap
)
/
2
);
}
.logo
{
margin
:
0
2rem
0
0
;
}
header
.wrapper
{
display
:
flex
;
place-items
:
flex-start
;
flex-wrap
:
wrap
;
}
nav
{
text-align
:
left
;
margin-left
:
-1rem
;
font-size
:
1rem
;
padding
:
1rem
0
;
margin-top
:
1rem
;
}
}
</
style
>
</
style
>
src/api/service/videoService.ts
→
src/api/service/
text2
videoService.ts
View file @
e9f12f92
/**
/**
*
视频转换
相关接口
* 相关接口
*/
*/
import
request
from
'@/api/request'
import
request
from
'@/api/request'
export
default
{
export
default
{
/**
genScriptsByGpt
(
postData
:
any
)
{
* 视频转换
return
request
.
post
(
'/text2video/gen_scripts_by_gpt'
,
postData
)
*/
wmVideoCut
(
postData
:
any
)
{
return
request
.
post
(
'/wm_video_cut'
,
postData
)
}
}
}
}
src/assets/main.css
View file @
e9f12f92
...
@@ -4,7 +4,8 @@
...
@@ -4,7 +4,8 @@
max-width
:
1280px
;
max-width
:
1280px
;
margin
:
0
auto
;
margin
:
0
auto
;
padding
:
2rem
;
padding
:
2rem
;
display
:
flex
;
justify-content
:
center
;
font-weight
:
normal
;
font-weight
:
normal
;
}
}
...
@@ -21,15 +22,3 @@ a,
...
@@ -21,15 +22,3 @@ a,
}
}
}
}
@media
(
min-width
:
1024px
)
{
body
{
display
:
flex
;
place-items
:
center
;
}
#app
{
display
:
grid
;
grid-template-columns
:
1
fr
1
fr
;
padding
:
0
2rem
;
}
}
src/views/home/index copy.vue
0 → 100644
View file @
e9f12f92
<
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
{
useLanguage
}
from
'./compositions/index'
import
videoService
from
'@/api/service/videoService'
import
exportFile
from
'@/utils/exportFile'
import
{
whenMouse
}
from
'element-plus/es/utils/index.mjs'
const
{
languages
}
=
useLanguage
()
const
step
=
ref
(
1
)
const
form
=
reactive
({
language
:
'en'
,
video
:
''
,
timeline
:
<
Wm
.
TimelineItem
[]
>
[],
withSub
:
true
})
const
upload
=
ref
<
UploadInstance
>
()
const
actionUrl
=
ref
(
import
.
meta
.
env
.
MODE
===
'production'
?
'/upload_file'
:
import
.
meta
.
env
.
VITE_APP_BASE_API
+
'/upload_file'
)
onMounted
(()
=>
{})
const
onSubmit
=
()
=>
{
if
(
!
form
.
video
)
{
ElMessage
({
message
:
'请先上传视频'
,
type
:
'error'
})
return
}
let
postData
:
Wm
.
VideoCutOptions
=
{
instances
:
[
{
video
:
form
.
video
,
lang
:
form
.
language
,
steps
:
[
'step'
+
step
.
value
]
}
]
}
if
(
step
.
value
===
2
)
{
let
srt_json_in
=
form
.
timeline
postData
.
instances
[
0
]
=
{
...
postData
.
instances
[
0
],
with_sub
:
form
.
withSub
,
srt_json_in
:
srt_json_in
}
}
videoService
.
wmVideoCut
(
postData
)
.
then
((
res
:
any
)
=>
{
console
.
log
(
res
)
ElMessage
({
message
:
'操作成功'
,
type
:
'success'
})
const
ishttps
=
document
.
location
.
protocol
===
'https:'
// console.log(document.location)
if
(
res
)
{
if
(
step
.
value
===
1
)
{
form
.
timeline
=
res
.
result
step
.
value
=
2
}
else
{
let
url
=
''
const
final_video_url
=
res
.
result
if
(
ishttps
)
{
url
=
final_video_url
.
replace
(
'http://'
,
'https://'
)
}
else
{
url
=
final_video_url
.
replace
(
'https://'
,
'http://'
)
}
url
=
'/download'
+
url
.
substring
(
1
,
url
.
length
)
console
.
log
(
url
)
const
arr_name
=
final_video_url
.
split
(
'/'
)
const
file_name
=
arr_name
[
arr_name
.
length
-
1
]
// 获取文件名
fetch
(
url
)
.
then
((
url
)
=>
url
.
blob
())
.
then
((
blob
:
any
)
=>
{
exportFile
.
getVideoFile
(
blob
,
file_name
)
})
step
.
value
=
1
}
}
})
.
catch
((
err
:
any
)
=>
{
console
.
log
(
err
)
ElMessage
({
message
:
'操作失败'
+
err
,
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
()
}
const
handleUploadSuccess
=
(
val
:
Wm
.
UploadResult
)
=>
{
form
.
video
=
val
.
result
.
file_url
ElMessage
({
message
:
'上传成功'
,
type
:
'success'
})
}
const
handleBeforeUpload
=
(
file
:
any
)
=>
{
const
isLt100M
=
file
.
size
/
1024
/
1024
<
100
const
fileName
=
file
.
name
const
fileType
=
fileName
.
substring
(
fileName
.
lastIndexOf
(
'.'
))
console
.
log
(
fileType
)
const
isMp4
=
(
file
.
type
.
indexOf
(
'video'
)
>
-
1
&&
file
.
type
===
'video/mp4'
)
||
fileType
===
'.mp4'
if
(
!
isLt100M
)
{
ElMessage
.
error
(
'上传文件大小不能超过 100MB!'
)
return
false
}
if
(
!
isMp4
)
{
ElMessage
.
error
(
'视频仅支持MP4格式!'
)
return
false
}
return
isMp4
&&
isLt100M
}
const
handleRemove
=
()
=>
{
form
.
video
=
''
}
</
script
>
<
template
>
<main
class=
"home-container"
>
<el-divider
content-position=
"left"
>
视频转换(先根据视频生成翻译,再转换视频)
</el-divider
>
<el-form
:model=
"form"
label-width=
"114px"
>
<el-form-item
label=
"选择语言"
>
<el-select
v-model=
"form.language"
placeholder=
"请选择要转换的语言"
>
<el-option
v-for=
"item in languages"
:key=
"item.value"
:label=
"item.label"
:value=
"item.value"
/>
</el-select>
</el-form-item>
<el-form-item
label=
"上传视频"
>
<el-upload
class=
"upload-demo"
drag
ref=
"upload"
accept=
".mp4"
:limit=
"1"
:action=
"actionUrl"
:on-success=
"handleUploadSuccess"
:on-exceed=
"handleExceed"
:on-remove=
"handleRemove"
:before-upload=
"handleBeforeUpload"
>
<el-icon
class=
"el-icon--upload"
><upload-filled
/></el-icon>
<div
class=
"el-upload__text"
>
将需要转换的视频文件拖到此处或
<em>
点击上传
</em>
</div>
<template
#
tip
>
<div
class=
"el-upload__tip"
>
<span>
1、视频请上传mp4格式;
</span>
<span>
2、视频大小控制在100M以内
</span>
</div>
</
template
>
</el-upload>
</el-form-item>
<el-form-item
label=
"校对翻译"
v-if=
"step === 2"
>
<!-- <el-timeline>
<el-timeline-item placement="top"
v-for="(srt, index) in form.timeline"
:key="index"
:timestamp="srt.start + ' --- ' + srt.end">
<el-input v-model="srt.content"
style="width: 500px"
:autosize="{ minRows: 1, maxRows: 3 }"
type="textarea"
/>
</el-timeline-item>
</el-timeline> -->
<div
v-for=
"(srt, index) in form.timeline"
>
<el-icon
v-if=
"srt.content != '< No Speech >'"
color=
"#409EFC"
size=
"10px"
>
<BellFilled
/>
</el-icon>
<span
v-if=
"srt.content != '< No Speech >'"
>
{{ srt.start + " --- " + srt.end }}
</span>
<el-input
v-if=
"srt.content != '< No Speech >'"
v-model=
"srt.content"
style=
"width: 600px; margin: 5px 0"
:autosize=
"{ minRows: 1, maxRows: 3 }"
type=
"textarea"
/>
</div>
</el-form-item>
<el-form-item
label=
"是否需要字幕"
v-if=
"step === 2"
>
<el-select
v-model=
"form.withSub"
placeholder=
"是否需要字幕"
>
<el-option
label=
"是"
:value=
"true"
/>
<el-option
label=
"否"
:value=
"false"
/>
</el-select>
</el-form-item>
<el-form-item>
<el-button
type=
"primary"
@
click=
"onSubmit"
>
{{ step === 1 ? "翻译" : "转换" }}
</el-button>
</el-form-item>
</el-form>
</main>
</template>
<
style
lang=
"scss"
scoped
>
.home-container
{
.upload-demo
{
width
:
600px
;
}
.el-upload__tip
{
>
span
{
display
:
flex
;
line-height
:
20px
;
}
}
}
</
style
>
@/api/service/myService
\ No newline at end of file
src/views/home/index.vue
View file @
e9f12f92
<
script
setup
lang=
"ts"
>
<
script
setup
lang=
"ts"
>
import
{
onMounted
,
reactive
,
ref
}
from
'vue'
import
{
onMounted
,
reactive
,
ref
}
from
"vue"
;
import
{
Sunny
,
UploadFilled
}
from
'@element-plus/icons-vue'
import
{
Sunny
,
UploadFilled
}
from
"@element-plus/icons-vue"
;
import
{
import
{
ElMessage
}
from
"element-plus"
;
ElMessage
,
import
text2videoService
from
"@/api/service/text2videoService"
;
genFileId
,
type
UploadInstance
,
type
UploadProps
,
type
UploadRawFile
}
from
'element-plus'
import
{
useLanguage
}
from
'./compositions/index'
import
videoService
from
'@/api/service/videoService'
import
exportFile
from
'@/utils/exportFile'
import
{
whenMouse
}
from
'element-plus/es/utils/index.mjs'
const
{
languages
}
=
useLanguage
()
const
step
=
ref
(
1
);
const
step
=
ref
(
1
)
const
form
=
reactive
({
const
form
=
reactive
({
language
:
'en'
,
chatgpt_prompt
:
""
,
video
:
''
,
});
timeline
:
<
Wm
.
TimelineItem
[]
>
[],
withSub
:
true
})
const
upload
=
ref
<
UploadInstance
>
()
const
actionUrl
=
ref
(
onMounted
(()
=>
{});
import
.
meta
.
env
.
MODE
===
'production'
?
'/upload_file'
:
import
.
meta
.
env
.
VITE_APP_BASE_API
+
'/upload_file'
)
onMounted
(()
=>
{})
const
onSubmit
=
()
=>
{
const
onSubmit
=
()
=>
{
if
(
!
form
.
video
)
{
if
(
!
form
.
chatgpt_prompt
)
{
ElMessage
({
ElMessage
({
message
:
'请先上传视频'
,
message
:
"prompt不能为空"
,
type
:
'error'
type
:
"error"
,
})
})
;
return
return
;
}
}
let
postData
:
Wm
.
VideoCutOptions
=
{
let
postData
=
{
instances
:
[
source_text
:
form
.
chatgpt_prompt
,
{
};
video
:
form
.
video
,
lang
:
form
.
language
,
steps
:
[
'step'
+
step
.
value
]
}
]
}
if
(
step
.
value
===
2
)
{
let
srt_json_in
=
form
.
timeline
postData
.
instances
[
0
]
=
{
...
postData
.
instances
[
0
],
with_sub
:
form
.
withSub
,
srt_json_in
:
srt_json_in
}
}
videoService
text2
videoService
.
wmVideoCu
t
(
postData
)
.
genScriptsByGp
t
(
postData
)
.
then
((
res
:
any
)
=>
{
.
then
((
res
:
any
)
=>
{
console
.
log
(
res
)
console
.
log
(
res
)
;
ElMessage
({
ElMessage
({
message
:
'操作成功'
,
message
:
"操作成功"
,
type
:
'success'
type
:
"success"
,
})
});
const
ishttps
=
document
.
location
.
protocol
===
'https:'
// if (res) {
// console.log(document.location)
if
(
res
)
{
if
(
step
.
value
===
1
)
{
form
.
timeline
=
res
.
result
step
.
value
=
2
}
else
{
let
url
=
''
const
final_video_url
=
res
.
result
if
(
ishttps
)
{
url
=
final_video_url
.
replace
(
'http://'
,
'https://'
)
}
else
{
url
=
final_video_url
.
replace
(
'https://'
,
'http://'
)
}
url
=
'/download'
+
url
.
substring
(
1
,
url
.
length
)
console
.
log
(
url
)
const
arr_name
=
final_video_url
.
split
(
'/'
)
// }
const
file_name
=
arr_name
[
arr_name
.
length
-
1
]
// 获取文件名
fetch
(
url
)
.
then
((
url
)
=>
url
.
blob
())
.
then
((
blob
:
any
)
=>
{
exportFile
.
getVideoFile
(
blob
,
file_name
)
})
step
.
value
=
1
}
}
})
})
.
catch
((
err
:
any
)
=>
{
.
catch
((
err
:
any
)
=>
{
console
.
log
(
err
)
console
.
log
(
err
)
;
ElMessage
({
ElMessage
({
message
:
'操作失败'
+
err
,
message
:
"操作失败"
+
err
,
type
:
'error'
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
()
}
const
handleUploadSuccess
=
(
val
:
Wm
.
UploadResult
)
=>
{
form
.
video
=
val
.
result
.
file_url
ElMessage
({
message
:
'上传成功'
,
type
:
'success'
})
}
const
handleBeforeUpload
=
(
file
:
any
)
=>
{
const
isLt100M
=
file
.
size
/
1024
/
1024
<
100
const
fileName
=
file
.
name
const
fileType
=
fileName
.
substring
(
fileName
.
lastIndexOf
(
'.'
))
console
.
log
(
fileType
)
const
isMp4
=
(
file
.
type
.
indexOf
(
'video'
)
>
-
1
&&
file
.
type
===
'video/mp4'
)
||
fileType
===
'.mp4'
if
(
!
isLt100M
)
{
ElMessage
.
error
(
'上传文件大小不能超过 100MB!'
)
return
false
}
if
(
!
isMp4
)
{
ElMessage
.
error
(
'视频仅支持MP4格式!'
)
return
false
}
return
isMp4
&&
isLt100M
}
const
handleRemove
=
()
=>
{
form
.
video
=
''
}
</
script
>
</
script
>
<
template
>
<
template
>
<main
class=
"home-container"
>
<main
class=
"home-container"
>
<el-divider
content-position=
"left"
<el-divider
content-position=
"left"
>
text2video
</el-divider>
>
视频转换(先根据视频生成翻译,再转换视频)
</el-divider
>
<el-form
:model=
"form"
label-width=
"114px"
>
<el-form
:model=
"form"
label-width=
"114px"
>
<el-form-item
label=
"选择语言"
>
<el-form-item
label=
"chatgpt prompt"
>
<el-select
v-model=
"form.language"
placeholder=
"请选择要转换的语言"
>
<el-input
<el-option
v-model=
"form.chatgpt_prompt"
v-for=
"item in languages"
:autosize=
"
{ minRows: 4, maxRows: 10 }"
:key=
"item.value"
type="textarea"
:label=
"item.label"
placeholder="Please input"
:value=
"item.value"
/>
/>
</el-select>
</el-form-item>
</el-form-item>
<el-form-item
label=
"上传视频"
>
<!--
<el-form-item
label=
"校对"
v-if=
"step === 2"
>
<el-upload
class=
"upload-demo"
drag
ref=
"upload"
accept=
".mp4"
:limit=
"1"
:action=
"actionUrl"
:on-success=
"handleUploadSuccess"
:on-exceed=
"handleExceed"
:on-remove=
"handleRemove"
:before-upload=
"handleBeforeUpload"
>
<el-icon
class=
"el-icon--upload"
><upload-filled
/></el-icon>
<div
class=
"el-upload__text"
>
将需要转换的视频文件拖到此处或
<em>
点击上传
</em>
</div>
<template
#
tip
>
<div
class=
"el-upload__tip"
>
<span>
1、视频请上传mp4格式;
</span>
<span>
2、视频大小控制在100M以内
</span>
</div>
</
template
>
</el-upload>
</el-form-item>
<el-form-item
label=
"校对翻译"
v-if=
"step === 2"
>
<!-- <el-timeline>
<el-timeline-item placement="top"
v-for="(srt, index) in form.timeline"
:key="index"
:timestamp="srt.start + ' --- ' + srt.end">
<el-input v-model="srt.content"
style="width: 500px"
:autosize="{ minRows: 1, maxRows: 3 }"
type="textarea"
/>
</el-timeline-item>
</el-timeline> -->
<div
v-for=
"(srt, index) in form.timeline"
>
<div
v-for=
"(srt, index) in form.timeline"
>
<el-icon
v-if=
"srt.content != '
<
No
Speech
>
'" color="#409EFC" size="10px">
<el-icon
v-if=
"srt.content != '
<
No
Speech
>
'" color="#409EFC" size="10px">
<BellFilled
/>
<BellFilled
/>
...
@@ -211,34 +75,17 @@ const handleRemove = () => {
...
@@ -211,34 +75,17 @@ const handleRemove = () => {
type="textarea"
type="textarea"
/>
/>
</div>
</div>
</el-form-item>
</el-form-item>
-->
<el-form-item
label=
"是否需要字幕"
v-if=
"step === 2"
>
<el-select
v-model=
"form.withSub"
placeholder=
"是否需要字幕"
>
<el-option
label=
"是"
:value=
"true"
/>
<el-option
label=
"否"
:value=
"false"
/>
</el-select>
</el-form-item>
<el-form-item>
<el-form-item>
<el-button
type=
"primary"
@
click=
"onSubmit"
<el-button
type=
"primary"
@
click=
"onSubmit"
>
确定
</el-button>
>
{{ step === 1 ? "翻译" : "转换" }}
</el-button>
</el-form-item>
</el-form-item>
</el-form>
</el-form>
</main>
</main>
</
template
>
</
template
>
<
style
lang=
"scss"
scoped
>
<
style
lang=
"scss"
scoped
>
.home-container
{
.home-container
{
.upload-demo
{
width
:
1000px
;
width
:
600px
;
}
.el-upload__tip
{
>
span
{
display
:
flex
;
line-height
:
20px
;
}
}
}
}
</
style
>
</
style
>
typings/types/wm/lib.wm.api.d.ts
View file @
e9f12f92
declare
namespace
Wm
{
import
type
internal
from
"stream"
interface
UploadResult
{
result
:
{
/**
* 上传后的文件地址
*/
file_url
:
string
}
}
interface
VideoCutOptions
{
instances
:
VideoCutOptionsInstance
[]
}
interface
VideoCutOptionsInstance
{
declare
namespace
Wm
{
/**
// chatgpt请求
* 需要转换的视频地址-通过上传接口返回的地址
interface
GenScriptsByGptOptions
{
*/
prompt
:
string
video
:
string
// 需要转换的语言
lang
:
string
// 步骤
steps
:
string
[]
// 最终视频是否需要合并字幕
with_sub
?:
boolean
// 修改后的字幕
srt_json_in
?:
any
}
interface
VideoCutResultItem
{
/**
* 转换后的视频地址
*/
final_video_url
:
string
/**
* 转换后的字幕地址
*/
srt_url
:
string
}
}
interface
VideoCutResult
{
// chatgpt回复
result
:
VideoCutResultItem
interface
GenScriptsByGptResult
{
result
:
GenScriptsByGptResultItem
}
}
interface
GenScriptsByGptResultItem
{
interface
TimelineItem
{
code
:
int
index
:
string
data
:
any
start
:
string
message
:
string
end
:
string
content
:
string
}
}
}
}
vite.config.ts
View file @
e9f12f92
...
@@ -26,7 +26,7 @@ export default defineConfig({
...
@@ -26,7 +26,7 @@ export default defineConfig({
server
:
{
server
:
{
proxy
:
{
proxy
:
{
'/api/'
:
{
'/api/'
:
{
target
:
'http://1
92.168.31.96:8080
'
,
// 后端服务实际地址
target
:
'http://1
27.0.0.1:5000/
'
,
// 后端服务实际地址
changeOrigin
:
true
,
changeOrigin
:
true
,
rewrite
:
(
path
:
any
)
=>
path
.
replace
(
/^
\/
api/
,
''
)
rewrite
:
(
path
:
any
)
=>
path
.
replace
(
/^
\/
api/
,
''
)
}
}
...
...
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