Vue+flask realizes video synthesis function (drag and drop upload)

Vue+flask realizes video synthesis function (drag and drop upload)

The video synthesis effect achieved by vue+flask is as follows

insert image description here

We have written about drag and drop upload in a previous article

//www.jb51.net/article/206543.htm

The principle is to listen to the drop event to get the dragged file list

insert image description here
insert image description here

Upload files

Upload files via axios

this,.fileList is our file list

let files = this.fileList;
let formd = new FormData();
let i = 1;

//Add upload list files.forEach(item => {
	formd.append(i + "", item, item.name)
	i++;
})
formd.append("type", i)
let config = {
	headers: {
		"Content-Type": "multipart/form-data"
	}
}

//Upload file request axios.post("/qwe", formd, config).then(res => {
	console.log(res.data)
})

Flask processes files

See the bottom for the complete code

The logic is as follows: Receive files, randomly generate a folder for each synthesis request, temporarily save files, stitch videos, return file path

@app.route("/file",methods=['POST'])
def test():

 #Get files files = request.files
 #Synthesis queue videoL = []
 #Random string dirs = sjs()
 #Generate folder os.mkdir(dirs)
 #Save the file and add it to the synthesis queue for file in files.values():
  print(file)
  dst = dirs + "/" + file.name + ".mp4"
  file.save(dst)
  video = VideoFileClip(dirs + "/" + file.name + ".mp4")
  videoL.append(video)
 
 #Splice video final = concatenate_videoclips(videoL)
 #File path fileName = dirs + "/" + "{}.mp4".format(sjs())
 #Generate video final.to_videofile(fileName)
 
 #Destroy folder def sc():
  shutil.rmtree(dirs)
 
 #Destroy the folder after 30 seconds timer = threading.Timer(30, sc)
 timer.start()

 # Return the file path return fileName

Splicing to get the file path

First, let's look at flask

The logic is as follows: Get the file by file name and return the file

app.route("/getvoi",methods=['GET'])
def getImg():
 #Get the file name ss = request.args['name']
 #Add the file to the returned response response = make_response(
  send_file(ss)

 #delete file def sc():
  os.remove(ss)
 
 #Delete the file after 30 seconds timer = threading.Timer(30, sc)
 timer.start()
 
 return response

Front-end acquisition

Download via tag a

<as :href="herfs" rel="external nofollow" rel="external nofollow" :download="fileName">Download</a>

herfs are as follows

insert image description here

After uploading the file, we process the returned file path through falsk and then obtain the file address

Adding the download attribute to the a tag can name the downloaded file

If you have any questions about /qwe /voi, please see the following proxy configuration instructions

Configuration Proxy Instructions

The purpose of configuring a proxy is to solve cross-domain issues. The development environment can be configured in vue.config.js and can be used. The production environment requires additional configuration of nginx

insert image description here

/qwe is actually http://127.0.0.1:8087/file
/voi is actually http://127.0.0.1:8087/getvoi
Corresponding to our flask

insert image description here

Additional Notes (if you use uni-app)

If you use uni-app, please refer to the documentation to use the api
Upload file api https://uniapp.dcloud.io/api/request/network-file?id=uploadfile
Download file API https://uniapp.dcloud.io/api/request/network-file?id=downloadfile
Or it is more convenient to directly use the plug-ins packaged by others.

Complete code

If you don't want to copy them one by one, you can download them from Download path 1: https://download.csdn.net/download/qq_42027681/15561897
Download path 2: https://github.com/dmhsq/vue-flask-videoSynthesis

flask code

md5random.py is used to generate random strings

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 service code

from flask import Flask,request,send_file,make_response
import os,json,threading,shutil
from moviepy.editor import *
from md5random import sjs

app = Flask(__name__)

@app.route("/file",methods=['POST'])
def test():

 #Get files files = request.files
 #Synthesis queue videoL = []
 #Random string dirs = sjs()
 #Generate folder os.mkdir(dirs)
 #Save the file and add it to the synthesis queue for file in files.values():
  print(file)
  dst = dirs + "/" + file.name + ".mp4"
  file.save(dst)
  video = VideoFileClip(dirs + "/" + file.name + ".mp4")
  videoL.append(video)

 #Splice video final = concatenate_videoclips(videoL)
 #File path fileName = dirs + "/" + "{}.mp4".format(sjs())
 #Generate video final.to_videofile(fileName)

 #Destroy folder def sc():
  shutil.rmtree(dirs)

 #Destroy the folder after 30 seconds timer = threading.Timer(30, sc)
 timer.start()

 # Return the file path return fileName


@app.route("/getvoi",methods=['GET'])
def getImg():
 #Get the file name ss = request.args['name']
 #Add the file to the returned response response = make_response(
  send_file(ss)

 #delete file def sc():
  os.remove(ss)

 #Delete the file after 30 seconds timer = threading.Timer(30, sc)
 timer.start()

 return response

if __name__ == '__main__':
 app.run(host='0.0.0.0',port=8087)

vue code

Demo file code

<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)">Delete</button>
 </div>
 <!-- Here is the last uploaded file to be displayed-->
