2021/03/21

windows バッチファイルあるある

 windows バッチファイルあるある 

2021/03/21 TubeP

MMD-VR180 HOWTO用にBowlRollで配っているファイルの1つ 325-305-VR180-bat.bat を書くときに学んだwindows batファイルあるあるネタです。うp主はWindowsの人ではないので、結構難儀しました。誰の役に立つのやら。


Tips 誤作動除け


作業時に間違えてbatchファイルをダブルクリックしたり、他のファイルをドロップしたりすると実行が始まって慌てることがあります。うp主は不注意なのでよくやっちゃいます。そういう方は、最初(とか面倒くさい処理が始まる前のところ)に、

echo Starting encoding, wait for 10 sec to start.
timeout /T 10

というのを挿入しておくと10秒待ってくれるので、その間に停止処理できるようになります。


Tips ウィンドウ表示の維持


batファイルを実行すると、通常は全て終わったら実行ウィンドウは片づけられちゃいます。そういうのが寂しい人向け。

cmd /k

を最後に入れておけば、表示が残ります。
上の10秒待ちと組み合わせるとこんな感じ。



Tips 行の接続


1行が長くなると読みくくなるので、折り返したくなりますよね?
そういうときは折り返す行の最後に"^"を置くそうです。
特にffmpegの引数は延々と書くことになるので、これ大事。


Tips 一部区間をまるまる飛ばす


今回の一番の魔法です。

(

というカッコ一文字だけの行と

)|echo "スクリプト中の ( から ) までを跳ばしました." 

という行でバッチファイルの一部を挟むと、その部分の実行をしなくなります。そんな馬鹿な、と思うかもしれません。私もそう思います。
でもね、挟まれた部分にどこでもいいから1回でも rem 文があると本当にスキップするのです。誰かすっきりした解説してください‥

この技法(トリック?)を使うと削除しなくて済むので、特にデバッグ時には便利。

echo文の後ろは自分で適宜書き換えましょう。
例えば、これを使って、VR135生成部分をコメントアウトしたりできます。
ただし可読性が猛烈に悪いので、一時的な作業にしかお勧めできませんねぇ。
これについてはにわかには信じがたいと思うので、別途実例をまとめてみました


Tips 変数


変数のセットにはSET命令、というところは容易に想像つきましたが、変数の参照時には変数名の前「後」に%を付けるというのがなかなか。特に後ろにつけるというのはうp主には新鮮過ぎました。じゃあ%0%じゃないのか、とか突っ込みたくなる。


Tips 変数操作


他のスクリプト言語でもそうですけど、変数に対する条件付代入って気合入りすぎてて謎です。解説する気ありませんが、下記の2行で、「バッチファイル自身のファイル名の先頭7文字」をMOVIENAME変数に代入しています。

set FNAME=%~n0
set MOVIENAME=%FNAME:~0,7%

% (パーセント) - DOS コマンド一覧


Tips 遅延環境変数


今回はカッコ "(" の中で変数代入をしない(ように実は書き直した)ので出てきませんが、遅延環境変数にもヤラレました。わかってしまえばどうということないんだけど、ほかのスクリプト言語からするとあり得ない仕様なのでびっくり。それぐらい古くからあるということなのでしょうかね。

【BAT】IF文やFOR文の括弧内で変更した変数の値を取得する方法
Use parentheses/brackets to group expressions in a Windows batch file.


記述例


以下が実際に MMD-VR180 HOWTO用に書いた 325-305-VR180-bat.bat です。MMD-VR180 HOWTOとして使う際には、実際には更新されている可能性があるので、利用時はこれをコピペするのではなく、BowlRollから最新版をDLしてください。

https://bowlroll.net/file/249559


@echo off

