しかたないので、AACを別録音する その8 マージ作業の自動化、何とかなりそう
職場で廻っていたメールが(もちろんtypoですが) 「~ですの。」 になっていたので、つい「なんで、『白井黒子』がこんなところにいるんだ…」とまぜっかえしたら、 「それはだれ?」と突っ込まれてしまい、『レールガン』とかの話をするはめに。( 来年年男の中年としては、ちとハズカシイ。笑) それはともかく、「マージ作業」の自動化はなんとかなりました。 必要なものは、ext_bs.exe,faad.exe,tsMuxeR.exeです。ext_bs.exeはここで、faad.exeはここ(FAAD2v2.7 for Win32)で、tsMuxeR.exeはここから。faad -i <AACファイル名> とすると、C:\>faad -i [映]「28週後…_WOWOW1_05_11_2009_03_09_02.wav.aac *********** Ahead Software MPEG-4 AAC Decoder V2.7 ****************** Build: May 13 2009 Copyright 2002-2004: Ahead Software AG http://www.audiocoding.com Floating point version This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License. **************************************************************************[映]「28週後…」_WOWOW1_05_11_2009_03_09_02.wav.aac file info:ADTS, 6024.768 sec, 320 kbps, 48000 Hzのように、AAC形式のオーディオ・ファイルの長さが表示されます。そこで、TS形式のビデオから、tsMuxeRでAAC形式の2ch音声を抽出し、 AAC形式のファイルを作り、同じ様にfaadで長さの情報を抽出します。この二つの長さの差分から、マージの際の遅延を計算し、最終的にtsMuxeRでマージ します。データの流れとしては図のようになります。 手作業で、毎回これをやるのは面倒くさいので、Rubyのスクリプトを作りました。最後にソースコードは載せます。使い方は、コマンドプロンプトから、 ruby -wKs XX.ts [YY.wav] とします。XX.tsはHD PVRで作ったtsファイル、YY.wavは同時に録ったWaveファイルです。Waveファイルを省略した場合は、XX.tsの拡張子を.wavにした ファイルを仮定します。出力ファイル名は、「ss入力ファイル名.ts」になります。中間ファイルは今のところn入力ファイルと同じディレクトリに作りますが、コマン ド終了時に消去しないので、作業後に自分で消去してください。2時間程度のHDのファイルでも作業は、我が家の環境(鈍足5400rpmのHDD)で 10分以内に終わります。いくらH264とはいえ、HDのビデオファイルは大きいので、作業時間は主にHDDの性能に依存します。中間ファイルを作成する (物理)ドライブを別にしたり、ビデオ系の処理と、オーディオ系の処理を同時に処理(マルチプロセス化)すれば、もっと高速になるでしょうが、しばらくこ のままで問題がないか見てから改良することにします。 ちょっと苦労したのは、tsMuxeRの使い方です。GUIから使うのは直感的にわかりやすいのですが、コマンドライン版はよくわかりません。実際の動作 としては、GUIは.metaファイルというパラメータを書いたファイルを作成して、コマンドライン版をバックグラウンドで呼び出しているだけのようです が、コマンドライン版のReadmeファイルが、ロシア語版しかない。 orz しかたないので、GUI版で作業中に、コマンドプロンプトで、「wmic process」とか実行してどうやって呼び出しているか、「盗み見」してみたりして…(笑)#ruby -wKs ##maac51.rb# (c) 2009 BO# Usage : ruby -wKs maac51.rb <XX.ts> [YY.wav]## History# 2009/11/11 1st beta## tested on ruby 1.8.7 (2009-06-12 patchlevel 174) [i386-mswin32]#def readinfofile( fname ) reg = /^ADTS, *(\d*\.?\d*) ?sec/ open( fname ) {|file| while l = file.gets if reg =~ l return $1.to_f end end } return 0.0end # def readinfofile( fname )def pinfo( str ) puts "#### #{$0} #{str}\n"end # def pinfo( str )def filecheck( path) if ! File.exist?( path ) pinfo( "Error. '#{path}' was not created/found. Abort..\n" ) exit(1) end # ifend # def filecheck( path)def systemandcheck( cmd ) if ! system( cmd ) pinfo( "Error. Subcommand '#{cmd}' seemed to fail. Abort..\n" ) exit(1) endend # def systemandcheck( cmd )####main##puts ARGV[0]puts ARGV[1]# input filesfn = Hash.newif ! ARGV[0] puts "Error. No input files specified. Abort.." exit 1 end # iffn[:ts] = File::expand_path( ARGV[0] )if ! ARGV[1] # No wave input files specified dname , fname = File::split( fn[:ts] ) bname = File.basename( fname, ".ts" ) fn[:wav] = "#{dname}/#{bname}.wav" pinfo( "No wave input files specified. assuming '#{fn[:wav]}'" )else fn[:wav] = File::expand_path( ARGV[1] )end # if# output filedname , fname = File::split( fn[:ts] )fn[:outts] = "#{dname}/ss#{fname}" fn[:outtsmeta] = "#{fn[:outts]}.meta"#intermediate filedname , fname = File::split( fn[:ts] )bname = File.basename( fname, ".ts" )fn[:tsaac] = "#{dname}/#{bname}.track_4352.aac"fn[:tsaacmeta] = "#{fn[:tsaac]}.meta"fn[:tsaacinfo] = "#{fn[:tsaac]}.info"fn[:_6chaac] = "#{fn[:wav]}.6ch.aac"fn[:_6chaacinfo] = "#{fn[:_6chaac]}.info"puts fn[:ts]puts fn[:wav]puts ""puts fn[:tsaac] puts fn[:tsaacmeta]puts fn[:tsaacinfo] puts "" puts fn[:_6chaac] puts fn[:_6chaacinfo] puts "" puts fn[:outts]puts fn[:outtsmeta]puts ""puts File.dirname(fn[:tsaac]) # exit(0)#default offsetdefalutOffset = -100.0 # in ms##main start#### video filepinfo("extract aac from ts file by tsMuxeR" )filecheck( fn[:ts] )# makeing meta file, note that file name in meta file must be with full pathopen( fn[:tsaacmeta] , "w") {|file| file.puts( "MUXOPT --no-pcr-on-video-pid --new-audio-pes --demux --vbr --vbv-len=500\n" ) file.puts( "A_AAC, \"#{fn[:ts]}\", timeshift=-99ms, track=4352\n" )}filecheck( fn[:tsaacmeta] )puts cmd ="tsMuxeR \"#{fn[:tsaacmeta]}\" \"#{File.dirname(fn[:tsaac])}\""systemandcheck( cmd )filecheck( fn[:tsaac] )puts "#### #{$0} make length info of the aac file by faad2"puts cmd ="faad -i \"#{fn[:tsaac]}\" 2> \"#{fn[:tsaacinfo]}\""systemandcheck( cmd )filecheck( fn[:tsaacinfo] )length_tsaac = readinfofile( fn[:tsaacinfo] )puts "ts(aac) length = #{length_tsaac.to_s} sec\n"#### audio filepinfo "extract aac from wave file by ext_bs"filecheck( fn[:wav] )puts cmd = "ext_bs \"#{fn[:wav]}\" \"#{fn[:_6chaac]}\""systemandcheck( cmd )pinfo "make length info of the aac file by faad2"filecheck( fn[:_6chaac] )puts cmd ="faad -i \"#{fn[:_6chaac]}\" 2> \"#{fn[:_6chaacinfo]}\""systemandcheck( cmd )filecheck( fn[:_6chaacinfo] )length_6chaac = readinfofile( fn[:_6chaacinfo] )puts "6ch aac length = #{length_6chaac.to_s} sec\n"offset = ((length_tsaac - length_6chaac ) * 1000.0 + defalutOffset).to_i # in mspinfo "offset is #{offset.to_s}"#### merge files# makeing meta file, note that file name in meta file must be with full pathopen( fn[:outtsmeta], "w") {|file| file.puts( "MUXOPT --no-pcr-on-video-pid --new-audio-pes --vbr --vbv-len=500") file.puts( "V_MPEG4/ISO/AVC, \"#{fn[:ts]}\", fps=29.970, insertSEI, contSPS, track=4113") file.puts( "A_AAC, \"#{fn[:_6chaac]}\", timeshift=#{offset.to_s}ms" )}filecheck( fn[:outtsmeta] )pinfo( "merge files by tsMuxeR" )puts cmd ="tsMuxeR \"#{fn[:outtsmeta]}\" \"#{fn[:outts]}\""systemandcheck( cmd )#EOF# vim:set ts=8 sts=2 sw=2 tw=0 expandtab: