@@ -96,6 +96,11 @@ const routes = [ | |||||
name: 'chatgpt', | name: 'chatgpt', | ||||
component: () => import("@/views/chatgpt/chatgpt"), | component: () => import("@/views/chatgpt/chatgpt"), | ||||
}, | }, | ||||
{ | |||||
path: '/chatgpt-getmp3', | |||||
name: 'chatgpt-getmp3', | |||||
component: () => import("@/views/chatgpt/chatgpt-getmp3"), | |||||
}, | |||||
, | , | ||||
// 音频new | // 音频new | ||||
{ | { | ||||
@@ -0,0 +1,59 @@ | |||||
<template> | |||||
<div> | |||||
<input type="file" ref="fileInput" @change="handleFileSelect" accept="video/*" /> | |||||
<video ref="videoPlayer" controls style="width: 200px; height: 200px"></video> | |||||
<button @click="extractAudio">提取音频</button> | |||||
<button @click="downloadAudio">下载音频</button> | |||||
</div> | |||||
</template> | |||||
<script> | |||||
import fluentffmpeg from 'fluent-ffmpeg'; | |||||
export default { | |||||
data() { | |||||
return { | |||||
videoFile: null, | |||||
audioBlob: null | |||||
}; | |||||
}, | |||||
methods: { | |||||
handleFileSelect(event) { | |||||
this.videoFile = event.target.files[0]; | |||||
this.previewVideo(); | |||||
}, | |||||
previewVideo() { | |||||
const videoPlayer = this.$refs.videoPlayer; | |||||
videoPlayer.src = URL.createObjectURL(this.videoFile); | |||||
}, | |||||
extractAudio() { | |||||
const fileInput = this.$refs.fileInput; | |||||
const videoFile = fileInput.files[0]; | |||||
const reader = new FileReader(); | |||||
reader.onload = e => { | |||||
const arrayBuffer = e.target.result; | |||||
// 使用 fluent-ffmpeg 提取视频音频 | |||||
fluentffmpeg(arrayBuffer) | |||||
.noVideo() | |||||
.format('mp3') | |||||
.on('end', () => { | |||||
const audioArrayBuffer = fs.readFileSync('output.mp3'); | |||||
this.audioBlob = new Blob([audioArrayBuffer], { type: 'audio/mp3' }); | |||||
}) | |||||
.saveToFile('output.mp3'); | |||||
}; | |||||
reader.readAsArrayBuffer(videoFile); | |||||
}, | |||||
downloadAudio() { | |||||
if (this.audioBlob) { | |||||
const downloadLink = document.createElement('a'); | |||||
downloadLink.href = URL.createObjectURL(this.audioBlob); | |||||
downloadLink.download = 'audio.mp3'; | |||||
downloadLink.click(); | |||||
} | |||||
} | |||||
} | |||||
}; | |||||
</script> |
@@ -0,0 +1,55 @@ | |||||
<!-- <template> | |||||
<div> | |||||
<input type="file" ref="videoInput" @change="handleVideoUpload" accept="video/*" /> | |||||
<div v-if="videoUrl"> | |||||
<video :src="videoUrl" controls style="width: 200px; height: 200px"></video> | |||||
</div> | |||||
<button @click="extractAudio" :disabled="!videoUrl">提取音频</button> | |||||
<button @click="downloadAudio" :disabled="!audioUrl">下载音频</button> | |||||
</div> | |||||
</template> | |||||
<script> | |||||
import { createFFmpeg, fetchFile } from '@ffmpeg/ffmpeg'; | |||||
export default { | |||||
data() { | |||||
return { | |||||
ffmpeg: null, | |||||
videoUrl: '', | |||||
audioUrl: '' | |||||
}; | |||||
}, | |||||
mounted() { | |||||
this.ffmpeg = createFFmpeg({ | |||||
log: true | |||||
}); | |||||
this.ffmpeg.load(); | |||||
}, | |||||
methods: { | |||||
handleVideoUpload(event) { | |||||
const file = event.target.files[0]; | |||||
this.videoUrl = URL.createObjectURL(file); | |||||
}, | |||||
async extractAudio() { | |||||
const file = this.$refs.videoInput.files[0]; | |||||
const inputPath = '/input' + file.name; | |||||
const outputPath = '/output.mp3'; | |||||
await this.ffmpeg.write(inputPath, await fetchFile(file)); | |||||
await this.ffmpeg.run('-i', inputPath, '-vn', '-acodec', 'libmp3lame', outputPath); | |||||
const data = await this.ffmpeg.read(outputPath); | |||||
const audioBlob = new Blob([data.buffer], { type: 'audio/mp3' }); | |||||
this.audioUrl = URL.createObjectURL(audioBlob); | |||||
}, | |||||
downloadAudio() { | |||||
const link = document.createElement('a'); | |||||
link.href = this.audioUrl; | |||||
link.download = 'audio.mp3'; | |||||
link.click(); | |||||
} | |||||
} | |||||
}; | |||||
</script> --> |
@@ -6,13 +6,15 @@ | |||||
<img style="width: 60%; margin-top: 20px" src="../../assets/img/logoh.png" alt="" /> | <img style="width: 60%; margin-top: 20px" src="../../assets/img/logoh.png" alt="" /> | ||||
</div> | </div> | ||||
<div style="padding: 0 20px"> | <div style="padding: 0 20px"> | ||||
<h1 style="margin-top: 30px">提交视频生成成功</h1> | |||||
<h1 style="margin-top: 30px">请耐心等待</h1> | |||||
<h1 style="margin-top: 20px"> | |||||
{{ countdown }}秒后将自动跳转至 | |||||
<i @click="$router.push({ path: '/myPage' })">首页</i> | |||||
</h1> | |||||
<h4 style="display: flex; justify-content: end; margin-top: 20px"> | |||||
<div style="margin-top: 10px; padding: 10px 10px 20px; border: 1px dashed #ccc; border-radius: 15px"> | |||||
<h1 style="margin-top: 10px">提交视频生成成功</h1> | |||||
<h2 style="margin-top: 30px">请耐心等待</h2> | |||||
<h2 style="margin-top: 20px"> | |||||
{{ countdown }}秒后将自动跳转至 | |||||
<i @click="$router.push({ path: '/myPage' })">首页</i> | |||||
</h2> | |||||
</div> | |||||
<h4 style="margin-top: 20px; text-align: center"> | |||||
您也可以点击 | 您也可以点击 | ||||
<i @click="$router.push('/myPage')" class="wordColor"> 返回 </i> | <i @click="$router.push('/myPage')" class="wordColor"> 返回 </i> | ||||
至 首页 | 至 首页 | ||||
@@ -82,6 +84,11 @@ export default { | |||||
</script> | </script> | ||||
<style lang="scss" scoped> | <style lang="scss" scoped> | ||||
h1, | |||||
h2 { | |||||
text-align: center; | |||||
color: #ccc; | |||||
} | |||||
.page { | .page { | ||||
transform: translateX(30%); | transform: translateX(30%); | ||||
opacity: 0; | opacity: 0; | ||||
@@ -3,10 +3,15 @@ | |||||
<div id="top"></div> | <div id="top"></div> | ||||
<HeadTop /> | <HeadTop /> | ||||
<div style="padding: 0 20px"> | <div style="padding: 0 20px"> | ||||
<h1 style="margin-top: 30px">视频生成失败</h1> | |||||
<h1 style="margin-top: 30px; margin-bottom: 10px">失败原因是:</h1> | |||||
<div style="text-indent: 2em; font-size: 14px">{{ message }}</div> | |||||
<h1 style="margin-top: 20px"> | |||||
<div style="display: flex; justify-content: space-around"> | |||||
<img style="width: 60%; margin-top: 20px" src="../../assets/img/logoh.png" alt="" /> | |||||
</div> | |||||
<div style="margin-top: 10px; padding: 10px 10px 20px; border: 1px dashed #ccc; border-radius: 15px"> | |||||
<h1 style="margin-top: 10px">视频生成失败</h1> | |||||
<h2 style="margin-top: 10px; margin-bottom: 10px">失败原因是:</h2> | |||||
<div style="font-size: 14px; text-align: center; color: #ccc">{{ message }}</div> | |||||
</div> | |||||
<h2 style="margin-top: 20px"> | |||||
<i | <i | ||||
@click=" | @click=" | ||||
$router.push({ | $router.push({ | ||||
@@ -20,8 +25,8 @@ | |||||
class="wordColor"> | class="wordColor"> | ||||
重新编辑 | 重新编辑 | ||||
</i> | </i> | ||||
</h1> | |||||
<h4 style="display: flex; justify-content: end; margin-top: 20px"> | |||||
</h2> | |||||
<h4 style="margin-top: 20px; text-align: center"> | |||||
您也可以点击 | 您也可以点击 | ||||
<i @click="$router.push(`myPage`)" class="wordColor"> 返回 </i> | <i @click="$router.push(`myPage`)" class="wordColor"> 返回 </i> | ||||
至 首页 | 至 首页 | ||||
@@ -75,6 +80,15 @@ export default { | |||||
</script> | </script> | ||||
<style lang="scss" scoped> | <style lang="scss" scoped> | ||||
h1, | |||||
h2 { | |||||
text-align: center; | |||||
color: #ccc; | |||||
i { | |||||
width: 100%; | |||||
text-align: center; | |||||
} | |||||
} | |||||
.page { | .page { | ||||
transform: translateX(30%); | transform: translateX(30%); | ||||
opacity: 0; | opacity: 0; | ||||