<!-- <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">Synthesis</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">Download</span></el-button></a>
 <div style="position: relative;top: 100px">File download validity time {{times}}s</div>
 </div>
</template>

<script>
import axios from "axios";

export default {
 name: "trs",
 data() {
 return {
  dt: "", //Upload reminder "Drag here to upload the file" or "Upload completed, you can continue uploading"
  fileList: [], // file list loading: false,
  srcs: "", //Picture/video/audio base64
  isImage: false, //Is it an image? isAudio: false, //Is it an audio? isVideo: false, //Is it a video? isCan: true, //Can it be synthesized? isCans: true, //Can it be downloaded? herfs: "", //Download address fileName: "", //File name times: 25 //Download validity period };
 },
 filters:
 //Format file size 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);

 //Global monitoring when there is a file drag reminder in the page drag here document.addEventListener("dragover", function() {
  console.log(111);
  vm.dt = "Drag here to upload files";
  console.log(vm.dt);
 });
 },
 methods: {
 //Display files are mainly of three types: picture/video/audio 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("Not a picture/video/audio");
  }
  vm.srcs = reader.result;
  // this.$nextTick(()=>{
  //
  // })
  };
 },
 //Globally monitor the trigger event of drop to cancel the drop pop-up window display resource testfunc(event) {
  alert("dragdrop!");

  //Cancel the drop pop-up window display resource event.stopPropagation();
  event.preventDefault();
 },
 del(index) {
  this.fileList.splice(index, 1);
  if (this.fileList.length === 0) {
  this.dt = "";
  }
 },
 //Monitor the div upload box and display "Drag here to upload the file" when a file is dragged
 tts(e) {
  console.log(e);
  this.dt = "Drag here to upload the file";
 },
 //Listen for the div upload box drop event to trigger ttrs(e) {
  console.log(e);
  console.log(e.dataTransfer.files);

  //Get files let datas = e.dataTransfer.files;

  //Cancel the drop pop-up window display resource e.stopPropagation();
  e.preventDefault();
  datas.forEach(item => {
  if(item.type=="video/mp4"){
   this.fileList.push(item);
  }
  });

  //Read files. If you don't want to display pictures/videos/audios, you can ignore this.readFile(this.fileList[this.fileList.length - 1]);



  this.dt = "Upload completed, you can continue uploading";
 },

 //Upload files to the server ups(){
  if(this.fileList.length==0){
  this.$message('The file list is empty');
  return ;
  }
  this.loading = true;
  this.isCan = false;
  this.isCans = true;
  let files = this.fileList;
  let formd = new FormData();
  let i = 1;

  //Add upload list files.forEach(item=>{
  formd.append(i+"",item,item.name)
  i++;
  })
  formd.append("type",i)
  let config={
  headers:{"Content-Type":"multipart/form-data"}
  }

  //Upload file request axios.post("/qwe",formd,config).then(res=>{
  console.log(res.data)
  this.loading = false
  //Synthesized download path this.herfs = "/voi?name="+res.data

  this.fileName = res.data.split('/')[1]
  //Synthesis is prohibited this.isCan = false

  this.isCans = false

  //Set the download validity period. After the time is up, the download cannot be completed but the synthesis can continue. 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": ""
  }
  }
 }
 }
};

This is the end of this article about vue+flask to realize video synthesis function (drag and drop upload). For more related vue video synthesis content, please search 123WORDPRESS.COM's previous articles or continue to browse the following related articles. I hope everyone will support 123WORDPRESS.COM in the future!

You may also be interested in:
  • Vue implements drag and drop or click to upload pictures
  • Realize mobile image upload, compression, drag-and-drop sorting, and drag-and-drop deletion functions based on Vue2
  • Full-screen drag upload component based on Vue3

<<:  MySQL 5.7.18 installation tutorial and problem summary

>>:  Problems and solutions when installing MySQL8.0.13 on Win10 system

Recommend

Vue development tree structure components (component recursion)

This article example shares the specific code of ...

How to change the encoding of MySQL database to utf8mb4

The utf8mb4 encoding is a superset of the utf8 en...

Json string + Cookie + localstorage in JS

Table of contents 1.Json string 1.1Json Syntax 1....

Basic learning tutorial of table tag in HTML

Table label composition The table in HTML is comp...

Achieve 3D flip effect with pure CSS3 in a few simple steps

As a required course for front-end developers, CS...

How to clean up the disk space occupied by Docker

Docker takes up a lot of space. Whenever we run c...

Vue large screen display adaptation method

This article example shares the specific code for...

Canonical enables Linux desktop apps with Flutter (recommended)

Google's goal with Flutter has always been to...

Detailed explanation of desktop application using Vue3 and Electron

Table of contents Vue CLI builds a Vue project Vu...

Detailed explanation of how to enable slow query log in MySQL database

The database enables slow query logs Modify the c...

How to design and optimize MySQL indexes

Table of contents What is an index? Leftmost pref...

Vue+node realizes audio recording and playback function

Result: The main part is to implement the code lo...

Detailed steps for quick installation of openshift

The fastest way to experience the latest version ...