rem Post process of assembling AVI files into VR180 mp4
rem 2021/03/08 TubeP
rem 6K (6144 x 3072), 5K (5760 x 2880), 4K (4096 x 2048), 2K (2048 x 1024) 
rem -- Input 
rem xxx-yyy: major version xxx and minor version yyy (taken from first seven letters of this file)
rem rrrr ... resolution (taken from xxx-yyy_L0.avi)
rem -- Output
rem xxx-yyy_LRM-rrrr.mp4 ... Main target
rem xxx-yyy_LRM-4096.mp4 ... Sub target1 (produced only when rrrr > 4096)
rem xxx-yyy_LRM-4096micro.mp4 ... Sub target2 (just for iwara.tv, < 300MB)

rem ffmpegとffprobeをインストール先に合わせる
set FFMBIN=X:\ffmpeg\bin\ffmpeg
set FFMPRB=X:\ffmpeg\bin\ffprobe
rem ワーキングフォルダに移動
Y:
cd Y:\tmp-work

rem --------------------------------------------------
rem ここから先は変更不要

echo Starting the process (wait 10 sec)
echo %0
timeout /T 10

rem コマンド名の最初7文字が映像名のprefixになる。(自動代入)
set FNAME=%~n0
set MOVIENAME=%FNAME:~0,7%

rem 解像度自動抽出 (%MOVIENAME%_L0.avi の垂直方向画素数)
rem video height => RSLF (ReSoLution Fullsize of a square image)
for /f %%i in ('%FFMPRB% -v error -i %MOVIENAME%_L0.avi -select_streams v:0 -show_entries stream^=height -of csv^=p^=0') do set RSLF=%%i

rem 秒数自動抽出 (%MOVIENAME%_L0.avi の秒数)
rem video duration => DURT
for /f %%i in ('%FFMPRB% -v error -i %MOVIENAME%_L0.avi -select_streams v:0 -show_entries stream^=duration -of csv^=p^=0') do set DURT=%%i

rem 位置決め(x2 double, x0.5 half)       6K   / 5K   / 4K   / 2K
rem RSLF should be one side of the square 3072 / 2880 / 2048 / 1024 
rem RSLD should be double of RSLF, means  6144 / 5760 / 4096 / 2048
rem RSLH should be half   of RSLF, means  1536 / 1440 / 1024 /  512
if        %RSLF%==3072 (
         set RSLD=6144
         set RSLH=1536
) else if %RSLF%==2880 (
         set RSLD=5760
         set RSLH=1440
) else if %RSLF%==2048 (
         set RSLD=4096
         set RSLH=1024
) else if %RSLF%==1024 (
         set RSLD=2048
         set RSLH=512
) else (
  echo 映像(正方形)の解像度設定ミスです。
  echo 検査対象:%MOVIENAME%_L0.avi
  echo サイズが %RSLF% になっています。
  echo 受け付けるのは 3072 / 2880 / 2048 / 1080 のみ。
  cmd /k echo finished on error ...
)

echo RSLDは %RSLD% です。
echo RSLFは %RSLF% です。
echo RSLHは %RSLH% です。
echo 映像L0の秒数は %DURT% です。

echo Starting encoding (wait 10 sec)
timeout /T 10

rem 処理を飛ばすためのコード
rem 開始時:
rem (
rem 終了時:
rem )|echo "スクリプト中の ( から ) までを跳ばしました."
rem timeout /T 5


echo " ---- VR135 test run ----"

rem  Test of Stereo view (testL0 testR0)
%FFMBIN% -y ^
-i "%MOVIENAME%_testL0.avi" ^
-i "%MOVIENAME%_testR0.avi" ^
-filter_complex "[1]pad=%RSLD%:%RSLF%:%RSLF%:0[right];[right][0]overlay=shortest=1" ^
-r 60 -vcodec h264 -b:v 30M %MOVIENAME%_testLR0-%RSLD%.mp4

rem  with Music
rem  to make it short, "-to 0:00:07" (for 7 sec), otherwise length = music.wav
%FFMBIN% -y ^
-i %MOVIENAME%_testLR0-%RSLD%.mp4 ^
-i music.wav ^
-map 0:0 -map 1:0 -vcodec copy ^
-to 0:00:%DURT% ^
%MOVIENAME%_testLR0M-%RSLD%.mp4

