最新国产好看的视频,伊人天堂AV在线,国产Aaaaaa视频,蜜臀视频在线观看一区,人妻av色图,密臀久久久精品影片,青青视频免费观看毛片,久草在线观看视,国产三级精品色情在线

vue+flask實現(xiàn)視頻合成功能(拖拽上傳)

 更新時間:2021年03月04日 17:10:21   作者:代碼哈士奇  
這篇文章主要介紹了vue+flask實現(xiàn)視頻合成功能(拖拽上傳),本文通過實例代碼給大家介紹的非常詳細(xì),對大家的學(xué)習(xí)或工作具有一定的參考借鑒價值,需要的朋友可以參考下

vue+flask實現(xiàn)視頻合成
效果如下

在這里插入圖片描述

拖拽上傳我們之前一個文章有寫過

//m.fzitv.net/article/206543.htm

原理就是 監(jiān)聽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處理文件

完整代碼見最底部

邏輯如下
接收文件
為每次合成請求隨機(jī)生成一個文件夾 臨時保存文件
拼接視頻
返回文件路徑

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

 #獲取文件
 files = request.files
 #合成隊列
 videoL = []
 #隨機(jī)字符串
 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']
 #文件加至返回響應(yīng)
 response = make_response(
  send_file(ss))

 #刪除文件
 def sc():
  os.remove(ss)
 
 #30秒后刪除文件
 timer = threading.Timer(30, sc)
 timer.start()
 
 return response

前端獲取

通過a標(biāo)簽下載

<a s :href="herfs" rel="external nofollow" rel="external nofollow" :download="fileName">下載</a>

herfs如下

在這里插入圖片描述

我們上傳文件后 通過falsk處理返回文件路徑 拼接后獲取文件地址

a標(biāo)簽添加download屬性可以給下載的文件命名

如果你對/qwe /voi有疑惑 請看下面的配置代理說明

配置代理說明

配置代理是為了解決跨域問題 開發(fā)環(huán)境可在vue.config.js配置即可使用
生產(chǎn)環(huán)境需要額外配置nginx

在這里插入圖片描述

/qwe實際上就是 http://127.0.0.1:8087/file
/voi實際上就是 http://127.0.0.1:8087/getvoi
對應(yīng)我們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
或者直接使用別人封裝好的 插件畢竟比較方便

完整代碼

如果你不想一個一個復(fù)制可以去下載
下載途徑1: https://download.csdn.net/download/qq_42027681/15561897
下載途徑2:https://github.com/dmhsq/vue-flask-videoSynthesis

flask代碼

md5random.py 用于隨機(jī)字符串生成

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 服務(wù)代碼

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 = []
 #隨機(jī)字符串
 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']
 #文件加至返回響應(yīng)
 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: "",//上傳提醒 "拖動到此處上傳文件“或者"上傳完成,可繼續(xù)上傳"
  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);

 //全局監(jiān)聽 當(dāng)頁面內(nèi)有文件拖動 提醒拖動到此處
 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(()=>{
  //
  // })
  };
 },
 //全局監(jiān)聽drop的觸發(fā)事件 取消drop彈窗顯示資源
 testfunc(event) {
  alert("dragdrop!");

  //取消drop彈窗顯示資源
  event.stopPropagation();
  event.preventDefault();
 },
 del(index) {
  this.fileList.splice(index, 1);
  if (this.fileList.length === 0) {
  this.dt = "";
  }
 },
 //監(jiān)聽div上傳框 當(dāng)有文件拖動時 顯示"拖動到此處上傳文件"
 tts(e) {
  console.log(e);
  this.dt = "拖動到此處上傳文件";
 },
 //監(jiān)聽div上傳框 drop事件觸發(fā)
 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 = "上傳完成,可繼續(xù)上傳";
 },

 //上傳文件到服務(wù)器
 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

  //設(shè)置下載有效時間 時間到后無法下載但可以繼續(xù)合成
  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": ""
  }
  }
 }
 }
};

到此這篇關(guān)于vue+flask實現(xiàn)視頻合成功能(拖拽上傳)的文章就介紹到這了,更多相關(guān)vue視頻合成內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!

