複数個の動画ファイル​を1つに結合すること​はできますか?

「.mp4」または「.avi」形式で保存された、動画ファイルが100個あります。
動画を縦横方向に(一例5×20)に結合して新たに1つの動画ファイルを作成し、保存することは可能でしょうか。
使用する動画を添付することができませんでした。使用したいファイルの名前は「test01」、「test02」...「test100」です。
フォルダを指定して、ワークスペースに展開した後、何らかの処理があると考えられるのですが、動画をどう取り扱うべきか分からず、こちらでご質問させていただきました。ファイルを数値変数として結合する必要があるのか、何らか動画形式で結合する手段があるのか、ご教示いただけないでしょうか。なお、フォーマット、フレームレート等の動画形式は、全て同じです。
ご確認を、どうぞよろしくお願いいたします。

2 Comments

Kojiro Saito
Kojiro Saito on 6 Feb 2024
映像を結合されたいのだと理解しましたが、音声も結合するのでしょうか?
non
non on 6 Feb 2024
コメントありがとうございます。映像のみ結合させたいです。

Sign in to comment.

 Accepted Answer

Kojiro Saito
Kojiro Saito on 6 Feb 2024
Edited: Kojiro Saito on 7 Feb 2024

5 votes

動画の数だけVideoReaderを作り、フレーム毎にreadFrameで画像を取得してhorzcatで横向きに結合、vertcatで縦向きに結合し、VideoWriterで1つの動画に出力する方法で実現できます。
あまりきれいなコードではないですが、サンプルを書きます。
% 出力先の1つの動画をVideoWriterで作成
vw = VideoWriter("videoMerge.avi");
open(vw)
% 元の100個の動画のVideoReaderを作成
myVideo = cell(100, 1);
for n=1:100
myVideo{n} = VideoReader(sprintf("test%02d.avi", n));
end
% 動画ごとのフレーム画像を事前に定義
myFrame = cell(100, 1);
while hasFrame(myVideo{1})
imM = [];
for n=1:100
% 動画ごとのフレーム画像を格納
myFrame{n} = readFrame(myVideo{n});
end
% 5行✕20列の結合した動画を作成する
for n=1:20:81
tempImM = [];
for m=0:19
% 横向きに画像を結合
tempImM = horzcat(tempImM, myFrame{n+m});
end
% 縦向きに画像を結合
imM = vertcat(imM, tempImM);
end
% 結合したフレームを動画に出力
writeVideo(vw, imM)
end
% VideoWriterとVideoReaderを消去
close(vw)
clear myVideo
※最初の回答では20行✕5列の動画になってしまっていたので5行✕20列の動画になるように修正しました。

2 Comments

non
non on 9 Feb 2024
Kojiro Saito様
的確なご回答と、サンプルコードまで、本当にありがとうございます。
無事に、動画を縦・横向きに結合することができました。
これまでは、パワーポイント上に貼り付けた動画ファイルを手作業で整列させていました。
ご回答いただいたコードのおかげで、動画結合が簡単になり、また、並び替えも自動で自由自在になりました。
この度は、誠にありがとうございました。
Kojiro Saito
Kojiro Saito on 9 Feb 2024
@nonさん
解決して良かったです。回答のAcceptもありがとうございました!

Sign in to comment.

More Answers (1)

Atsushi Ueno
Atsushi Ueno on 11 Feb 2024

0 votes

すでに解決済みですが...
”MATLABでfor文使ったら負け”教の信者として、どうしてもfor文を削除したかったんです。
% 元の100個の動画のVideoReaderを作成
path = uigetdir(pwd,'動画のあるフォルダを選択');
fds = fileDatastore(path,'ReadFcn',@(fn) VideoReader(fn));
myVideo = readall(fds);
% 出力先の1つの動画をVideoWriterで作成
vw = VideoWriter('videoMerge.avi');
open(vw)
while hasFrame(myVideo{1})
% 動画ごとのフレーム画像を格納
myFrame = cellfun(@readFrame, myVideo, 'UniformOutput', false);
% 5行✕20列の結合した動画を作成する
imM = cell2mat(reshape(myFrame, 5, 20));
% 結合したフレームを動画に出力
writeVideo(vw, imM)
end
% VideoWriterとVideoReaderを消去
close(vw)
clear myVideo

3 Comments

Kojiro Saito
Kojiro Saito on 12 Feb 2024
@Atsushi Uenoさん、追加の回答ありがとうございます。
私もdatastoreでfor文無しで考えましたが、動画の順番をコントロールするところにコツが要りますよね。
まず、fds.Filesの順番ではtest01.avi、test02.avi、…test09.avi、test10.avi、test100.avi、test11.avi…という順番になってしまうため、数字の並びとASCIIの並びに不一致が生じてしまいます。
上記のコードを実行すると5✕20の動画は作れますが、このように順番がおかしくなってしまいます。
対応策としてファイルの文字列を渡してdatastoreを作ればよいのですが、 
fnames=compose('test%02d.avi',1:100).';
fds = fileDatastore(fnames,'ReadFcn',@(fn) VideoReader(fn));
動画の向きがこちらの回答のように
1,2,3,… 20
21,22,…40
81,82,…100
にはならずに
1,6,11,…96
2,7,12,…97
5,10,15,…100
となってしまいます。
実行例↓
今回のご質問では100個の動画の並び順までは分からなかったですが質問者様の方で並び順を変更できるように、コードはきれいではないですが私はfor文で回答しました。
Atsushi Ueno
Atsushi Ueno on 12 Feb 2024
🤔 mmm... 'xylophone.mp4' を並べて動作確認してたので、重要な事に気付きませんでした。
しかしながら、個々の課題は下記の方法で解消できます。
  • ファイル名の並び:ご提案の compose 関数や有志による natsortfiles 関数でOK(類似質問)
  • 並べる方向の変更:reshape(myFrame, 5, 20)⇒reshape(myFrame, 20, 5)' でOK
  • for文の方が読み易い:むしろ信者は for 文の無い方が読み易いと考えます(続く)
(続き)これは正に「MATLABで for 文使ったら負け教」のメインテーマ「MATLABを布教し、MATLABのあらゆる機能に通じたMATLABネイティブ信者を増やす」事につながるのです。下記は我々が日々の修行で連呼している決意文です。
MF負け教の決意文:MATLABで for 文は甘え!数あるデータ構造とメソッドで for 文を消し去れ!結局ループ処理が回ってても良い!読めないなんて言わせない!MATLABで for 文使ったら負け!
Atsushi Ueno
Atsushi Ueno on 16 Feb 2024

Sign in to comment.

Products

Release

R2022b

Asked:

non
on 5 Feb 2024

Commented:

on 16 Feb 2024

Community Treasure Hunt

Find the treasures in MATLAB Central and discover how the community can help you!

Start Hunting!