rem for DEO VR (upper limit 4096)
if %RSLD% gtr 4096 (
  %FFMBIN% -y ^
  -i %MOVIENAME%_testLR0M-%RSLD%.mp4 ^
  -vf scale=4096:-1 ^
  %MOVIENAME%_testLR0M-4096.mp4
)



echo " ---- VR135 full ----"

rem  VR135 of Stereo view (L0 R0)
%FFMBIN% -y ^
-i "%MOVIENAME%_L0.avi" ^
-i "%MOVIENAME%_R0.avi" ^
-filter_complex "[1]pad=%RSLD%:%RSLF%:%RSLF%:0[right];[right][0]overlay=shortest=1" ^
-r 60 -vcodec h264 -b:v 30M %MOVIENAME%_LR0-%RSLD%.mp4

rem  with Music
%FFMBIN% -y ^
-i %MOVIENAME%_LR0-%RSLD%.mp4 ^
-i music.wav ^
-map 0:0 -map 1:0 -vcodec copy ^
%MOVIENAME%_LR0M-%RSLD%.mp4

rem for DEO VR (upper limit 4096)
if %RSLD% gtr 4096 (
  %FFMBIN% -y ^
  -i %MOVIENAME%_LR0M-%RSLD%.mp4 ^
  -acodec copy ^
  -vf scale=4096:-1 ^
  -b:v 8000k ^
  %MOVIENAME%_LR0M-4096micro.mp4
) else (
  %FFMBIN% -y ^
  -i %MOVIENAME%_LR0M-%RSLD%.mp4 ^
  -acodec copy ^
  -b:v 8000k ^
     %MOVIENAME%_LR0M-%RSLD%micro.mp4
)


rem ウィンドウを残すためのおまじない。
rem date /t
rem time /t
rem cmd /k echo "testLR0 and LR0 / VR135 finished..."



echo " ---- Left Eye ----"

rem  L1-L2 左目 左・右
%FFMBIN% -y ^
-i %MOVIENAME%_L1.avi ^
-i %MOVIENAME%_L2.avi ^
-filter_complex "[0]crop=%RSLH%:%RSLF%:0:0[left];[1][left]overlay=shortest=1" ^
-r 60 -vcodec utvideo zzL12-.avi

rem  L3-L4 左目 上・下
%FFMBIN% -y ^
-i "%MOVIENAME%_L3.avi" ^
-i "%MOVIENAME%_L4.avi" ^
-filter_complex "[0]crop=%RSLF%:%RSLH%:0:0[top];[1][top]overlay=shortest=1" ^
-r 60 -vcodec utvideo zzL34-.avi

rem  L12-L34 左目 左右・上下
%FFMBIN% -y ^
-i "zzL12-.avi" ^
-i "zzL34-.avi" ^
-i "mask135deg-HorVer_%RSLF%.png" ^
-filter_complex "[0:v]format=rgba,lutrgb[zz12];[1:v]format=rgba,lutrgb[zz34];[zz34][zz12][2]maskedmerge" ^
-r 60 -vsync 1 -vcodec utvideo zzL1234-.avi

rem  L1234-L0 左目 正面
%FFMBIN% -y ^
-i "%MOVIENAME%_L0.avi" ^
-i "zzL1234-.avi" ^
-i "mask135deg-Center_%RSLF%.png" ^
-filter_complex "[0:v]format=rgba,lutrgb[Center];[1:v]format=rgba,lutrgb[Skirt];[Center][Skirt][2]maskedmerge" ^
-r 60 -vsync 1 -vcodec utvideo %MOVIENAME%_Lm.avi



echo " ---- Right Eye ----"

rem  R1-R2 右目 左・右
%FFMBIN% -y ^
-i "%MOVIENAME%_R1.avi" ^
-i "%MOVIENAME%_R2.avi" ^
-filter_complex "[0]crop=%RSLH%:%RSLF%:0:0[left];[1][left]overlay=shortest=1" ^
-r 60 -vcodec utvideo zzR12-.avi

