vue+flask实现视频合成功能(拖拽上传)
目录
- 拖拽上传我们之前一个文章有写过
- 上传文件
- flask处理文件
- 拼接获取文件路径
- 首先我们看flask
- 前端获取
- 配置代理说明
- 额外说明(如果你使用uni-app)
- 完整代码
- flask代码
- md5random.py 用于随机字符串生成
- app_service.py 服务代码
- vue代码
vue+flask实现视频合成
效果如下
拖拽上传我们之前一个文章有写过
//www.js-code.com/article/206543.htm
原理就是 监听drop事件 来获取拖拽的文件列表
上传文件
通过axios 上传文件
this,.fileList就是我们的文件列表
let files = this.fileList; let formd = new FormData(); let i = 1; //添加上传列表files.foreach(ITem => { formd.apPEnd(i + "", item, item.name) i++; } )formd.append("type", i)let config = { headers: { "Content-type": "multipart/form-data" } } //上传文件请求axios.post("/qwe", formd, config).then(res => { console.LOG(res.data)} )
flask处理文件
完整代码见最底部
逻辑如下
接收文件
为每次合成请求随机生成一个文件夹 临时保存文件
拼接视频
返回文件路径
@app.route("/file",methods=['POST'])def test(): #获取文件 files = request.files #合成队列 videoL = [] #随机字符串 dirs = sjs() #生成文件夹 os.mkdir(dirs) #保存文件并添加至合成队列 for file in files.values(): PRint(file) dst = dirs + "/" + file.name + ".mp4" file.save(dst) video = VideoFileClip(dirs + "/" + file.name + ".mp4") videoL.append(video) #拼接视频 final = concatenate_videoclips(videoL) #文件路径 fileName = dirs + "/" +"{ } .mp4".format(sjs()) #生成视频 final.to_videofile(fileName) #销毁文件夹 def sc(): shutil.rmtree(dirs) #30秒后销毁文件夹 timer = threading.Timer(30, sc) timer.start() # 返回文件路径 return fileName
拼接获取文件路径
首先我们看flask
逻辑如下
通过文件名 获取文件 返回文件
app.route("/getvoi",methods=['GET'])def getimg(): #获取文件名 ss = request.args['name'] #文件加至返回响应 response = make_response( send_file(ss)) #删除文件 def sc(): os.remove(ss) #30秒后删除文件 timer = threading.Timer(30, sc) timer.start() return response
前端获取
通过a标签下载
a s :href="herfs" rel="external nofollow" rel="external nofollow" :download="fileName"> 下载/a>
herfs如下
我们上传文件后 通过falsk处理返回文件路径 拼接后获取文件地址
a标签添加download属性可以给下载的文件命名
如果你对/qwe /voi有疑惑 请看下面的配置代理说明
配置代理说明
配置代理是为了解决跨域问题 开发环境可在vue.config.js配置即可使用
生产环境需要额外配置nginx
/qwe实际上就是 http://127.0.0.1:8087/file
/voi实际上就是 http://127.0.0.1:8087/getvoi
对应我们flask中的
额外说明(如果你使用uni-app)
如果你使用uni-app 可参照文档使用api
上传文件api https://uniapp.dcloud.io/api/request/network-file?id=uploaDFile
下载文件api https://uniapp.dcloud.io/api/request/network-file?id=downloadfile
或者直接使用别人封装好的 插件毕竟比较方便
完整代码
如果你不想一个一个复制可以去下载
下载途径1: https://download.csdn.net/download/QQ_42027681/15561897
下载途径2:https://github.COM/dmhsq/vue-flask-videoSynthesis
flask代码
md5random.py 用于随机字符串生成
import randomimport hashlibdef sjs(): a = random.randint(0, 100) a = "a" + str(a); b = random.randint(100, 10000); b = "b" + str(b); c = hashlib.md5(a.encode(encoding='UTF-8')).hexdigest() + hashlib.md5(b.encode(encoding='UTF-8')).hexdigest(); c = "c" + str(c); d = random.randint(10, 100); d = "d" + str(d); e = hashlib.md5(c.encode(encoding='UTF-8')).hexdigest() + hashlib.md5(d.encode(encoding='UTF-8')).hexdigest(); e = hashlib.md5(e.encode(encoding='UTF-8')).hexdigest() return e;
app_service.py 服务代码
From flask import Flask,request,send_file,make_responseimport os,json,threading,shutilfrom moviepy.editor import *from md5random import sjsapp = Flask(__name__)@app.route("/file",methods=['POST'])def test(): #获取文件 files = request.files #合成队列 videoL = [] #随机字符串 dirs = sjs() #生成文件夹 os.mkdir(dirs) #保存文件并添加至合成队列 for file in files.values(): print(file) dst = dirs + "/" + file.name + ".mp4" file.save(dst) video = VideoFileClip(dirs + "/" + file.name + ".mp4") videoL.append(video) #拼接视频 final = concatenate_videoclips(videoL) #文件路径 fileName = dirs + "/" +"{ } .mp4".format(sjs()) #生成视频 final.to_videofile(fileName) #销毁文件夹 def sc(): shutil.rmtree(dirs) #30秒后销毁文件夹 timer = threading.Timer(30, sc) timer.start() # 返回文件路径 return fileName@app.route("/getvoi",methods=['GET'])def getImg(): #获取文件名 ss = request.args['name'] #文件加至返回响应 response = make_response( send_file(ss)) #删除文件 def sc(): os.remove(ss) #30秒后删除文件 timer = threading.Timer(30, sc) timer.start() return responseif __name__ == '__main__': app.run(host='0.0.0.0',port=8087)
vue代码
演示文件代码
template> div> div v-on:Dragover="tts" v-on:drop="ttrs" style="width: 800px; height: 200px; border: 1px solid black; font-Size: 40px; line-height: 200px" > { { dt } } /div> div v-for="(item, index) in fileList" :key="index" style="width: 800px; height: 200px; border: 1px solid black; font-size: 40px; position: relative; top:10px" > p style="font-size: 20px; float: left; position: relative; left: 20pxword-wrap:break-word; word-break:normal; " > { { item.name } } /p> h5 style="float:right; position: absolute; top: 80px; right: 20px"> { { item.type } } /h5> h6 style="position: absolute; top: 80px; float: left; left: 20px"> { { item.size | sizeType } } /h6> button style="float: right" @click="del(index)"> 删除/button> /div> !-- 此处为展示最后一个上传的文件 --> !-- div style="position:relative; top: 100px"> --> !-- img v-if="isImage" :src="srcs" style="width: 800px" /> --> !-- video v-if="isVideo" controls :src="srcs" style="width: 800px"> /video> --> !-- audio v-if="isAudio" controls :src="srcs" style="width: 800px"> /audio> --> !-- /div> --> el-button style="position: relative; top: 50px" type="success" @click="ups()" :disabled="!isCan"> 合成/el-button> el-button style="position: relative; top: 50px" v-loading="loading" type="success" > 。。。/el-button> a style="position: relative; top: 50px; left: 15px; " type="success" :href="herfs" rel="external nofollow" rel="external nofollow" :download="fileName"> el-button :disabled="isCans"> span style="color: black"> 下载/span> /el-button> /a> div style="position: relative; top: 100px"> 文件下载有效时间{ { times} } s/div> /div> /template> script> import axios from "axios"; export default { name: "trs", data() { return { dt: "",//上传提醒 "拖动到此处上传文件“或者"上传完成,可继续上传" fileList: [],//文件列表 loading:false, srcs: "",//图片/视频/音频 base64 isImage: false,//是否是图片 isAudio: false,//是否是音频 isVideo: false,//是否是视频 isCan: true,//是否能合成 isCans:true,//是否能下载 herfs: "",//下载地址 fileName: "",//文件名 times: 25//下载有效时间 } ; } , filters: { //格式化文件大小 sizeType(val) { let kbs = val / 1024; let mbs = 0; let gbs = 0; if (kbs > = 1024) { mbs = kbs / 1024; } if (mbs > = 1024) { gbs = mbs / 1024; return gbs.toFixed(2) + "GB"; } else if (mbs > = 1) { return mbs.toFixed(2) + "MB"; } else { return kbs.toFixed(2) + "KB"; } } } , mounted() { let vm = this; window.addEventListener("dragdrop", this.testfunc, false); //全局监听 当页面内有文件拖动 提醒拖动到此处 document.addEventListener("dragover", function() { console.log(111); vm.dt = "拖动到此处上传文件"; console.log(vm.dt); } ); } , methods: { //展示文件 主要为三个类型 图片/视频/音频 readFile(file) { let vm = this; let reader = new FileReader(); reader.readAsDataURL(file); reader.onload = function() { let type = file.type.substr(0, 5); if (type == "image") { vm.isImage = true; vm.isAudio = false; vm.isVideo = false; } else if (type == "audio") { vm.isImage = false; vm.isAudio = true; vm.isVideo = false; } else if (type == "video") { vm.isImage = false; vm.isAudio = false; vm.isVideo = true; } else { alert("不是图片/视频/音频"); } vm.srcs = reader.result; // this.$nextTick(()=> { // // } ) } ; } , //全局监听drop的触发事件 取消drop弹窗显示资源 testfunc(event) { alert("dragdrop!"); //取消drop弹窗显示资源 event.stopPropagation(); event.preventDefault(); } , del(index) { this.fileList.splice(index, 1); if (this.fileList.length === 0) { this.dt = ""; } } , //监听div上传框 当有文件拖动时 显示"拖动到此处上传文件" tts(e) { console.log(e); this.dt = "拖动到此处上传文件"; } , //监听div上传框 drop事件触发 ttrs(e) { console.log(e); console.log(e.datatransfer.files); //获取文件 let datas = e.dataTransfer.files; //取消drop弹窗显示资源 e.stopPropagation(); e.preventDefault(); datas.forEach(item => { if(item.type=="video/mp4"){ this.fileList.push(item); } } ); //读取文件 如果不想展示图片/视频/音频可忽略 this.readFile(this.fileList[this.fileList.length - 1]); this.dt = "上传完成,可继续上传"; } , //上传文件到服务器 ups(){ if(this.fileList.length==0){ this.$message('文件列表为空'); return ; } this.loading = true; this.isCan = false; this.isCans = true; let files = this.fileList; let formd = new FormData(); let i = 1; //添加上传列表 files.forEach(item=> { formd.append(i+"",item,item.name) i++; } ) formd.append("type",i) let config={ headers:{ "Content-Type":"multipart/form-data"} } //上传文件请求 axios.post("/qwe",formd,config).then(res=> { console.log(res.data) this.loading = false //合成下载路径 this.herfs = "/voi?name="+res.data this.fileName = res.data.split('/')[1] //禁止合成 this.isCan = false this.isCans = false //设置下载有效时间 时间到后无法下载但可以继续合成 let timer = setInterval(()=> { this.times--; } ,1000) this.setCans(timer) } ) } , setCans(timer){ setTimeout(()=> { this.isCans = true this.isCan = true this.fileName ="" clearInterval(timer) this.times = 25 } ,25000) } } } ; /script> style scoped> /style>
vue.config.js
module.exports = { devServer: { // assetsSubDirectory: 'static', // assetsPublicPath: '/', Proxy: { "/qwe": { target: "http://127.0.0.1:8087/file", changeOrigin: true, pathRewrite: { "^/qwe": "" } } , "/voi": { target: "http://127.0.0.1:8087/getvoi", changeOrigin: true, pathRewrite: { "^/voi": "" } } } } } ;
到此这篇关于vue+flask实现视频合成功能(拖拽上传)的文章就介绍到这了,更多相关vue视频合成内容请搜索以前的文章或继续浏览下面的相关文章希望大家以后多多支持!
您可能感兴趣的文章:- vue实现拖拽或点击上传图片
- 基于Vue2实现移动端图片上传、压缩、拖拽排序、拖拽删除功能
- 基于Vue3的全屏拖拽上传组件
声明:本文内容由网友自发贡献,本站不承担相应法律责任。对本内容有异议或投诉,请联系2913721942#qq.com核实处理,我们将尽快回复您,谢谢合作!
若转载请注明出处: vue+flask实现视频合成功能(拖拽上传)
本文地址: https://pptw.com/jishu/594729.html