vue + node如何通過一個(gè)Txt文件批量生成MP3并壓縮成Zip
看看效果叭
解壓的文件
上傳的文件格式
測(cè)試1|||測(cè)試1的文字
測(cè)試2|||測(cè)試2的文字
測(cè)試3|||測(cè)試3的文字
測(cè)試4|||測(cè)試4的文字
測(cè)試5|||測(cè)試5的文字
實(shí)現(xiàn)的邏輯如下
- 上傳文件
- 解析txt
- 發(fā)送內(nèi)容至百度語(yǔ)音合成
- 生成文件夾放置本次合成的mp3文件,并壓縮成zip
- 發(fā)送zip的地址給前端
使用了 element-ui 的 el-upload 組件
<el-upload v-loading="loading" class="upload-demo" drag ref="upload" action="#" accept=".txt" :before-upload="onBeforeUploadImage" :http-request="UploadImage" :on-change="fileChange" :file-list="fileList" > <i class="el-icon-upload"></i> <div class="el-upload__text"> 將文件拖到此處,或 <em>點(diǎn)擊上傳</em> </div> <div class="el-upload__tip" slot="tip">只能上傳txt文件,且不超過1M</div> </el-upload>
在上傳之前判斷上傳的文件是否符合要求
onBeforeUploadImage(file) { const isTxt = file.type === "text/plain"; const isLt1M = file.size / 1024 / 1024 < 1; if (!isTxt) { this.$message.error("上傳文件只能是txt格式!"); } if (!isLt1M) { this.$message.error("上傳文件大小不能超過 1MB!"); } return isTxt && isLt1M; }
一次只上傳一個(gè)文件,在文件列表更新時(shí)先清除之前的文件
fileChange(file) { let obj = this.onBeforeUploadImage(file.raw); if (obj) { this.$refs.upload.clearFiles(); this.fileList = [{ name: file.name, url: file.url }]; } }
上傳的主要函數(shù)
UploadImage(param) { this.loading = true; const formData = new FormData(); formData.append("file", param.file); this.$axios({ url: process.env.VUE_APP_BASE_API + "api/txtToMp3", method: "post", data: formData }) .then(response => { if (response.data.code == 0) { this.loading = false; this.dialogVisible = true; this.url = response.data.data.url; } }) .catch(error => { console.log(error); }); }
node代碼
用到的依賴項(xiàng)
const formidable = require("formidable"); //獲取上傳的txt,并保存 const path = require("path"); const AipSpeech = require("baidu-aip-sdk").speech; //百度語(yǔ)音合成sdk const fs = require("fs"); const compressing = require("compressing"); //壓縮文件夾用
接口代碼
router.post("/txtToMp3", async function (req, res, next) { let form = new formidable.IncomingForm(); form.encoding = "utf-8"; //編碼 form.uploadDir = path.join(__dirname + "/../txt"); //保存上傳文件地址 form.keepExtensions = true; //保留后綴 form.parse(req, function (err, fields, files) { let filename; filename = files.file.name; let nameArray = filename.split("."); //分割 let type = nameArray[nameArray.length - 1]; let name = ""; for (let i = 0; i < nameArray.length - 1; i++) { name = name + nameArray[i]; } let date = new Date(); let time = "_" + date.getTime(); let avatarName = name + time + "." + type; let newPath = form.uploadDir + "/" + avatarName; fs.renameSync(files.file.path, newPath); //移動(dòng)文件 fs.readFile(newPath, "utf-8", function (err, data) { if (err) { console.log(err); new Result(null, "讀取失敗").fail(res); } else { let client = new AipSpeech( 0, "百度語(yǔ)音合成key", "百度語(yǔ)音合成secret" ); let resultData = data.split("\n"); let number = resultData.length; let formTime = new Date().getTime(); let mp3FileDir = path.join(__dirname + "/../mp3_" + formTime); fs.mkdirSync(mp3FileDir); for (let i in resultData) { setTimeout(function(){ if (resultData[i].indexOf("|||") != -1) { let text = resultData[i].split("|||")[1]; // 語(yǔ)音合成,保存到本地文件 client.text2audio(text, { spd: 4, per: 4 }).then( function (result) { if (result.data) { let time = resultData[i].split("|||")[0] + "_voice"; let avatarName_mp3 = mp3FileDir + "/" + time + ".mp3"; fs.writeFileSync(avatarName_mp3, result.data); number--; if (number == 0) { let zipFileName = "zip/mp3_" + formTime + ".zip"; compressing.zip .compressDir(mp3FileDir, zipFileName) .then(() => { let item = { url: zipFileName, }; new Result(item, "壓縮成功").success(res); }) .catch((err) => { new Result(null, "壓縮失敗").fail(res); }); } } else { // 合成服務(wù)發(fā)生錯(cuò)誤 new Result(null, "合成失敗").fail(res); } }, function (err) { console.log(err); } ); } else { new Result(null, "文件格式錯(cuò)誤").fail(res); } },i * 20) } } }); }); });
PS:
在node部分,在判斷需要合成的文件是否全部完成時(shí),我是通過number的值等于0判斷完成,不知道大佬們有啥好方法不?
到此這篇關(guān)于vue + node如何通過一個(gè)Txt文件批量生成MP3并壓縮成Zip的文章就介紹到這了,更多相關(guān)vue node批量生成MP3內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
vue 實(shí)現(xiàn) ios 原生picker 效果及實(shí)現(xiàn)思路解析
這篇文章主要介紹了vue 實(shí)現(xiàn) ios 原生picker 效果及實(shí)現(xiàn)思路解析,本文給大家介紹的非常詳細(xì),具有參考借鑒價(jià)值,需要的朋友可以參考下2017-12-12Vue 項(xiàng)目遷移 React 路由部分經(jīng)驗(yàn)分享
這篇文章主要為大家介紹了Vue 項(xiàng)目遷移 React 路由部分經(jīng)驗(yàn)分享,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪2022-09-09vue表單綁定實(shí)現(xiàn)多選框和下拉列表的實(shí)例
本篇文章主要介紹了vue表單綁定實(shí)現(xiàn)多選框和下拉列表的實(shí)例,小編覺得挺不錯(cuò)的,現(xiàn)在分享給大家,也給大家做個(gè)參考。一起跟隨小編過來看看吧2017-08-08vue關(guān)于點(diǎn)擊詳情頁(yè)面keep-alive的緩存問題
這篇文章主要介紹了vue關(guān)于點(diǎn)擊詳情頁(yè)面keep-alive的緩存問題,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教2022-06-06如何啟動(dòng)一個(gè)Vue.js項(xiàng)目
這篇文章主要介紹了如何啟動(dòng)一個(gè)Vue.js項(xiàng)目,對(duì)Vue.js感興趣的同學(xué),可以參考下2021-04-04vue自動(dòng)化路由的實(shí)現(xiàn)代碼
這篇文章主要介紹了vue自動(dòng)化路由的實(shí)現(xiàn)代碼,文中通過示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧2019-09-09