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

Completely uninstall mysql. Personal test!

Cleanly uninstall MySQL. Personally tested, this ...

What hidden attributes in the form can be submitted with the form

The form elements with visibility=hidden and displ...

Front-end vue+express file upload and download example

Create a new server.js yarn init -y yarn add expr...

40 web page designs with super large fonts

Today's web designs tend to display very larg...

Implementation of tomcat deployment project and integration with IDEA

Table of contents 3 ways to deploy projects with ...

Native JS to implement hover drop-down menu

JS implements a hover drop-down menu. This is a s...

Teach you how to get the pointer position in javascript

The method of obtaining the position of the point...

MySQL data analysis storage engine example explanation

Table of contents 1. Introduce cases 2. View the ...

How to modify Ubuntu's source list (source list) detailed explanation

Introduction The default source of Ubuntu is not ...

MySQL variable declaration and stored procedure analysis

Declaring variables Setting Global Variables set ...

Example of how to quickly build a LEMP environment with Docker

LEMP (Linux + Nginx + MySQL + PHP) is basically a...

Example of how to upload a Docker image to a private repository

The image can be easily pushed directly to the Do...

Linux bash: ./xxx: Unable to execute binary file error

Today I sent a small tool for Ubuntu to a custome...

Implementation code for adding links to FLASH through HTML (div layer)

Today a client wants to run an advertisement, and ...

Detailed explanation of vue page state persistence

Table of contents Code: Replenish: Summarize Requ...