首页前端开发JavaScriptvue+flask实现视频合成功能(拖拽上传)

vue+flask实现视频合成功能(拖拽上传)

时间2024-02-01 01:17:03发布访客分类JavaScript浏览454
导读:收集整理的这篇文章主要介绍了vue+flask实现视频合成功能(拖拽上传 ,觉得挺不错的,现在分享给大家,也给大家做个参考。 目录拖拽上传我们之前一个文章有写过上传文件flask处理文件...
收集整理的这篇文章主要介绍了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核实处理,我们将尽快回复您,谢谢合作!

      上一篇: JavaScript统计字符出现次数下一篇:React服务端渲染原理解析与实践猜你在找的JavaScript相关文章 html font标签如何设置字体大小?html font标签属性用法介绍2022-05-16vue3+TypeScript+vue-router的使用方法2022-04-16vue3获取当前路由地址2022-04-16如何利用React实现图片识别App2022-04-16JavaScript展开运算符和剩余运算符的区别详解2022-04-16微信小程序中使用vant框架的具体步骤2022-04-16Vue elementUI表单嵌套表格并对每行进行校验详解2022-04-16如何利用Typescript封装本地存储2022-04-16微信小程序中wxs文件的一些妙用分享2022-04-16JavaScript的Set数据结构详解2022-04-16 其他相关热搜词更多phpjavapython程序员loadpost-format-gallery

      若转载请注明出处: vue+flask实现视频合成功能(拖拽上传)
      本文地址: https://pptw.com/jishu/594729.html
      char数组如何转string c程序的基本组成单位是什么?

      游客 回复需填写必要信息