日日操夜夜添-日日操影院-日日草夜夜操-日日干干-精品一区二区三区波多野结衣-精品一区二区三区高清免费不卡

公告:魔扣目錄網為廣大站長提供免費收錄網站服務,提交前請做好本站友鏈:【 網站目錄:http://www.ylptlb.cn 】, 免友鏈快審服務(50元/站),

點擊這里在線咨詢客服
新站提交
  • 網站:51998
  • 待審:31
  • 小程序:12
  • 文章:1030137
  • 會員:747

這篇文章主要介紹了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 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 視頻合成功能 拖拽上傳
用戶無頭像

網友整理

注冊時間:

網站:5 個   小程序:0 個  文章:12 篇

  • 51998

    網站

  • 12

    小程序

  • 1030137

    文章

  • 747

    會員

趕快注冊賬號,推廣您的網站吧!
最新入駐小程序

數獨大挑戰2018-06-03

數獨一種數學游戲,玩家需要根據9

答題星2018-06-03

您可以通過答題星輕松地創建試卷

全階人生考試2018-06-03

各種考試題,題庫,初中,高中,大學四六

運動步數有氧達人2018-06-03

記錄運動步數,積累氧氣值。還可偷

每日養生app2018-06-03

每日養生,天天健康

體育訓練成績評定2018-06-03

通用課目體育訓練成績評定