0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

FFmpegで4つの動画を並べて再生する(遅延も修正)

Posted at

概要

FFmpegで、画面を上下左右4つに分割し、それぞれの場所で動画4つを同時に再生させ、1つの動画にするコマンドを記載します。

手順

4つの動画を同時に再生させ1つの動画に

単純に4つの動画を合体するコマンドを示します。

# 1つの動画の画面解像度
# Full HDの場合は以下になる(最終的に出来上がる動画はFull HD x 4 となる
cut_w=1920
cut_h=1080

input0='左上の動画ファイルパス.mp4'
input1='右上の動画ファイルパス.mp4'
input2='左下の動画ファイルパス.mp4'
input3='右下の動画ファイルパス.mp4'

ffmpeg -i "$input0" -i "$input1" -i "$input2" -i "$input3" \
  -filter_complex "\
  amix=inputs=4:duration=longest,loudnorm;\
  [0:v] setpts=PTS-STARTPTS, scale=${cut_w}x${cut_h} [upperleft];\
  [1:v] setpts=PTS-STARTPTS, scale=${cut_w}x${cut_h} [upperright];\
  [2:v] setpts=PTS-STARTPTS, scale=${cut_w}x${cut_h} [lowerleft];\
  [3:v] setpts=PTS-STARTPTS, scale=${cut_w}x${cut_h} [lowerright];\
  [upperleft]pad=2*iw:2*ih[v0];\
  [v0][upperright]overlay=w:0[v1];\
  [v1][lowerleft]overlay=0:h[v2];\
  [v2][lowerright]overlay=w:h;\
  " \
  -b:v 2M -c:v libx264 \
  -c:a libopus -b:a 64k \
  output.mp4

以下に各行の詳細を示す。

  • ffmpeg -i "$input0" -i "$input1" -i "$input2" -i "$input3"
    • 動画4本をそれぞれ取込む
  • -filter_complex "\
    • -filter_complexオプションと呼ばれる設定をし、以降にそれぞれのストリームを定義
  • amix=inputs=4:duration=longest,loudnorm;\
    • オーディオストリーム4つをすべてまとめて音量調整し、1つのストリームにする
  • [0:v] setpts=PTS-STARTPTS, scale=${cut_w}x${cut_h} [upperleft];\
    • input0の映像ストリームを抜き出して[upperleft]ストリームとして定義
  • [1:v] setpts=PTS-STARTPTS, scale=${cut_w}x${cut_h} [upperright];\
    • input1の映像ストリームを抜き出して[upperright]ストリームとして定義
  • [2:v] setpts=PTS-STARTPTS, scale=${cut_w}x${cut_h} [lowerleft];\
    • input2の映像ストリームを抜き出して[lowerleft]ストリームとして定義
  • [3:v] setpts=PTS-STARTPTS, scale=${cut_w}x${cut_h} [lowerright];\
    • input3の映像ストリームを抜き出して[lowerright]ストリームとして定義
  • [upperleft]pad=2*iw:2*ih[v0];\
    • [upperleft]ストリーム(input0)を左上に配置する。width、heightそれぞれに2倍の余白を付ける
  • [v0][upperright]overlay=w:0[v1];\
    • 先ほどのストリームに[upperright]ストリーム(input1)を右上に重ねる
  • [v1][lowerleft]overlay=0:h[v2];\
    • 先ほどのストリームに[lowerleft]ストリーム(input2)を左下に重ねる
  • [v2][lowerright]overlay=w:h;\
    • 先ほどのストリームに[lowerright]ストリーム(input3)を右下に重ねる
  • -b:v 2M -c:v libx264 \
    • 適当な映像エンコード設定
  • -c:a libopus -b:a 64k \
    • 適当な音声エンコード設定
  • output.mp4
    • 出力ファイル名

4つの動画の開始時間がバラバラな場合(先頭を削除して合わせる)

4つの動画の開始位置がバラバラな場合、それぞれの動画の先頭を削除(trim)して合わせます。以下の遅延が発生しているとします。

  • input1: input0に対し、1秒開始が遅れている
  • input2: input0に対し、2秒開始が遅れている
  • input3: input0に対し、3秒開始が遅れている

この場合、一番遅れているinput3の動画に合わせ、それぞれの動画の先頭を以下のように削除(trim)すればよさそうです。

  • input0: 3秒先頭を削除する
  • input1: 2秒先頭を削除する(3秒-1秒)
  • input2: 1秒先頭を削除する(3秒-2秒)
  • input3: そのまま

遅延をtrimによって解消し、連結するコマンドを示します。

# 1つの動画の画面解像度
cut_w=1920
cut_h=1080

