それなりにたいへんそうで勉強になるかと思い、ScalaでWebM形式の動画を再生するコードを書いてみた。やりたくなったから、やっただけなので特に有用性とかはないです。
WebMのデコーダを準備する
Javaで、WebM形式の動画を扱うには gstreamer-java が使える。
gstramer-java はネイティブのgstreamerを呼びだすのでインストールする。また、gstreamerがWebM形式の動画をデコードできるように、デコーダもインストールしておく。
WebMデコーダのインストール
WebMのデコーダ(libvpx)のソースコードをcloneしてビルド/インストール。
$ git clone git://review.webmproject.org/libvpx.git $ cd libvpx $ ./configure $ make $ sudo make install # とりあえず/usr/local にいれておく
gstreamerのインストール
MacPortsからインストール。GNOME系のライブラリ/各種コーデックに依存しているためか、とても時間がかかる。
$ sudo port install gstreamer gst-plugins-base gst-plugins-bad gst-plugins-good
Scalaでgstreamerを呼び出すコードを書く
gstreamer-javaのサンプルコードをScalaに翻訳する。
import java.io.File; import scala.swing._; import org.gstreamer.Gst; import org.gstreamer.State; import org.gstreamer.elements.PlayBin; import org.gstreamer.swing.VideoComponent; object VideoPlayer { def main(args : Array[String]) { val gstArgs = Gst.init("VideoPlayer", args) val playBin = new PlayBin("VideoPlayer") playBin.setInputFile(new File(gstArgs(0))) Swing.onEDT { val videoComponent = new VideoComponent; playBin.setVideoSink(videoComponent.getElement) val panel = new BorderPanel { add(Component.wrap(videoComponent), BorderPanel.Position.Center) } val frame = new MainFrame { title = "VideoPlayer" preferredSize = new Dimension(640, 480) contents = panel open } playBin.setState(State.PLAYING) } Gst.main playBin.setState(State.NULL) } }
もとのコードよりもSwingまわりはscalaっぽくなっていてきれいですね。newしながらコンストラクタ拡張しつつ初期化コードを走らせているのが Scalaっぽい? scala.swingの使い方がよくわかんなかったので適当です。
コンパイル
gstreamer-java-1.4.jarとjna.jarをダウンロードして適当なところにおいておく(うちはlibディレクトリを作っておいてる) 。あと、コンパイル時にはjnaにライブラリの場所を教えてあげる。あと、Scala2.8じゃないとうごかなさそうです。
$ scalac -Djna.library.path=/opt/local/lib/ -cp .:lib/gstreamer-java-1.4.jar:lib/jna.jar VideoPlayer.scala
実行
$ scala -Djna.library.path=/opt/local/lib/ -cp .:lib/gstreamer-java-1.4.jar:lib/jna.jar VideoPlayer ~/Desktop/k-on_op.webm
再生できました!!
WebM形式の動画は YouTube からとってくるのが便利ですね。
メモ
- Java系で動画再生とか大変そうに思っていたけどライブラリがそろっていて簡単。Scalaでも余裕でつかえる
- gstreamer/gstreamer-javaが汎用的に使えて便利 (WebMにもプラグインで対応)
- ただしネイティブにコンパイルされたライブラリに依存してる
- ScalaでJavaのライブラリを呼び出すコードを書くとあまりJavaとかわらなくなって、Scalaの書きやすさを享受できなくなる
- scala.swingではなくて、javax.swingを使うとだいぶJavaっぽくなってしまう (new Runnable() {} とかいるし)
- JavaのライブラリのScalaラッパが増えれば、もっとScalaが書きやすくなりそう
- Scalaのソースコード内のライブラリのコードはScalaの勉強するのにたいへんよい
- Scalaのソースコード内の src/swing とか
- Scalaの開発環境整えたいです
- import たいへん
- コンパイラがおそい
- クラスパスとかをコマンドラインで毎回渡すのがたいへん
今回のようにただ再生するだけだと、さすがにしょうもないので、今度は、Actorを使ってWebインターフェースからプレイヤーをコントロールとかやりたいですね。