相關(guān)文章

  • gulp模塊使用方法示例詳解

    gulp模塊使用方法示例詳解

    這篇文章主要為大家介紹了gulp模塊使用方法示例詳解,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪
    2022-09-09
  • vue3引入Element-plus的詳細(xì)步驟記錄

    vue3引入Element-plus的詳細(xì)步驟記錄

    Element Plus是為適配Vue3而對Element UI進(jìn)行重構(gòu)后產(chǎn)生的前端組件庫,包含豐富的基礎(chǔ)組件,下面這篇文章主要給大家介紹了關(guān)于vue3引入Element-plus的相關(guān)資料,需要的朋友可以參考下
    2022-04-04
  • vue中控制mock在開發(fā)環(huán)境使用,在生產(chǎn)環(huán)境禁用方式

    vue中控制mock在開發(fā)環(huán)境使用,在生產(chǎn)環(huán)境禁用方式

    這篇文章主要介紹了vue中控制mock在開發(fā)環(huán)境使用,在生產(chǎn)環(huán)境禁用方式,具有很好的參考價值,希望對大家有所幫助。如有錯誤或未考慮完全的地方,望不吝賜教
    2022-04-04
  • vue之監(jiān)聽頁面是否以到底部

    vue之監(jiān)聽頁面是否以到底部

    這篇文章主要介紹了vue之監(jiān)聽頁面是否以到底部問題,具有很好的參考價值,希望對大家有所幫助,如有錯誤或未考慮完全的地方,望不吝賜教
    2023-10-10
  • Vue實現(xiàn)移動端拖拽交換位置

    Vue實現(xiàn)移動端拖拽交換位置

    這篇文章主要為大家詳細(xì)介紹了Vue實現(xiàn)移動端拖拽交換位置,文中示例代碼介紹的非常詳細(xì),具有一定的參考價值,感興趣的小伙伴們可以參考一下
    2020-07-07
  • 詳解vue中v-bind:style效果的自定義指令

    詳解vue中v-bind:style效果的自定義指令

    這篇文章主要介紹了vue中v-bind:style效果的自定義指令,本文通過實例代碼給大家介紹的非常詳細(xì),具有一定的參考借鑒價值,需要的朋友可以參考下
    2020-01-01
  • Vue自定義指令學(xué)習(xí)及應(yīng)用詳解

    Vue自定義指令學(xué)習(xí)及應(yīng)用詳解

    這篇文章主要為大家詳細(xì)介紹了Vue中自定義指令的學(xué)習(xí)以及如何利用Vue制作一個簡單的學(xué)生信息管理系統(tǒng),感興趣的小伙伴可以跟隨小編一起學(xué)習(xí)一下
    2023-05-05
  • vuex + keep-alive實現(xiàn)tab標(biāo)簽頁面緩存功能

    vuex + keep-alive實現(xiàn)tab標(biāo)簽頁面緩存功能

    這篇文章主要介紹了vuex + keep-alive實現(xiàn)tab標(biāo)簽頁面緩存功能,非常不錯,具有一定的參考借鑒價值,需要的朋友可以參考下
    2019-10-10
  • vue2.0如何借用vue-pdf實現(xiàn)在線預(yù)覽pdf文件

    vue2.0如何借用vue-pdf實現(xiàn)在線預(yù)覽pdf文件

    這篇文章主要介紹了vue2.0如何借用vue-pdf實現(xiàn)在線預(yù)覽pdf文件問題,具有很好的參考價值,希望對大家有所幫助,如有錯誤或未考慮完全的地方,望不吝賜教
    2024-03-03
  • vue開發(fā)中關(guān)于axios的封裝過程

    vue開發(fā)中關(guān)于axios的封裝過程

    這篇文章主要介紹了vue開發(fā)中關(guān)于axios的封裝過程,具有很好的參考價值,希望對大家有所幫助。如有錯誤或未考慮完全的地方,望不吝賜教
    2022-08-08

最新評論

东阳市| 太谷县| 鄯善县| 新宁县| 奈曼旗| 巨野县| 苗栗市| 遵化市| 辽源市| 余干县| 仁化县| 年辖:市辖区| 福鼎市| 云阳县| 庄浪县| 柯坪县| 天气| 屯留县| 清水河县| 广德县| 辉南县| 大厂| 东乡族自治县| 仪征市| 手游| 开阳县| 南岸区| 柏乡县| 迭部县| 佳木斯市| 韶山市| 辽阳县| 武功县| 博兴县| 阜城县| 罗甸县| 华安县| 青海省| 绍兴县| 定结县| 乐清市|