input0='左上の動画ファイルパス.mp4'
input1='右上の動画ファイルパス.mp4'
input2='左下の動画ファイルパス.mp4'
input3='右下の動画ファイルパス.mp4'

# それぞれの動画input0~3の先頭を削除する秒数を設定
trim0=3.000
trim1=2.000
trim2=1.000
trim3=0

ffmpeg -i "$input0"  -i "$input1"  -i "$input2"  -i "$input3" \
	-filter_complex "\
	[0:v] trim=start=${trim0}, setpts=PTS-STARTPTS, scale=${cut_w}x${cut_h} [upperleft];\
	[0:a] atrim=start=${trim0},asetpts=PTS-STARTPTS,loudnorm=I=-16:TP=-1.5:LRA=11 [a0];\
	[1:v] trim=start=${trim1}, setpts=PTS-STARTPTS, scale=${cut_w}x${cut_h} [upperright];\
	[1:a] atrim=start=${trim1},asetpts=PTS-STARTPTS,loudnorm=I=-16:TP=-1.5:LRA=11 [a1];\
	[2:v] trim=start=${trim2}, setpts=PTS-STARTPTS, scale=${cut_w}x${cut_h} [lowerleft];\
	[2:a] atrim=start=${trim2},asetpts=PTS-STARTPTS,loudnorm=I=-16:TP=-1.5:LRA=11 [a2];\
	[3:v] trim=start=${trim3}, setpts=PTS-STARTPTS, scale=${cut_w}x${cut_h} [lowerright];\
	[3:a] atrim=start=${trim3},asetpts=PTS-STARTPTS,loudnorm=I=-16:TP=-1.5:LRA=11 [a3];\
	[upperleft]pad=2*iw:2*ih[v0];\
	[v0][upperright]overlay=w:0[v1];\
	[v1][lowerleft]overlay=0:h[v2];\
	[v2][lowerright]overlay=w:h[v];\
	[a0][a1][a2][a3]amix=inputs=4:duration=longest,loudnorm[a];\
	" \
	-b:v 2M -c:v hevc_nvenc \
	-c:a libopus -b:a 32k \
	-map "[v]" -map "[a]" \
	output.mp4
  • ffmpeg -i "$input0" -i "$input1" -i "$input2" -i "$input3"
    • 動画4本をそれぞれ取込む
  • -filter_complex "\
    • -filter_complexオプションと呼ばれる設定をし、以降にそれぞれのストリームを定義
  • [0:v] trim=start=${trim0}, setpts=PTS-STARTPTS, scale=${cut_w}x${cut_h} [upperleft];\
    • input0の映像ストリームを抜き出し、$trim0秒先頭を削除し[upperleft]ストリームとして定義
  • [0:a] atrim=start=${trim0},asetpts=PTS-STARTPTS,loudnorm=I=-16:TP=-1.5:LRA=11 [a0];\
    • input0の音声ストリームを抜き出し、$trim0秒先頭を削除し[a0]ストリームとして定義
  • [1:v] trim=start=${trim1}, setpts=PTS-STARTPTS, scale=${cut_w}x${cut_h} [upperright];\
    • input1の映像ストリームを抜き出し、$trim1秒先頭を削除し[upperright]ストリームとして定義
  • [1:a] atrim=start=${trim1},asetpts=PTS-STARTPTS,loudnorm=I=-16:TP=-1.5:LRA=11 [a1];\
    • input1の音声ストリームを抜き出し、$trim1秒先頭を削除し[a1]ストリームとして定義
  • [2:v] trim=start=${trim2}, setpts=PTS-STARTPTS, scale=${cut_w}x${cut_h} [lowerleft];\
    • input2の映像ストリームを抜き出し、$trim2秒先頭を削除し[lowerleft]ストリームとして定義
  • [2:a] atrim=start=${trim2},asetpts=PTS-STARTPTS,loudnorm=I=-16:TP=-1.5:LRA=11 [a2];\
    • input2の音声ストリームを抜き出し、$trim2秒先頭を削除し[a2]ストリームとして定義
  • [3:v] trim=start=${trim3}, setpts=PTS-STARTPTS, scale=${cut_w}x${cut_h} [lowerright];\
    • input3の映像ストリームを抜き出し、$trim3秒先頭を削除し[lowerright]ストリームとして定義
  • [3:a] atrim=start=${trim3},asetpts=PTS-STARTPTS,loudnorm=I=-16:TP=-1.5:LRA=11 [a3];\
    • input3の音声ストリームを抜き出し、$trim3秒先頭を削除し[a3]ストリームとして定義
  • [upperleft]pad=2*iw:2*ih[v0];\
    • [upperleft]ストリーム(input0)を左上に配置し、width、heightそれぞれに2倍の余白を付ける
  • [v0][upperright]overlay=w:0[v1];\
    • 先ほどのストリームに[upperright]ストリーム(input1)を右上に重ねる
  • [v1][lowerleft]overlay=0:h[v2];\
    • 先ほどのストリームに[lowerleft]ストリーム(input2)を左下に重ねる
  • [v2][lowerright]overlay=w:h[v];\
    • 先ほどのストリームに[lowerright]ストリーム(input3)を右下に重ねる。これを最終的なストリーム[v]と定義
  • [a0][a1][a2][a3]amix=inputs=4:duration=longest,loudnorm[a];\
    • オーディオストリーム4つをすべてまとめて音量調整し、1つのストリームにする。これを最終的なストリーム[a]と定義
  • -b:v 2M -c:v hevc_nvenc \
    • 適当な映像エンコード設定
  • -c:a libopus -b:a 32k \
    • 適当な音声エンコード設定
  • -map "[v]" -map "[a]" \
    • ストリーム[v][a]を動画ファイルとして保存
  • output.mp4
    • 出力ファイル名

