头像视频合成支持动态模型
This commit is contained in:
@@ -42,3 +42,12 @@ export function getVideoSynthesisStatus(taskId) {
|
||||
method: 'get'
|
||||
})
|
||||
}
|
||||
|
||||
// 播放视频
|
||||
export function playVideo(minioPath, expires = 900) {
|
||||
return request({
|
||||
url: `/video-synthesis/play/${minioPath}`,
|
||||
method: 'get',
|
||||
params: { expires }
|
||||
})
|
||||
}
|
||||
|
||||
@@ -114,8 +114,12 @@
|
||||
<el-col :span="12">
|
||||
<el-form-item label="模型供应商" prop="modelProvider">
|
||||
<el-select v-model="form.modelProvider" placeholder="请选择模型供应商" style="width: 100%">
|
||||
<el-option label="dashscope" value="dashscope" />
|
||||
<el-option label="其他" value="other" />
|
||||
<el-option
|
||||
v-for="option in modelProviderOptions"
|
||||
:key="option.value"
|
||||
:label="option.label"
|
||||
:value="option.value"
|
||||
/>
|
||||
</el-select>
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
@@ -243,7 +247,28 @@ export default {
|
||||
]
|
||||
},
|
||||
imageOptions: [],
|
||||
audioOptions: []
|
||||
audioOptions: [],
|
||||
selectedImageModel: '' // 存储选中头像的模型名
|
||||
}
|
||||
},
|
||||
computed: {
|
||||
// 根据选中头像的模型名动态计算模型供应商选项
|
||||
modelProviderOptions() {
|
||||
if (this.selectedImageModel === 'emo-detect-v1') {
|
||||
return [
|
||||
{ label: 'emo-v1', value: 'emo-v1' }
|
||||
]
|
||||
} else if (this.selectedImageModel === 'liveportrait-detect') {
|
||||
return [
|
||||
{ label: 'liveportrait', value: 'liveportrait' }
|
||||
]
|
||||
} else {
|
||||
// 默认选项
|
||||
return [
|
||||
{ label: 'dashscope', value: 'dashscope' },
|
||||
{ label: '其他', value: 'other' }
|
||||
]
|
||||
}
|
||||
}
|
||||
},
|
||||
mounted() {
|
||||
@@ -272,7 +297,8 @@ export default {
|
||||
url: item.imageUrl,
|
||||
avatarName: item.avatarName,
|
||||
ownerName: item.ownerName,
|
||||
ownerPhone: item.ownerPhone
|
||||
ownerPhone: item.ownerPhone,
|
||||
modelName: item.modelName || item.model || '' // 获取模型名信息
|
||||
}))
|
||||
console.log('Image options set:', this.imageOptions)
|
||||
} else if (response && response.success === false) {
|
||||
@@ -280,18 +306,18 @@ export default {
|
||||
this.$message.error(`获取头像列表失败: ${response.message || '未知错误'}`)
|
||||
// 使用模拟数据
|
||||
this.imageOptions = [
|
||||
{ id: 'img-001', name: '头像1', url: 'http://example.com/images/avatar1.jpg', ownerName: '张三', ownerPhone: '13800138000' },
|
||||
{ id: 'img-002', name: '头像2', url: 'http://example.com/images/avatar2.jpg', ownerName: '李四', ownerPhone: '13900139000' },
|
||||
{ id: 'img-003', name: '头像3', url: 'http://example.com/images/avatar3.jpg', ownerName: '王五', ownerPhone: '13700137000' }
|
||||
{ id: 'img-001', name: '头像1', url: 'http://example.com/images/avatar1.jpg', ownerName: '张三', ownerPhone: '13800138000', modelName: 'emo-detect-v1' },
|
||||
{ id: 'img-002', name: '头像2', url: 'http://example.com/images/avatar2.jpg', ownerName: '李四', ownerPhone: '13900139000', modelName: 'liveportrait-detect' },
|
||||
{ id: 'img-003', name: '头像3', url: 'http://example.com/images/avatar3.jpg', ownerName: '王五', ownerPhone: '13700137000', modelName: 'other-model' }
|
||||
]
|
||||
} else {
|
||||
console.error('Unexpected face detect response format:', response)
|
||||
this.$message.error('获取头像列表失败: 响应数据格式不正确')
|
||||
// 使用模拟数据
|
||||
this.imageOptions = [
|
||||
{ id: 'img-001', name: '头像1', url: 'http://example.com/images/avatar1.jpg', ownerName: '张三', ownerPhone: '13800138000' },
|
||||
{ id: 'img-002', name: '头像2', url: 'http://example.com/images/avatar2.jpg', ownerName: '李四', ownerPhone: '13900139000' },
|
||||
{ id: 'img-003', name: '头像3', url: 'http://example.com/images/avatar3.jpg', ownerName: '王五', ownerPhone: '13700137000' }
|
||||
{ id: 'img-001', name: '头像1', url: 'http://example.com/images/avatar1.jpg', ownerName: '张三', ownerPhone: '13800138000', modelName: 'emo-detect-v1' },
|
||||
{ id: 'img-002', name: '头像2', url: 'http://example.com/images/avatar2.jpg', ownerName: '李四', ownerPhone: '13900139000', modelName: 'liveportrait-detect' },
|
||||
{ id: 'img-003', name: '头像3', url: 'http://example.com/images/avatar3.jpg', ownerName: '王五', ownerPhone: '13700137000', modelName: 'other-model' }
|
||||
]
|
||||
}
|
||||
}).catch(error => {
|
||||
@@ -300,9 +326,9 @@ export default {
|
||||
this.$message.error(`网络请求失败: ${error.message || '请检查网络连接'}`)
|
||||
// 开发环境使用模拟数据
|
||||
this.imageOptions = [
|
||||
{ id: 'img-001', name: '头像1', url: 'http://example.com/images/avatar1.jpg', ownerName: '张三', ownerPhone: '13800138000' },
|
||||
{ id: 'img-002', name: '头像2', url: 'http://example.com/images/avatar2.jpg', ownerName: '李四', ownerPhone: '13900139000' },
|
||||
{ id: 'img-003', name: '头像3', url: 'http://example.com/images/avatar3.jpg', ownerName: '王五', ownerPhone: '13700137000' }
|
||||
{ id: 'img-001', name: '头像1', url: 'http://example.com/images/avatar1.jpg', ownerName: '张三', ownerPhone: '13800138000', modelName: 'emo-detect-v1' },
|
||||
{ id: 'img-002', name: '头像2', url: 'http://example.com/images/avatar2.jpg', ownerName: '李四', ownerPhone: '13900139000', modelName: 'liveportrait-detect' },
|
||||
{ id: 'img-003', name: '头像3', url: 'http://example.com/images/avatar3.jpg', ownerName: '王五', ownerPhone: '13700137000', modelName: 'other-model' }
|
||||
]
|
||||
})
|
||||
},
|
||||
@@ -374,6 +400,19 @@ export default {
|
||||
if (selectedImage.ownerPhone) {
|
||||
this.form.ownerPhone = selectedImage.ownerPhone
|
||||
}
|
||||
|
||||
// 获取头像的模型名信息
|
||||
this.selectedImageModel = selectedImage.modelName || ''
|
||||
|
||||
// 根据模型名自动设置模型供应商
|
||||
if (this.selectedImageModel === 'emo-detect-v1') {
|
||||
this.form.modelProvider = 'emo-v1'
|
||||
} else if (this.selectedImageModel === 'liveportrait-detect') {
|
||||
this.form.modelProvider = 'liveportrait'
|
||||
} else {
|
||||
// 默认设置
|
||||
this.form.modelProvider = 'dashscope'
|
||||
}
|
||||
}
|
||||
},
|
||||
|
||||
@@ -442,6 +481,8 @@ export default {
|
||||
pasteBack: true,
|
||||
headMoveStrength: 0.7
|
||||
}
|
||||
// 重置选中的头像模型
|
||||
this.selectedImageModel = ''
|
||||
},
|
||||
|
||||
// 返回
|
||||
|
||||
@@ -441,6 +441,7 @@ export default {
|
||||
const formData = new FormData()
|
||||
formData.append('file', file)
|
||||
formData.append('type', 'avatar')
|
||||
formData.append('model', this.uploadForm.model || 'liveportrait-detect')
|
||||
formData.append('avatarName', this.uploadForm.avatarName || '')
|
||||
formData.append('ownerName', this.uploadForm.ownerName || '')
|
||||
formData.append('ownerPhone', this.uploadForm.ownerPhone || '')
|
||||
@@ -448,6 +449,7 @@ export default {
|
||||
console.log('FormData内容:', {
|
||||
file: file.name,
|
||||
type: 'avatar',
|
||||
model: this.uploadForm.model,
|
||||
avatarName: this.uploadForm.avatarName,
|
||||
ownerName: this.uploadForm.ownerName,
|
||||
ownerPhone: this.uploadForm.ownerPhone
|
||||
@@ -465,6 +467,7 @@ export default {
|
||||
// 调用检测API
|
||||
const requestData = {
|
||||
imageUrl: imageUrl,
|
||||
model: this.uploadForm.model || 'liveportrait-detect',
|
||||
ownerName: this.uploadForm.ownerName || '',
|
||||
ownerPhone: this.uploadForm.ownerPhone || '',
|
||||
avatarName: this.uploadForm.avatarName || ''
|
||||
@@ -601,6 +604,7 @@ export default {
|
||||
// 调用检测API
|
||||
const requestData = {
|
||||
imageUrl: imageUrl,
|
||||
model: this.uploadForm.model || 'liveportrait-detect',
|
||||
ownerName: this.uploadForm.ownerName || '',
|
||||
ownerPhone: this.uploadForm.ownerPhone || '',
|
||||
avatarName: this.uploadForm.avatarName || ''
|
||||
@@ -625,6 +629,7 @@ export default {
|
||||
// 使用文件URL调用检测API
|
||||
const requestData = {
|
||||
imageUrl: fileUrl,
|
||||
model: this.uploadForm.model || 'liveportrait-detect',
|
||||
ownerName: this.uploadForm.ownerName || '',
|
||||
ownerPhone: this.uploadForm.ownerPhone || '',
|
||||
avatarName: this.uploadForm.avatarName || ''
|
||||
@@ -944,15 +949,18 @@ export default {
|
||||
this.detectLoading = true
|
||||
const requestData = {
|
||||
imageUrl: this.detectForm.imageUrl,
|
||||
model: this.detectForm.model || 'liveportrait-detect',
|
||||
ownerName: this.detectForm.ownerName,
|
||||
ownerPhone: this.detectForm.ownerPhone,
|
||||
avatarName: this.detectForm.avatarName
|
||||
}
|
||||
console.log('头像检测请求参数:', requestData)
|
||||
console.log('头像检测参数验证:', {
|
||||
hasModel: !!requestData.model,
|
||||
hasOwnerName: !!requestData.ownerName,
|
||||
hasOwnerPhone: !!requestData.ownerPhone,
|
||||
hasAvatarName: !!requestData.avatarName,
|
||||
modelValue: requestData.model,
|
||||
ownerNameValue: requestData.ownerName,
|
||||
ownerPhoneValue: requestData.ownerPhone,
|
||||
avatarNameValue: requestData.avatarName
|
||||
|
||||
@@ -97,9 +97,17 @@
|
||||
<el-table-column label="处理时间(ms)" prop="processingTimeMs" width="120" align="center" />
|
||||
<el-table-column label="模型提供方" prop="modelProvider" width="120" />
|
||||
<el-table-column label="创建时间" prop="createdAt" width="160" />
|
||||
<el-table-column label="操作" width="200" fixed="right">
|
||||
<el-table-column label="操作" width="250" fixed="right">
|
||||
<template slot-scope="scope">
|
||||
<el-button type="text" @click="handleView(scope.row)">查看</el-button>
|
||||
<el-button
|
||||
v-if="scope.row.success"
|
||||
type="text"
|
||||
icon="el-icon-video-play"
|
||||
@click="handlePlay(scope.row)"
|
||||
>
|
||||
播放
|
||||
</el-button>
|
||||
<el-button type="text" @click="handleDelete(scope.row)">删除</el-button>
|
||||
</template>
|
||||
</el-table-column>
|
||||
@@ -243,6 +251,40 @@
|
||||
<el-button @click="detailVisible = false">关闭</el-button>
|
||||
</div>
|
||||
</el-dialog>
|
||||
|
||||
<!-- 视频播放对话框 -->
|
||||
<el-dialog
|
||||
title="视频播放"
|
||||
:visible.sync="playVisible"
|
||||
width="800px"
|
||||
@close="handlePlayClose"
|
||||
>
|
||||
<div v-if="currentRecord" class="play-content">
|
||||
<div class="video-info">
|
||||
<p><strong>视频名称:</strong> {{ currentRecord.videoName }}</p>
|
||||
<p><strong>视频时长:</strong> {{ currentRecord.videoDuration }}秒</p>
|
||||
<p><strong>视频比例:</strong> {{ currentRecord.videoRatio }}</p>
|
||||
</div>
|
||||
<div v-loading="playLoading" class="video-player">
|
||||
<video
|
||||
v-if="currentVideoUrl && !playLoading"
|
||||
:src="currentVideoUrl"
|
||||
controls
|
||||
style="width: 100%; max-height: 400px;"
|
||||
preload="metadata"
|
||||
>
|
||||
您的浏览器不支持视频播放
|
||||
</video>
|
||||
<div v-else-if="playLoading" class="loading-placeholder">
|
||||
<i class="el-icon-loading" />
|
||||
<p>正在加载视频...</p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div slot="footer" class="dialog-footer">
|
||||
<el-button @click="playVisible = false">关闭</el-button>
|
||||
</div>
|
||||
</el-dialog>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
@@ -259,6 +301,9 @@ export default {
|
||||
selectedIds: [],
|
||||
detailVisible: false,
|
||||
currentRecord: null,
|
||||
playVisible: false,
|
||||
currentVideoUrl: '',
|
||||
playLoading: false,
|
||||
// 查询参数
|
||||
queryParams: {
|
||||
pageNum: 1,
|
||||
@@ -409,6 +454,32 @@ export default {
|
||||
// 头像合成视频
|
||||
handleAvatarSynthesis() {
|
||||
this.$router.push('/video/avatar-synthesis')
|
||||
},
|
||||
|
||||
// 播放视频
|
||||
handlePlay(row) {
|
||||
// 直接使用videoTempUrl,无需调用后端接口
|
||||
const videoUrl = row.videoTempUrl || row.videoUrl
|
||||
|
||||
if (!videoUrl) {
|
||||
this.$message.warning('视频链接不存在,无法播放')
|
||||
return
|
||||
}
|
||||
|
||||
this.playLoading = true
|
||||
this.currentRecord = row
|
||||
this.currentVideoUrl = videoUrl
|
||||
this.playVisible = true
|
||||
this.playLoading = false
|
||||
this.$message.success('视频加载成功')
|
||||
},
|
||||
|
||||
// 关闭播放对话框
|
||||
handlePlayClose() {
|
||||
this.playVisible = false
|
||||
this.currentVideoUrl = ''
|
||||
this.currentRecord = null
|
||||
this.playLoading = false
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -449,4 +520,43 @@ export default {
|
||||
color: #303133;
|
||||
flex: 1;
|
||||
}
|
||||
|
||||
.play-content {
|
||||
padding: 20px 0;
|
||||
}
|
||||
|
||||
.video-info {
|
||||
margin-bottom: 20px;
|
||||
padding: 15px;
|
||||
background-color: #f5f7fa;
|
||||
border-radius: 4px;
|
||||
}
|
||||
|
||||
.video-info p {
|
||||
margin: 8px 0;
|
||||
font-size: 14px;
|
||||
color: #606266;
|
||||
}
|
||||
|
||||
.video-player {
|
||||
text-align: center;
|
||||
min-height: 200px;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
}
|
||||
|
||||
.loading-placeholder {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
color: #909399;
|
||||
font-size: 14px;
|
||||
}
|
||||
|
||||
.loading-placeholder i {
|
||||
font-size: 24px;
|
||||
margin-bottom: 10px;
|
||||
}
|
||||
</style>
|
||||
|
||||
Reference in New Issue
Block a user