rem  R3-R4 右目 上・下
%FFMBIN% -y ^
-i "%MOVIENAME%_R3.avi" ^
-i "%MOVIENAME%_R4.avi" ^
-filter_complex "[0]crop=%RSLF%:%RSLH%:0:0[top];[1][top]overlay=shortest=1" ^
-r 60 -vcodec utvideo zzR34-.avi

rem  R12-R34 右目 左右・上下
%FFMBIN% -y ^
-i "zzR12-.avi" ^
-i "zzR34-.avi" ^
-i "mask135deg-HorVer_%RSLF%.png" ^
-filter_complex "[0:v]format=rgba,lutrgb[zz12];[1:v]format=rgba,lutrgb[zz34];[zz34][zz12][2]maskedmerge" ^
-r 60 -vsync 1 -vcodec utvideo zzR1234-.avi

rem  R1234-R0 右目 正面
%FFMBIN% -y ^
-i "%MOVIENAME%_R0.avi" ^
-i "zzR1234-.avi" ^
-i "mask135deg-Center_%RSLF%.png" ^
-filter_complex "[0:v]format=rgba,lutrgb[Center];[1:v]format=rgba,lutrgb[Skirt];[Center][Skirt][2]maskedmerge" ^
-r 60 -vsync 1 -vcodec utvideo %MOVIENAME%_Rm.avi



echo " ---- Binding L and R ----"

rem  Stereo view (Lm Rm)
%FFMBIN% -y ^
-i "%MOVIENAME%_Lm.avi" ^
-i "%MOVIENAME%_Rm.avi" ^
-filter_complex "[1]pad=%RSLD%:%RSLF%:%RSLF%:0[right];[right][0]overlay=shortest=1" ^
-r 60 -vcodec h264 -b:v 30M %MOVIENAME%_LR-%RSLD%.mp4

rem  with Music
%FFMBIN% -y ^
-i %MOVIENAME%_LR-%RSLD%.mp4 ^
-i music.wav ^
-map 0:0 -map 1:0 -vcodec copy ^
%MOVIENAME%_LRM-%RSLD%.mp4


rem for DEO VR (upper limit 4096)
if %RSLD% gtr 4096 (
  %FFMBIN% -y ^
  -i %MOVIENAME%_LRM-%RSLD%.mp4 ^
  -vf scale=4096:-1 ^
  -acodec copy ^
  %MOVIENAME%_LRM-4096.mp4
  %FFMBIN% -y ^
  -i %MOVIENAME%_LRM-%RSLD%.mp4 ^
  -vf scale=4096:-1 ^
  -acodec copy ^
  -b:v 8000k ^
  %MOVIENAME%_LRM-4096micro.mp4
) else (
  %FFMBIN% -y ^
  -i %MOVIENAME%_LRM-%RSLD%.mp4 ^
  -acodec copy ^
  -b:v 8000k ^
  %MOVIENAME%_LRM-%RSLD%micro.mp4
)


rem ウィンドウを残すためのおまじない。
date /t
time /t
cmd /k echo finished...

rem ------------------------------------------------------------
rem Thanks to the useful links 

rem https://qiita.com/Marukaziler/items/686cfa0e6564fb7ce69d

rem https://www.pg-fl.jp/program/dos/doscmd/str_percent.htm
rem Use first 7 letters for prefix (MOVIENAME).

rem https://nico-lab.net/how_to_use_ffprobe/
rem ffprobe to get info.

rem https://qiita.com/long_long_float/items/f1a19816ef0d0070b68f

rem Windows batでコマンドの結果を変数に格納
rem FOR /F %%i in ('コマンド') do set 変数=%%i
rem http://tugi.hatenablog.com/entry/2014/09/18/204239
rem Escape is made by "^"




0 件のコメント:

コメントを投稿