ソフトウェア開発部、粕谷(@daiksy)です。
今回は音声ファイルの操作についてのお話です。
我々のチームでは、ソーシャルゲームのサーバサイドの開発・運用を行っています。
昨今のソーシャルゲームは、アニメーションや音声の再生など、一昔前に比べて表現がずいぶんリッチになっています。
そのような流れの中で、我々のチームでも音声ファイルの操作について検証をはじめました。
別にどのような技術を用いても良かったのですが、我々のチームでは、ゲームのサーバサイドのシステムをPlay + Scalaで構築しており、どうせならScalaから音声ファイルを操作しようと思いました。
やりたいことは、
- wav -> mp3 などの形式変換
- 音声ファイルのサイズ(再生秒数)の取得
- 複数の音声ファイルの結合
の3要件です。
我々が扱っているScalaは、JVMで動作する言語であり、Javaの豊富なライブラリを使用することができます。
そういったライブラリ群を用いれば、音声ファイルの操作は行えるでしょうが、今回はそれらを使わずにSoXというツールをScalaから呼び出すことで要件を実現することにしました。
理由は、SoXは基本的にコマンドラインで音声ファイルを操作するツールなので、Scalaからこれらのコマンドを呼び出せば、Javaのライブラリを使うよりも楽に要件が実現できそうだったからです。
まとめると、システム構成は以下のようになります。
まず、最初の手順としては、SoXをCentOSにインストールする必要があります。
インストールは実に簡単で、wgetで最新版をとってきて解凍し、makeするだけです。
cd /usr/src
wget http://sourceforge.net/projects/sox/files/sox/14.4.1/sox-14.4.1.tar.gz
tar zxvf sox-14.4.1.tar.gz
cd sox-14.4.1
./configure
make all
make install
これだけで、SoXは使えるようになるはずです。しかし、CentOSを扱っている場合は注意が必要です。
./configure
を実行すると、SoXの設定状態が一覧表示されます。この時点での設定状態を見てみましょう。
注目すべきはこの部分です。
mp2/mp3....................no
id3tag....................no
lame......................no
lame id3tag...............no
dlopen lame...............no
mad.......................no
dlopen mad................no
twolame...................no
ご覧のように、mp3がサポートされていません。
今回、我々はmp3のファイルを扱う必要があるのですが、CentOSはデフォルトではmp3を扱えないのです。 そこで、mp3を扱うために必要なライブラリを入れましょう。
こちらのサイトを参考にしました。
rpm -Uhv http://apt.sw.be/redhat/el5/en/i386/rpmforge/RPMS/rpmforge-release-0.3.6-1.el5.rf.i386.rpm
yum install lame
yum install libmad
yum install libid3tag
rpm -Uvh http://download1.rpmfusion.org/free/el/updates/6/x86_64/rpmfusion-free-release-6-1.noarch.rpm
yum install madplay
yum install gcc-c++ libmad libmad-devel libid3tag libid3tag-devel lame lame-devel flac-devel libvorbis-devel
再度、SoXをmakeします。
./configure make all make install
これで、SoXの状態が下記になっていれば準備完了です。
mp2/mp3....................yes
id3tag....................yes
lame......................yes
lame id3tag...............yes
dlopen lame...............no
mad.......................yes
dlopen mad................no
twolame...................no
サーバでSoXさえ動くようになれば、Scalaからこれを呼び出すのは容易です。
ScalaからOSのコマンドを叩くには scala.sys.process
を使います。
これは非常に強力で、import scala.sys.process._
とimportすると、Scalaの暗黙の型変換(implicit conversion)によってStringにプロセスを実行するメソッドが拡張されます。
例えば、
val ret = "ls -l" !!
を実行してやると、変数ret
にls -l
コマンドの実行結果が格納されます。
詳しくは、こちらをご参照ください。
この scala.sys.process
と、Scala2.10のString Interpolationを組み合わせることで、可読性も非常に高くSoXコマンドを扱うことができます。
それぞれのコード例を見てみましょう。
例1) wav -> mp3 の形式変換
val sox = "/usr/local/bin/sox"
val beforeFile = "/hoge/before.wav"
val afterFile = "/hoge/before.mp3"
s"$sox $beforeFile $afterFile" !
例2) 音声ファイルのサイズ取得
val sox = "/usr/local/bin/sox"
val targetFile = "/hoge/target.mp3"
val ret = s"$sox --i -D $targetFile" !!
例3) 複数の音声ファイルの結合
val sox = "/usr/local/bin/sox"
val beforeFileA = "/hoge/a.mp3"
val beforeFileB = "/hoge/b.mp3"
val afterFile = "/hoge/after.mp3"
s"$sox $beforeFileA $beforeFileB $afterFile" !
非常に簡単ですね!!