| @@ -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; | ||||