vue+flask实现视频合成
效果如下

欢迎访问博客代码哈士奇
技术 聊天 交流群 974178910
前端交流群 535620886

vue+flask实现视频合成

  • 拖拽上传我们之前一个文章有写过
  • 上传文件
  • flask处理文件
  • 拼接获取文件路径
    • 首先我们看flask
    • 前端获取
      • 配置代理说明
  • 额外说明(如果你使用uni-app)
  • 完整代码
    • flask代码
      • md5random.py 用于随机字符串生成
      • app_service.py 服务代码
    • vue代码
      • 演示文件代码
      • vue.config.js

拖拽上传我们之前一个文章有写过

https://dmhsq.blog.csdn.net/article/details/114109519

原理就是 监听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" :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 random
import hashlib
def 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_response
import os,json,threading,shutil
from 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><divv-on:dragover="tts"v-on:drop="ttrs"style="width: 800px;height: 200px;border: 1px solid black;font-size: 40px;line-height: 200px">{{ dt }}</div><divv-for="(item, index) in fileList":key="index"style="width: 800px;height: 200px;border: 1px solid black;font-size: 40px;position: relative;top:10px"><pstyle="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" :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: "",//图片/视频/音频 base64isImage: 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.datathis.fileName = res.data.split('/')[1]//禁止合成this.isCan = falsethis.isCans = false//设置下载有效时间 时间到后无法下载但可以继续合成let timer = setInterval(()=>{this.times--;},1000)this.setCans(timer)})},setCans(timer){setTimeout(()=>{this.isCans = truethis.isCan = truethis.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实现视频合成(拖拽上传)相关推荐

  1. vue对文件夹进行拖拽上传完整流程(文件夹中超出100个文件)

    前言 上个文章介绍了多图片压缩,多图片可以通过直接多选图片进行拖拽,也可以通过直接拖拽文件夹进行解析得到多图片,接下来直接上代码 先展示文件拖拽后对文件的解析效果 图片文件夹 图片文件夹解析 大文件夹 ...

  2. vue+element-ui实现富文本(含有图片粘贴拖拽上传)

    vue+element-ui实现富文本(含有图片粘贴拖拽上传) Just For Share | 仅仅分享 首先需要安装 cnpm i vue-quill-editor -D 富文本编辑器 cnpm ...

  3. dropzonejs中文翻译手册 DropzoneJS是一个提供文件拖拽上传并且提供图片预览的开源类库....

    http://wxb.github.io/dropzonejs.com.zh-CN/dropzonezh-CN/ 由于项目需要,完成一个web的图片拖拽上传,也就顺便学习和了解了一下前端的比较新的技术 ...

  4. vue-simple-uploader实现多文件/文件夹以及可拖拽上传

    vue-simple-uploader的简单使用 1.效果图展示 2.安装 3.vue2使用(vue3使用会报错) 4.代码 vue-simple-uploader是基于simple-uploader ...

  5. 如何实现拖拽上传、上传进度条,以及取消上传?

    文件上传是最常见的一种业务需求,上传功能可简单,可复杂,简单就是把文件传上去就行,复杂就是涉及大文件断点续传.控制并发等,不知道大家对上传都了解多少.今天要给大家分享的是上传需求中最为常见的一些场景, ...

  6. vant组件实现上传图片裁剪_如何用 120 行代码,实现交互完整的拖拽上传组件?...

    作者 | 前端劝退师 责编 | 伍杏玲 你将在该篇学到: 如何将现有组件改写为 React Hooks函数组件 useState.useEffect.useRef是如何替代原生命周期和Ref的. 一个 ...

  7. html5 上传超大文件,HTML5教程 如何拖拽上传大文件

    本篇教程探讨了HTML5教程 如何拖拽上传大文件,希望阅读本篇文章以后大家有所收获,帮助大家HTML5+CSS3从入门到精通 . < 前言: 大文件传输一直是技术上的一大难点.文件过大时,一些性 ...

  8. Dropzone.js实现文件拖拽上传

    dropzone.js是一个开源的JavaScript库,提供 AJAX 异步文件上传功能,支持拖拽文件.支持最大文件大小.支持设置文件类型.支持预览上传结果,不依赖jQuery库. 使用Dropzo ...

  9. 截图后粘贴或拖拽上传

    在浏览器中使用截图工具截图后直接粘贴到页面上传,以及拖拽到页面标签区域上传 主要使用了粘贴(paste)事件,以及拖拽(drag)事件,其中拖拽时要禁用浏览器的默认将图片打开的行为 例子: HTML部 ...

最新文章

  1. Ble Connection Events(转载)
  2. 数学之史:微积分的发明——变量数学的巨人之争
  3. python计算两字符串中的位置_python – 计算两个字符串之间距离的算法
  4. APP论坛社区软件源码 APP封装
  5. android app应用签名生成工具,android应用签名详细步骤
  6. 将windows c盘安装在linux,将WindowsC盘hda1安装在Linux文件系统的/winsys目录下,命令是()。...
  7. 深度强化学习之近端策略优化(Proximal Policy Optimization)
  8. Origin好友列表离线的解决办法汇总
  9. 城市大脑标准体系与评价指标总体框架
  10. 3dmax2016的破解和安装
  11. 【协议基础】DNS协议概述DNS抓包分析
  12. unix时间戳 为什么计算机时间要从1970年1月1日开始算起?
  13. 18款 jQuery UI框架
  14. background-clip和background-origin
  15. Swiper图片垂直滑动
  16. 扎拉赞恩 服务器 微信群,《魔兽世界怀旧服》杜隆塔尔扎拉赞恩攻略 任务怎么玩...
  17. Python实战——自动生成情人节对女朋友表白玫瑰花、爱心,以及用Python画一颗樱花树,愿祖国繁花与共!
  18. 网安学习第一天——创建一个WNMP站点
  19. windows下xampp安装phpoffice/phpspreadsheet
  20. 联想G470自带的无线网卡总是不能上网

热门文章

  1. Windows 7操作系统设定密码策略和账户锁定策略
  2. 前端防抖与节流超详细讲解
  3. dell灵越14R笔记本出现关机3秒自动重启
  4. Windows10睡眠模式下过一段时间自动关机解决方法
  5. !important属性
  6. html 禁用自动跳转,阻止iframe里的网页自动跳转如何阻止iframe里引用的网页自动跳转方法...
  7. 企业APP的用途以及功能
  8. PGPool-II+PG流复制实现HA主备切换
  9. 2021中国大学生程序设计竞赛(CCPC),烤仔与你不见不散!
  10. Fio工具详解【强大的IO性能压测工具】