EBU R128 / BS.1770-3:オーディオ/ビデオファイルボリュームのバッチ正規化、パート2

以前の投稿で、オーディオ/ビデオファイルのボリュームのバッチ正規化に関するアイデア概説しました。



このアイデアの実装をレイアウトする時が来ました。 このソリューションは、柔軟でスケーラブルであることが判明しました。



使用するには、サウンドとビデオの素材に関する知識、 SoXマニュアル-Sound eXchangeFFmpegBS1770GAIN 、および私のお気に入りのAutoItパッケージを用意する必要があります。



Windows Serverおよび他のいくつかのSmall Softプラットフォームでは、ffmpegバージョン3.1以前は動作しなくなりました。



実装は次のとおりです。



かなり単純なスクリプト(自動)は、セクションがリッスンされるフォルダーであるiniファイルをリッスンします。 各セクションは独自のワーカー(スクリプトインスタンス)を開き、メディアファイルを通過する前に構成を読み取ります。 セクションが削除されると、ワーカーは閉じます。 メインワーカーが閉じると、開いているワーカーはすべて閉じられます。



ワーカーの設定の形式は次のとおりです。



[\\host\path\] destination=\\host\path\ bak=\\host\path\ stmp=tmp\ tmp1=tmp\ tmp2=tmp\ otmp=tmp\ destinationExtension=.avi threads=16 prepare_ffmpeg_cmd=-flags +ilme+ildct -deinterlace -c:v copy -c:a copy ffmpeg_cmd=-flags +ilme+ildct -deinterlace -c:v copy -c:a copy sox_cmd=compand 0.1,0.3 -90,-90,-70,-55,-50,-35,-31,-31,-21,-21,0,-20 0 0 0.1
      
      





マニュアル:



マニュアルを読む

1)目的地



結果のファイルを保存する場所。

2)bak



ソースファイルを保存する場所。

ソースファイルはネットワークバスケットにあり、ファイルは同じバスケットの別のフォルダーにバックアップされます。

3)一時ディレクトリ



ビデオファイルを処理するマシンには、いくつかの物理メディアがあることが理解されています。

たとえば、ソースファイルは同じネットワークバスケットにあり、完成したファイルは2番目のネットワークバスケットにあり、3番目のマシンがそれを処理します。

3番目のマシンでは、一時ファイル用に3つのハードドライブをスタックしました。

stmp



 $sFile = $stmp & $tempFile & $sExtension
      
      





ネットワークバスケットからのファイルがhard0に到着します

tmp1



 $audioInputSox = $tmp1 & $tempFile & "_sox.wav" $audioOutput = $tmp1 & $tempFile & "_norm.wav"
      
      





構成に値sox_cmdが存在する場合、オーディオデータはhard2から読み込まれ、処理結果はhard1に書き込まれます

ボリュームが正規化されると、オーディオデータはhard2またはhard1から読み取られ( sox_cmd? )、hard1に書き込まれます

tmp2



 $audioInput = $tmp2 & $tempFile & ".wav"
      
      





ビデオファイルの元のオーディオストリームは、hard0からhard2に読み取られます。

otmp



 $outFile = $otmp & $tempFile & "_out" & $destinationExtension
      
      





完成したビデオファイルをアセンブルする場合、ビデオストリームはhard0( stmp )から読み取られ、オーディオストリームはhard1( tmp1 )から読み取られ、結果はhard2に書き込まれます

4)destinationExtension



結果ビデオコンテナ

5)スレッド



構成から得られるビデオファイルスレッド=(スレッド)のアセンブリのコマンドラインに書き込みます。

6)prepare_ffmpeg_cmd



空でない場合、

ffmpeg -y -ss 0:0:0.0 -r 25 -i [bak] [prepare_ffmpeg_cmd] [stmp]





それ以外の場合、ソースファイルはbakからstmpにコピーされます

7)ffmpeg_cmd



ファイル名が読み取られます。

ファイル名の最後に{HH MM SS mm ss}という形式の構造があり、HH MM SSフレームから始まる場合、ファイルの末尾は、オーディオトラックを歪めることなく加速/減速方法を使用してmm ssタイミングに短縮されます。

