Dies Aliquanti

スポンサーサイト

上記の広告は1ヶ月以上更新のないブログに表示されています。
新しい記事を書く事で広告が消せます。

しかたないので、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でマージ します。データの流れとしては図のようになります。

maac51

手作業で、毎回これをやるのは面倒くさいので、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.0
end # 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 # if
end # def filecheck( path)

def systemandcheck( cmd )
  if ! system( cmd )
    pinfo( "Error. Subcommand '#{cmd}' seemed to fail. Abort..\n" )
    exit(1)
  end
end # def systemandcheck( cmd )
##
##main
##
puts ARGV[0]
puts ARGV[1]

# input files
fn = Hash.new
if ! ARGV[0]
  puts "Error. No input files specified. Abort.."
  exit 1
end # if
fn[: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 file
dname , fname = File::split( fn[:ts] )
fn[:outts] = "#{dname}/ss#{fname}"
fn[:outtsmeta] = "#{fn[:outts]}.meta"

#intermediate file
dname , 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 offset
defalutOffset = -100.0 # in ms

##main start
#### video file
pinfo("extract aac from ts file by tsMuxeR" )

filecheck( fn[:ts] )
# makeing meta file, note that file name in meta file must be with full path
open( 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 file
pinfo "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 ms
pinfo "offset is #{offset.to_s}"

#### merge files
# makeing meta file, note that file name in meta file must be with full path
open( 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:



コメント

コメントの投稿


管理者にだけ表示を許可する

トラックバック

トラックバック URL
http://diesaliquanti.blog.fc2.com/tb.php/731-9fcfa716
この記事にトラックバックする(FC2ブログユーザー)

FC2Ad

まとめ

上記広告は1ヶ月以上更新のないブログに表示されています。新しい記事を書くことで広告を消せます。