左右の音量バランス調整

Panningして、左上・左下の動画は左から、右上・右下の動画は右から音が鳴るようにします。

# 1つの動画の画面解像度
cut_w=1920
cut_h=1080

input0='左上の動画ファイルパス.mp4'
input1='右上の動画ファイルパス.mp4'
input2='左下の動画ファイルパス.mp4'
input3='右下の動画ファイルパス.mp4'

# それぞれの動画input0~3の先頭を削除する秒数を設定
trim0=3.000
trim1=2.000
trim2=1.000
trim3=0

# 0.0~1.0 の間で指定。0に近づけば左右の音分離が強くなります
pan_gap=0.3

ffmpeg -i "$input0"  -i "$input1"  -i "$input2"  -i "$input3" \
	-filter_complex "\
	[0:v] trim=start=${trim0}, setpts=PTS-STARTPTS, scale=${cut_w}x${cut_h} [upperleft];\
	[0:a] atrim=start=${trim0},asetpts=PTS-STARTPTS,loudnorm=I=-16:TP=-1.5:LRA=11,pan=stereo|c0=c0|c1=${pan_gap}*c1 [a0];\
	[1:v] trim=start=${trim1}, setpts=PTS-STARTPTS, scale=${cut_w}x${cut_h} [upperright];\
	[1:a] atrim=start=${trim1},asetpts=PTS-STARTPTS,loudnorm=I=-16:TP=-1.5:LRA=11,pan=stereo|c0=${pan_gap}*c0|c1=c1 [a1];\
	[2:v] trim=start=${trim2}, setpts=PTS-STARTPTS, scale=${cut_w}x${cut_h} [lowerleft];\
	[2:a] atrim=start=${trim2},asetpts=PTS-STARTPTS,loudnorm=I=-16:TP=-1.5:LRA=11,pan=stereo|c0=c0|c1=${pan_gap}*c1 [a2];\
	[3:v] trim=start=${trim3}, setpts=PTS-STARTPTS, scale=${cut_w}x${cut_h} [lowerright];\
	[3:a] atrim=start=${trim3},asetpts=PTS-STARTPTS,loudnorm=I=-16:TP=-1.5:LRA=11,pan=stereo|c0=${pan_gap}*c0|c1=c1 [a3];\
	[upperleft]pad=2*iw:2*ih[v0];\
	[v0][upperright]overlay=w:0[v1];\
	[v1][lowerleft]overlay=0:h[v2];\
	[v2][lowerright]overlay=w:h[v];\
	[a0][a1][a2][a3]amix=inputs=4:duration=longest,loudnorm[a];\
	" \
	-b:v 2M -c:v hevc_nvenc \
	-c:a libopus -b:a 32k \
	-map "[v]" -map "[a]" \
	output.mp4

前節との違いは、[0:a][1:a][2:a][3:a]のストリームの個所です。

  • [0:a] ... ,pan=stereo|c0=c0|c1=${pan_gap}*c1 [a0];\
    • (左上の動画の音声)左をそのまま、右を${pan_gap}
  • [1:a] ... ,pan=stereo|c0=${pan_gap}*c0|c1=c1 [a1];\
    • (右上の動画の音声)左を${pan_gap}倍、右をそのまま
  • [2:a] ... ,pan=stereo|c0=c0|c1=${pan_gap}*c1 [a2];\
    • (左下の動画の音声)左をそのまま、右を${pan_gap}
  • [3:a] ... ,pan=stereo|c0=${pan_gap}*c0|c1=c1 [a3];\
    • (右下の動画の音声)左を${pan_gap}倍、右をそのまま
0
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?