結果のファイルは、コマンドでアセンブルされます

ffmpeg -i [stmp(video)] -i [tmp1(normalized -23LUFS audio)] [ffmpeg_cmd] -map 0:v -map 1:a -threads [threads] [otmp] -y





sox_cmd



サウンドを正規化する前に、オーディオフィルターが適用されます

sox [tmp2] [tmp1] [sox_cmd]







ここで、実際には、全体の単純なスクリプト。 とても快適です。 彼は自分でパパを作成し、ファイル、プロセスを監視し、必要に応じてそれらを保存します。バグはほとんど発生せず、ほとんど発生しません。 記憶は食べず、尊厳をもって行動する)あなたの健康に使用してください!



スクリプトコードを読む
 #Region ;**** Directives created by AutoIt3Wrapper_GUI **** #AutoIt3Wrapper_Icon=C:\Program Files (x86)\AutoIt3\Icons\MyAutoIt3_Blue.ico #AutoIt3Wrapper_Compile_Both=y #AutoIt3Wrapper_UseX64=y #EndRegion ;**** Directives created by AutoIt3Wrapper_GUI **** #include <Array.au3> #include <File.au3> Func randomString($digits) Local $pwd = "" Local $aSpace[3] For $i = 1 To $digits $aSpace[0] = Chr(Random(65, 90, 1)) ;AZ $aSpace[1] = Chr(Random(97, 122, 1)) ;az $aSpace[2] = Chr(Random(48, 57, 1)) ;0-9 $pwd &= $aSpace[Random(0, 2, 1)] Next Return $pwd EndFunc $iniFile = "watch.ini" Dim $run[0][2] Dim $newRun[0] Func TerminateChilds() For $i = 0 to UBound($run) - 1 ProcessClose($run[$i][0]) Next EndFunc Local $source If $CmdLine[0] == 0 Then Local $i, $j, $exists, $pid OnAutoItExitRegister ( "TerminateChilds" ) While 1 $source = IniReadSectionNames($iniFile) For $i = 0 To UBound($run) - 1 $exists = False For $j = 1 To $source[0] If $source[$j] == $run[$i][1] Then $exists = True Next If Not $exists Then ProcessClose($run[$i][0]) _ArrayDelete($run, $i) ContinueLoop EndIf Next For $i = 1 To $source[0] $exists = False For $j = 0 To UBound($run) - 1 If $source[$i] == $run[$j][1] Then $exists = True Next If Not $exists Then $pid = Run(@ScriptName & " """ & $source[$i] & """") Dim $temp[1][2] = [[$pid, $source[$i]]] _ArrayAdd($run, $temp) ContinueLoop EndIf Next For $i = 0 To UBound($run) - 1 If ProcessExists($run[$i][0]) == 0 Then $pid = Run(@ScriptName & " """ & $run[$i][1] & """") $run[$i][0] = $pid ContinueLoop EndIf Next Sleep(1000) WEnd EndIf MsgBox($MB_SYSTEMMODAL, $CmdLine[1], "I am started " & @CRLF & $CmdLine[1], 10) Func Terminated() MsgBox($MB_SYSTEMMODAL, $CmdLine[1], "I am terminated " & @CRLF & $CmdLine[1], 10) EndFunc OnAutoItExitRegister ( "Terminated" ) TraySetToolTip($CmdLine[1]) $tools = "bs1770gain-tools\" Local $source = $CmdLine[1] Local $destination = IniRead($iniFile, $source, "destination", Null) Local $bak = IniRead($iniFile, $source, "bak", Null) Local $stmp = IniRead($iniFile, $source, "stmp", Null) Local $tmp1 = IniRead($iniFile, $source, "tmp1", Null) Local $tmp2 = IniRead($iniFile, $source, "tmp2", Null) Local $otmp = IniRead($iniFile, $source, "otmp", Null) Local $ffmpeg_cmd = IniRead($iniFile, $source, "ffmpeg_cmd", Null) Local $destinationExtension = IniRead($iniFile, $source, "destinationExtension", Null) Local $threads = IniRead($iniFile, $source, "threads", Null) Local $sox_cmd = IniRead($iniFile, $source, "sox_cmd", Null) If Not FileExists($source) Then DirCreate($source) If Not FileExists($bak) Then DirCreate($bak) If Not FileExists($destination) Then DirCreate($destination) If Not FileExists($stmp) Then DirCreate($stmp) If Not FileExists($tmp1) Then DirCreate($tmp1) If Not FileExists($tmp2) Then DirCreate($tmp2) If Not FileExists($otmp) Then DirCreate($otmp) Local $tempFile Local $sFile Local $descriptionFile Local $audioInput Local $audioOutput Local $outFile Local $sTitr Local $eTitr While 1 Local $files = _FileListToArray($source, "*", $FLTA_FILES, False) Local $i = 1 For $i = 1 To Ubound($files) - 1 Local $f = $files[$i] Local $sDrive = "", $sDir = "", $sFileName = "", $sExtension = "" Local $aPathSplit = _PathSplit($f, $sDrive, $sDir, $sFileName, $sExtension) Local $h = FileOpen($source & $sFileName & $sExtension, $FO_APPEND) If $h == -1 Then ContinueLoop FileClose($h) Sleep(50) Local $h = FileOpen($source & $sFileName & $sExtension, $FO_APPEND) If $h == -1 Then ContinueLoop FileClose($h) Sleep(50) Local $h = FileOpen($source & $sFileName & $sExtension, $FO_APPEND) If $h == -1 Then ContinueLoop FileClose($h) Sleep(50) Local $h = FileOpen($source & $sFileName & $sExtension, $FO_APPEND) If $h == -1 Then ContinueLoop FileClose($h) $bak = IniRead($iniFile, $source, "bak", Null) $destination = IniRead($iniFile, $source, "destination", Null) $stmp = IniRead($iniFile, $source, "stmp", Null) $tmp1 = IniRead($iniFile, $source, "tmp1", Null) $tmp2 = IniRead($iniFile, $source, "tmp2", Null) $otmp = IniRead($iniFile, $source, "otmp", Null) $ffmpeg_cmd = IniRead($iniFile, $source, "ffmpeg_cmd", Null) $destinationExtension = IniRead($iniFile, $source, "destinationExtension", Null) $threads = IniRead($iniFile, $source, "threads", Null) $sox_cmd = IniRead($iniFile, $source, "sox_cmd", Null) $pre_cmd = IniRead($iniFile, $source, "prepare_ffmpeg_cmd", Null) $tempFile = randomString(8) $bak &= $sFileName & $sExtension $sFile = $stmp & $tempFile & $sExtension $descriptionFile = $tmp1 & $tempFile & $sExtension & ".ini" $audioInput = $tmp2 & $tempFile & ".wav" $audioInputSox = $tmp1 & $tempFile & "_sox.wav" $audioOutput = $tmp1 & $tempFile & "_norm.wav" $outFile = $otmp & $tempFile & "_out" & $destinationExtension If FileMove($source & $sFileName & $sExtension, $bak, $FC_OVERWRITE) == 0 Then ContinueLoop If Not $pre_cmd Then If FileCopy($bak, $sFile, $FC_OVERWRITE) == 0 Then ContinueLoop Else $cmd_pre = $tools & "ffmpeg -y -ss 0:0:0.0 -r 25 -i """ & $bak & """ " & $pre_cmd & " " & $sFile RunWait($cmd_pre) EndIf Sleep(100) ;$log = FileOpen($tempFile & ".bat", $FO_OVERWRITE + $FO_UTF8 + $FO_CREATEPATH) $cmd_info = "cmd /c """ & $tools & "ffprobe -v quiet -print_format ini -show_format -show_streams " & $sFile & " > """ & $descriptionFile & """" ;FileWriteLine($log, $cmd_info) RunWait($cmd_info) $dur = Number(IniRead($descriptionFile, "streams.stream.0", "duration", Null)) $cmd_AudioInput = $tools & "ffmpeg -ss 0:0:0 -i " & $sFile & " -t " & $dur & " -vn -c:a pcm_s16le -af ""pan=stereo| FL < FL + 0.5*FC + 0.6*BL + 0.6*SL | FR < FR + 0.5*FC + 0.6*BR + 0.6*SR"" -ac 2 " & $audioInput & " -y -threads " & $threads ;FileWriteLine($log, $cmd_AudioInput) RunWait($cmd_AudioInput) Sleep(100) $audioOutput = "tmp\" & $tempFile & ".flac" If IsString($sox_cmd) And $sox_cmd <> "" Then $audioOutput = "tmp\" & $tempFile & "_sox.flac" $cmd_Sox = $tools & "sox " & $audioInput & " " & $audioInputSox & " " & $sox_cmd ;FileWriteLine($log, $cmd_Sox) RunWait($cmd_Sox) $audioInput = $audioInputSox EndIf $cmd_BS1770gain = "bs1770gain --ebu """ & $audioInput & """ -ao ""tmp""" ;FileWriteLine($log, $cmd_BS1770gain) RunWait($cmd_BS1770gain) Sleep(100) $a = StringRegExp($sFileName, "^.+{(\d{2}) (\d{2}) (\d{2}) (\d{2}) (\d{2})}$", $STR_REGEXPARRAYGLOBALMATCH) If @error Then $cmd_Output = $tools & "ffmpeg -i " & $sFile & " -i " & $audioOutput & " " & $ffmpeg_cmd & " -map 0:v -map 1:a -threads " & $threads & " " & $outFile & " -y" ;FileWriteLine($log, $cmd_Output) RunWait($cmd_Output) Else $titr_h = Number($a[0]) $titr_m = Number($a[1]) $titr_s = Number($a[2]) $dur_m = Number($a[3]) $dur_s = Number($a[4]) $dur = $dur - ($titr_h*60*60 + $titr_m*60 + $titr_s) $dstDur = $dur_m*60 + $dur_s $outDur = $titr_h*60*60 + $titr_m*60 + $titr_s + $dur_m*60 + $dur_s $speed = $dstDur / $dur $codec = IniRead($descriptionFile, "streams.stream.0", "codec_name", Null) $sTitr = $tmp1 & $tempFile & "_stitr" & $sExtension $eTitr = $tmp1 & $tempFile & "_etitr" & $sExtension $cmd_ETirt = $tools & "ffmpeg -y -ss " & $titr_h & ":" & $titr_m & ":" & $titr_s & " -i " & $sFile & " -filter:v ""setpts=" & $speed & "*PTS"" -t 00:" & $dur_m & ":" & $dur_s & " -c:v " & $codec & " -qscale:v 0 -flags +ilme+ildct -deinterlace -an " & $eTitr $cmd_STitr = $tools & "ffmpeg -y -ss 0:0:0 -i " & $sFile & " -t " & $titr_h & ":" & $titr_m & ":" & $titr_s & " -c:v copy -an " & $sTitr $cmd_Output = $tools & "ffmpeg -y -i concat:""" & $sTitr & "|" & $eTitr & """ -i " & $audioOutput & " -t " & $outDur & " " & $ffmpeg_cmd & " -map 0:v -map 1:a -threads " & $threads & " " & $outFile ;FileWriteLine($log, $cmd_ETirt) ;FileWriteLine($log, $cmd_STitr) ;FileWriteLine($log, $cmd_Output) RunWait($cmd_ETirt) RunWait($cmd_STitr) RunWait($cmd_Output) EndIf ;FileClose($log) FileMove($outFile, $destination & $sFileName & $destinationExtension, $FC_OVERWRITE) Sleep(100) FileDelete($sFile) FileDelete($descriptionFile) FileDelete($sTitr) FileDelete($eTitr) FileDelete($tmp2 & $tempFile & ".wav") FileDelete($tmp1 & $tempFile & "_sox.wav") FileDelete($tmp1 & $tempFile & "_norm.wav") FileDelete($audioOutput) ;Exit Next Sleep(1000) WEnd
      
      








All Articles