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

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

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

//www.jb51.net/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 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 sjs

app = 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 response

if __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视频合成内容请搜索我们以前的文章或继续浏览下面的相关文章希望大家以后多多支持我们!

(0)

相关推荐

  • vue视频播放插件vue-video-player的具体使用方法

    安装 npm install vue-video-player --save 引入 可以全局引入插件,也可以在需要用到该插件的组件内单独引入(二选一) [1]全局引用, 在main.js里面导入并引用 import VideoPlayer from 'vue-video-player' import 'vue-video-player/src/custom-theme.css' import 'video.js/dist/video-js.css' Vue.use(VideoPlayer) [2

  • vue-video-player视频播放器使用配置详解

    本文实例为大家分享了vue-video-player视频播放器的使用配置,供大家参考,具体内容如下 1.安装 npm install vue-video-player -save 2.在main.js中添加 import VueVideoPlayer from 'vue-video-player' // 视频播放器 import 'video.js/dist/video-js.css' Vue.use(VueVideoPlayer) 3.新建一个vueVideoPlayer.vue组件供调用 <

  • 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>

  • 基于Vue2实现移动端图片上传、压缩、拖拽排序、拖拽删除功能

    用Vue2实现移动端图片上传.压缩.拖拽排序.拖拽删除功能 图片上传图片压缩拖拽排序.拖拽删除 之前在公司开发过一段时间的移动端H5页面,有个功能就是要上传图片+压缩.参考了一下网上的方法,外加自己摸索的过程,最终实现了这个功能.后面在家闲的时候又加多了个长按选中图片,并且可以拖拽排序.拖拽到指定位置删除的功能. github地址:代码地址 下面直接进入正题: 图片上传 图片上传用的是HTML的input标签实现的.核心就是把获取到的文件通过FileReader转换成图片,代码如下: <inpu

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

    vue+flask实现视频合成 效果如下 拖拽上传我们之前一个文章有写过 //www.jb51.net/article/206543.htm 原理就是 监听drop事件 来获取拖拽的文件列表 上传文件 通过axios 上传文件 this,.fileList就是我们的文件列表 let files = this.fileList; let formd = new FormData(); let i = 1; //添加上传列表 files.forEach(item => { formd.append(

  • Nodejs+express+html5 实现拖拽上传

    一.前言 文件上传是一个比较常见的功能,传统的选择方式的上传比较麻烦,需要先点击上传按钮,然后再找到文件的路径,然后上传.给用户体验带来很大问题.html5开始支持拖拽上传的需要的api.nodejs也是一个最近越来越流行的技术,这也是自己第一次接触nodejs,在nodejs开发中,最常用的开发框架之一是expess,它是一个类似mvc模式的框架.结合html5.nodejs express实现了拖拽上传的功能. 二.基础知识普及 1.NodeJs基础知识 nodejs简单来说就是一个可以让j

  • 前端页面文件拖拽上传模块js代码示例

    最近给卫生局做一个表格上传/可视化系统,算是小有成果.今天把项目中的文件拖拽上传模块分离出来,做了一个独立的小demo,并把相关代码打包上传到了我的github中,为了其他学习者和开发者提供拙见. gitHub地址:https://github.com/codeplay2015/dragToUpload 由于代码中我的注释很详尽,所以具体逻辑实现及不介绍了,大家直接看代码及能明白.现在简单列一个功能清单和一些用到的知识点清单: 模态框 文件的批量上传 使用formData API 封装数据 并通

  • 基于Vue3的全屏拖拽上传组件

    本文主要介绍了基于Vue3的全屏拖拽上传组件,分享给大家,具体如下: 知识点 浏览器拖拽 api fetch 请求 vue3 说来话长,长话短说,关于 html5 的拖拽 api 也只是做过一些拖拽排序的例子.其实思路上与其他拖拽上传组件基本一样,都是指定一个区域可拖拽,然后读取文件在上传 先说说拖拽 api,这个是 html5 新增的一个 api,给一个元素设置 draggable = true 属性时,该元素就会支持拖拽 拖拽元素事件如下 1. ondrag 当拖动元素的时候运行脚本 2.

  • HTML5附件拖拽上传drop & google.gears实现代码

    腾讯微博也已近实现了拖拽上传.其实很简单. 由于没有服务器支持在文章里不能做上传演示,下载实例 拖拽上传需要什么支持 1:需要浏览器支持 drop 事件.(响应拖拽事件获取file对象); 2:XMLHttpRequest 对象有 sendAsBinary 方法(用于发送数据); 以上两个条件 目前仅有 firefox 能达到. chrome 第一项达标,第2项可以使用 google.gears 来模拟. 所以能实现拖拽上传的浏览器 有 firefox3.6 + 和 chrome7+. 如何实现

  • Js+php实现异步拖拽上传文件

    异步拖拽上传文件--小实例 upload.html <!DOCTYPE html> <!-- To change this license header, choose License Headers in Project Properties. To change this template file, choose Tools | Templates and open the template in the editor. --> <html> <head&g

  • 简单实现ajax拖拽上传文件

    AJAX拖拽上传功能实现,供大家参考,具体内容如下 <!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <meta http-equiv="

  • 关于js拖拽上传 [一个拖拽上传修改头像的流程]

    如今现代的浏览器已经有很多支持拖拽文件读取操作,其优点不再复述.前端时间利用拖拽改进了一下网站的头像上传流程,对其中的要点和实践体会做一点总结. 先看一下总体视图:1. 文件拖拽接受区域要有明显的标示,并且要尽可能的大(由于版面的原因,这个界面的拖放盒子并不大).可以用虚线框盒子等样式吸引用户拖拽文件.最好有明显的文字提示和图标配合. 2. 在交互体验上当文件拖入浏览器窗口时,可以用拖放区变换背景颜色等向用户发起放置操作邀请. 实现代码: 复制代码 代码如下: doc.bind({ 'drage

  • javascript拖拽上传类库DropzoneJS使用方法

    用法 1. add js and css style 复制代码 代码如下: <link href="~/Dropzone/css/basic.css" rel="stylesheet" /> <link href="~/Dropzone/css/dropzone.css" rel="stylesheet" /> <script src="~/Dropzone/dropzone.min.j

  • Dropzone.js实现文件拖拽上传功能(附源码下载)

    dropzone.js是一个开源的JavaScript库,提供 AJAX 异步文件上传功能,支持拖拽文件.支持最大文件大小.支持设置文件类型.支持预览上传结果,不依赖jQuery库. 效果演示      源码下载 使用Dropzone 我们可以建立一个正式的上传form表单,并且给表单一个.dropzone的class. <form id="mydropzone" action="/upload.php" class="dropzone"&

随机推荐