• linkedu视频
  • 平面设计
  • 电脑入门
  • 操作系统
  • 办公应用
  • 电脑硬件
  • 动画设计
  • 3D设计
  • 网页设计
  • CAD设计
  • 影音处理
  • 数据库
  • 程序设计
  • 认证考试
  • 信息管理
  • 信息安全
菜单
linkedu.com
  • 网页制作
  • 数据库
  • 程序设计
  • 操作系统
  • CMS教程
  • 游戏攻略
  • 脚本语言
  • 平面设计
  • 软件教程
  • 网络安全
  • 电脑知识
  • 服务器
  • 视频教程
  • dedecms
  • ecshop
  • z-blog
  • UcHome
  • UCenter
  • drupal
  • WordPress
  • 帝国cms
  • phpcms
  • 动易cms
  • phpwind
  • discuz
  • 科汛cms
  • 风讯cms
  • 建站教程
  • 运营技巧
您的位置:首页 > CMS教程 >建站教程 > vue+flask实现视频合成功能(拖拽上传)

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

作者:站长图库 字体:[增加 减小] 来源:互联网 时间:2022-04-29

站长图库向大家介绍了vue+flask,视频合成功能,拖拽上传等相关知识,希望对您有所帮助

这篇文章主要介绍了vue+flask实现视频合成功能(拖拽上传),本文通过实例代码给大家介绍的非常详细,对大家的学习或工作具有一定的参考借鉴价值,需要的朋友可以参考下

vue+flask实现视频合成

效果如下


在这里插入图片描述

原理就是 监听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": ""                }            }        }    }};


分享到:QQ空间新浪微博腾讯微博微信百度贴吧QQ好友复制网址打印

您可能想查找下面的文章:

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

相关文章

  • 2022-04-29PHP调用今天的日期几月星期几
  • 2022-04-29分析PHP7.2忽略父类方法以及Liskov替换原则相关问题
  • 2022-04-29让dedecms友情链接也支持limit
  • 2022-04-29Photoshop制作玻璃图标按钮
  • 2022-04-29JavaScript如何替换中间内容
  • 2022-04-29AI教程巧形状生成器制作设计立体渐变数字字体设计教程
  • 2022-04-29解决网站打开出现"SEC_ERROR_EXPIRED_CERTIFICATE"问题
  • 2022-04-29Photoshop技巧:CC版本的最全总结
  • 2022-04-29Photoshop设计书法人像前后期创作分享
  • 2022-04-29PHP采集插件QueryList实践教学

文章分类

  • dedecms
  • ecshop
  • z-blog
  • UcHome
  • UCenter
  • drupal
  • WordPress
  • 帝国cms
  • phpcms
  • 动易cms
  • phpwind
  • discuz
  • 科汛cms
  • 风讯cms
  • 建站教程
  • 运营技巧

最近更新的内容

    • Javascript中事件对象的target和this的区别
    • Thinkphp5.1 + layui时间范围设置方法
    • Javascript删除字符串最后一个字符
    • WordPress子分类页面使用父分类页面模板
    • PhotoShop绘制水晶质感3D立体按钮制作教程
    • 四种Laravel ORM开启created_at的方法
    • 柒比贰主题网格风格四缩略图对齐样式代码
    • PhotoShop制作逼真的补丁文字效果的教程
    • css如何实现底部tapbar栏效果
    • 怎么为WordPress上下篇文章链接添加缩略图

关于我们 - 联系我们 - 免责声明 - 网站地图

©2020-2025 All Rights Reserved. linkedu.com 版权所有