vue+flaskで実現したビデオ合成効果は以下のとおりです ドラッグアンドドロップアップロードについては以前の記事で書きました。//www.jb51.net/article/206543.htm 原理は、ドロップイベントをリッスンしてドラッグされたファイルリストを取得することです。 ファイルをアップロードするaxios経由でファイルをアップロードする this.fileListはファイルリストです ファイルを this.fileList とします。 formd = new FormData(); i = 1 とします。 //アップロードリストファイルを追加します。forEach(item => { formd.append(i + "", 項目、項目名) 私は++; }) formd.append("type", i) 設定 = { ヘッダー: { 「コンテンツタイプ」: 「マルチパート/フォームデータ」 } } //ファイルアップロードリクエスト axios.post("/qwe", formd, config).then(res => { コンソールログ(res.data) }) Flaskはファイルを処理する完全なコードは下部をご覧ください ロジックは次のとおりです。ファイルを受信し、合成要求ごとにフォルダーをランダムに生成し、ファイルを一時的に保存し、ビデオをステッチし、ファイルパスを返します。 @app.route("/file",メソッド=['POST']) デフテスト(): #ファイルを取得する files = request.files #合成キュー videoL = [] #ランダム文字列 dirs = sjs() #フォルダーを生成 os.mkdir(dirs) #ファイルを保存し、files.values() 内のファイルの合成キューに追加します。 印刷(ファイル) dst = dirs + "/" + ファイル名 + ".mp4" ファイル.save(dst) ビデオ = VideoFileClip(dirs + "/" + ファイル名 + ".mp4") videoL.append(ビデオ) #ビデオを結合 final = concatenate_videoclips(videoL) #ファイルパス fileName = dirs + "/" + "{}.mp4".format(sjs()) #ビデオを生成する final.to_videofile(fileName) #フォルダーを破棄 def sc(): shutil.rmtree(ディレクトリ) #30秒後にフォルダーを破棄します timer = threading.Timer(30, sc) タイマー.開始() # ファイルパスを返す return fileName ファイルパスを取得するためのスプライシングまずフラスコを見てみましょうロジックは次のとおりです。ファイル名でファイルを取得し、ファイルを返します。 app.route("/getvoi",メソッド=['GET']) getImg() を定義します: #ファイル名を取得する ss = request.args['name'] #返されたレスポンスにファイルを追加する response = make_response( 送信ファイル #ファイルを削除する def sc(): os.remove(ss) #30秒後にファイルを削除します timer = threading.Timer(30, sc) タイマー.開始() 応答を返す フロントエンドの獲得タグaでダウンロード <as :href="herfs" rel="external nofollow" rel="external nofollow" :download="fileName">ダウンロード</a> ハーフは以下の通りです ファイルをアップロードした後、返されたファイルパスをfalskで処理し、ファイルアドレスを取得します。 aタグにダウンロード属性を追加すると、ダウンロードしたファイルに名前を付けることができます。 /qwe /voiについてご質問がある場合は、次のプロキシ設定手順を参照してください。 プロキシ設定手順プロキシを設定する目的は、クロスドメインの問題を解決することです。開発環境はvue.config.jsで設定して使用できます。本番環境ではnginxの追加設定が必要です。 /qwe は実際には http://127.0.0.1:8087/file です 追加メモ(uni-app を使用する場合) uni-appを使用する場合は、APIを使用するためのドキュメントを参照してください。 完全なコード一つずつコピーしたくない場合は、ダウンロード パス 1 からダウンロードできます: https://download.csdn.net/download/qq_42027681/15561897 フラスココードmd5random.pyはランダムな文字列を生成するために使用されますランダムにインポート ハッシュライブラリをインポートする sjs() を定義します: a = ランダム.randint(0, 100) a = "a" + str(a); 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 = ランダム.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() e を返します。 app_service.py サービスコードFlask から Flask、request、send_file、make_response をインポートします os、json、threading、shutil をインポートします moviepy.editor からインポート * md5randomからsjsをインポート アプリ = Flask(__name__) @app.route("/file",メソッド=['POST']) デフテスト(): #ファイルを取得する files = request.files #合成キュー videoL = [] #ランダム文字列 dirs = sjs() #フォルダーを生成 os.mkdir(dirs) #ファイルを保存し、files.values() 内のファイルの合成キューに追加します。 印刷(ファイル) dst = dirs + "/" + ファイル名 + ".mp4" ファイル.save(dst) ビデオ = VideoFileClip(dirs + "/" + ファイル名 + ".mp4") videoL.append(ビデオ) #ビデオを結合 final = concatenate_videoclips(videoL) #ファイルパス fileName = dirs + "/" + "{}.mp4".format(sjs()) #ビデオを生成する final.to_videofile(fileName) #フォルダーを破棄 def sc(): shutil.rmtree(ディレクトリ) #30秒後にフォルダーを破棄します timer = threading.Timer(30, sc) タイマー.開始() # ファイルパスを返す return fileName @app.route("/getvoi",メソッド=['GET']) getImg() を定義します: #ファイル名を取得する ss = request.args['name'] #返されたレスポンスにファイルを追加する response = make_response( 送信ファイル #ファイルを削除する def sc(): os.remove(ss) #30秒後にファイルを削除します timer = threading.Timer(30, sc) タイマー.開始() 応答を返す __name__ == '__main__' の場合: app.run(ホスト='0.0.0.0'、ポート=8087) vueコードデモファイルコード <テンプレート> <div> <div v-on:dragover="tts" v-on:drop="ttrs" スタイル="幅: 800px;高さ: 200px;境界線: 1px 黒一色;フォントサイズ: 40px;行の高さ: 200px" > {{dt}} </div> <div v-for="(item, index) in fileList" :key="インデックス" スタイル="幅: 800px;高さ: 200px;境界線: 1px 黒一色;フォントサイズ: 40px;位置: 相対;上: 10px" > <p style="font-size: 20px;float: left;position: relative;left: 20pxword-wrap:break-word;word-break:normal;" > {{アイテム名}} </p> <h5 style="float:right;position: absolute;top: 80px;right: 20px"> {{アイテムタイプ}} </h5> <h6 スタイル="位置: 絶対;上: 80px;フロート: 左;左: 20px"> {{ item.size | サイズタイプ }} </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}} 秒</div> </div> </テンプレート> <スクリプト> 「axios」からaxiosをインポートします。 エクスポートデフォルト{ 名前: "trs", データ() { 戻る { dt: "", // アップロードリマインダー「ファイルをアップロードするにはここにドラッグしてください」または「アップロードが完了しました。アップロードを続行できます」 fileList: [], // ファイルリストの読み込み: false, srcs: "", //画像/ビデオ/オーディオ base64 isImage: false, //画像ですか? isAudio: false, //音声ですか? isVideo: false, //動画ですか? isCan: true, //合成できますか? isCans: true, //ダウンロードできますか? herfs: "", //ダウンロードアドレス fileName: "", //ファイル名 times: 25 //ダウンロード有効期間 }; }, フィルター: //ファイルサイズのフォーマット sizeType(val) { kbs = val / 1024とします。 mbs = 0 とします。 gbs = 0 とします。 (kbs >= 1024)の場合{ mbs = kbs / 1024; } mbs >= 1024の場合{ gbs = mbs / 1024; gbs.toFixed(2) + "GB" を返します。 } それ以外の場合 (mbs >= 1) { mbs.toFixed(2) + "MB"を返します。 } それ以外 { kbs.toFixed(2) + "KB"を返します。 } } }, マウント() { vm = this とします。 window.addEventListener("dragdrop", this.testfunc, false); //ページ内にファイルドラッグリマインダーがあるときのグローバル監視ここにドラッグ document.addEventListener("dragover", function() { コンソールログ(111); vm.dt = "ファイルをアップロードするにはここにドラッグしてください"; コンソールログ(vm.dt); }); }, メソッド: { //表示ファイルは主に画像/ビデオ/オーディオの3種類です。readFile(file) { vm = this とします。 リーダーを新しいFileReader()にします。 reader.readAsDataURL(ファイル); リーダー.onload = 関数() { type = file.type.substr(0, 5); とします。 if (type == "画像") { vm.isImage が true である。 vm.isAudio = false; vm.isVideo = false; } そうでない場合 (type == "audio") { vm.isImage = false; vm.isAudio が true である。 vm.isVideo = false; } そうでない場合 (type == "video") { vm.isImage = false; vm.isAudio = false; vm.isVideo が true である。 } それ以外 { alert("画像/ビデオ/オーディオではありません"); } vm.srcs = リーダーの結果; // this.$nextTick(()=>{ // // }) }; }, //ドロップのトリガーイベントをグローバルに監視してドロップポップアップウィンドウの表示をキャンセルするリソース testfunc(event) { アラート("ドラッグドロップ!"); //ドロップポップアップウィンドウの表示リソースをキャンセルします。event.stopPropagation(); イベントをデフォルトにしない(); }, del(インデックス) { this.fileList.splice(インデックス、1); if (this.fileList.length === 0) { this.dt = ""; } }, //div アップロード ボックスを監視し、ファイルがドラッグされたときに「ファイルをアップロードするにはここにドラッグしてください」と表示します tts(e) { コンソールログ(e); this.dt = "ファイルをアップロードするにはここにドラッグしてください"; }, //divアップロードボックスのドロップイベントをリッスンしてttrs(e)をトリガーします{ コンソールログ(e); console.log(e.dataTransfer.files); //ファイルを取得する let datas = e.dataTransfer.files; //ドロップポップアップウィンドウの表示リソースをキャンセルします e.stopPropagation(); e.preventDefault(); datas.forEach(item => { if(item.type=="video/mp4"){ this.fileList.push(アイテム); } }); // ファイルを読み取ります。画像/ビデオ/オーディオを表示したくない場合は、this.readFile(this.fileList[this.fileList.length - 1]); を無視できます。 this.dt = "アップロードが完了しました。アップロードを続行できます"; }, //サーバーにファイルをアップロードする ups(){ if(this.fileList.length==0){ this.$message('ファイルリストは空です'); 戻る ; } this.loading = true; this.isCan = false; this.isCans = true; ファイルを this.fileList とします。 formd = new FormData(); i = 1 とします。 //アップロードリストファイルを追加します。forEach(item=>{ formd.append(i+"",item,item.name) 私は++; }) formd.append("type",i) config={を設定します ヘッダー:{"Content-Type":"multipart/form-data"} } //ファイルアップロードリクエスト axios.post("/qwe",formd,config).then(res=>{ コンソールログ(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(()=>{ 今回は--; },1000) this.setCans(タイマー) }) }, setCans(タイマー){ タイムアウトを設定します(()=>{ this.isCans = true this.isCan = true this.fileName = "" クリアインターバル(タイマー) これを25回繰り返す },25000) } } }; </スクリプト> <スタイル スコープ></style> 設定ファイル モジュール.エクスポート = { 開発サーバー: { // アセットサブディレクトリ: 'static', // アセットパブリックパス: '/', プロキシ: { "/qwe": { ターゲット: "http://127.0.0.1:8087/file", 変更元: true、 パス書き換え: { "^/qwe": "" } }, "/voi": { ターゲット: "http://127.0.0.1:8087/getvoi", 変更元: true、 パス書き換え: { "^/voi": "" } } } } }; これで、vue+flask で動画合成機能 (ドラッグアンドドロップアップロード) を実現する方法についての説明は終わりです。vue 動画合成に関するその他の関連コンテンツについては、123WORDPRESS.COM の過去の記事を検索するか、以下の関連記事を引き続き参照してください。今後とも 123WORDPRESS.COM をよろしくお願いいたします。 以下もご興味があるかもしれません:
|
<<: Win10 システムに MySQL8.0.13 をインストールする際の問題と解決策
>>: MySQL v5.7.18 解凍バージョンのインストール詳細チュートリアル
この記事では、簡単な画像ドラッグ効果を実現するためのjsの具体的なコードを参考までに紹介します。具体...
目次背景1) yumのkeepchche機能を有効にする: 方法1 2) yum-utils ソフト...
本日の投稿では、Web デザインで使用される円形要素の優れた例をいくつか挙げ、美しい丸いボタン、メニ...
1. ソフトウェアをダウンロードする1. MySQL の公式サイトにアクセスし、Oracle アカウ...
会社の開発者がテスト環境で挿入ステートメントを実行すると、正常に実行されるまでに 10 秒以上かかり...
目次1. 準備: 2. ソースコードのコンパイル1. 設定する2. コンパイルエラー3. ターゲット...
grubの起動時間を変更するためのオンライン検索は基本的に/etc/default/grubを変更す...
序文始める前に、ファイル属性とファイル属性を変更する方法について簡単に理解しておく必要があります。 ...
この記事では、jQueryプラグインを使用したマインスイーパゲームの最初の記事の具体的なコードを参考...
この記事では、物流タイムライン効果を実現するためのVueの具体的なコードを例として紹介します。具体的...
目次シナリオ解決してみる解決するシナリオ今日、コンポーネントの双方向データバインディングにv-mod...
その後、VSC で Jupyter Notebook を使用する方法も追加しました...アナコンダを...
まず依存関係をダウンロードします yarn sass-loader ノード sass を追加します次...
数日前、ある要件に取り組んでいたとき、MySQL で重複レコードをクリーンアップする必要がありました...
この記事では、ビデオタグを使用してビデオ再生を実装するVueの具体的なコードを参考までに共有します。...