Java Media Framework の使い方と動画・音声再生サンプル
リソース を resouce と書いているのに気づいた.resource のつもりだったのに.
Java で 動画・音声を扱う手段として,公式的には JMF(Java Media Framework)が用意されている.公式の説明書を読むとかサンプルコードを読むとかが王道だろうが,面倒だった.イケてる日本語文献が見つかったから使ってみる.
本エントリでは情報元,インストール方法,やったことを記述した.
情報
インストール
Sun から jmf-2_1_1e-windows-i586.exe を入手して実行する.Javadoc はないみたい.
NetBeans を使用している場合は不要かもしれないが,インストールしてしまったから確認が面倒だ.
教科書 JMFyy.pdf
習作目標「AVI ファイルを読み込み,全フレームをどこかのフォルダに PNG 形式で出力する」を設定した.
ひとまず教科書どおりのコードを書く.NetBeans で Java ファイルを作り,「ファイルを実行」していく.どれもこれも,ウインドウの閉じるボタンをクリックしてもプロセスが走りっぱなしだったから,IDE 右下の running... のバツボタンをクリックする手間がある.
mp3play.java
音声を再生する.教科書どおりの q.mp3 が手元になくて,Help - MP3 Search & Free Mp3 Downloads から拾った.しかし聴いていて気分が悪いから,C:\WINDOWS\Media のファイルを使用した.
- Windows XP Startup.wav
- Windows XP Shutdown.wav を ffmpeg -i "Windows XP Shutdown.wav" "Windows XP Shutdown.mp3" したもの
- onestop.mid
package test; import java.io.File; import java.io.IOException; import java.net.MalformedURLException; import java.net.URL; import java.util.logging.Level; import java.util.logging.Logger; import javax.media.CannotRealizeException; import javax.media.Manager; import javax.media.NoPlayerException; import javax.media.Player; public class mp3play { public static void main(String[] args) { try { // File file = new File("resouce/Windows XP Shutdown.mp3"); // File file = new File("resouce/Windows XP Startup.wav"); File file = new File("resouce/onestop.mid"); URL url = file.toURL(); Player player = Manager.createRealizedPlayer(url); player.start(); } catch (MalformedURLException ex) { Logger.getLogger(mp3play.class.getName()).log(Level.SEVERE, null, ex); } catch (IOException ex) { Logger.getLogger(mp3play.class.getName()).log(Level.SEVERE, null, ex); } catch (NoPlayerException ex) { Logger.getLogger(mp3play.class.getName()).log(Level.SEVERE, null, ex); } catch (CannotRealizeException ex) { Logger.getLogger(mp3play.class.getName()).log(Level.SEVERE, null, ex); } } }
MIDI ファイルは再生できなかった.
Error: Unable to prefetch com.sun.media.content.audio.midi.Handler$MidiController@197d257
mp3play_control.java
mp3play に GUI を取り付けたもの.ウインドウが出現し再生ボタン,シークバー,ファイル情報表示ボタンが表示される.ウインドウが青いバーしかなく,コントロールはマウスでぐいーんとサイズ変更しないと表示されない.
package test; import java.awt.Component; import java.io.File; import java.io.IOException; import java.net.MalformedURLException; import java.net.URL; import java.util.logging.Level; import java.util.logging.Logger; import javax.media.CannotRealizeException; import javax.media.Manager; import javax.media.NoPlayerException; import javax.media.Player; import javax.swing.JFrame; public class mp3play_control extends JFrame { public static void main(String[] args) { JFrame frame = new JFrame(); try { File file = new File("resouce/Windows XP Shutdown.mp3"); // File file = new File("resouce/Windows XP Startup.wav"); // File file = new File("resouce/onestop.mid"); URL url = file.toURL(); Player player = Manager.createRealizedPlayer(url); Component cp = player.getControlPanelComponent(); frame.getContentPane().add(cp); frame.setVisible(true); player.start(); } catch (MalformedURLException ex) { Logger.getLogger(mp3play_control.class.getName()).log(Level.SEVERE, null, ex); } catch (IOException ex) { Logger.getLogger(mp3play_control.class.getName()).log(Level.SEVERE, null, ex); } catch (NoPlayerException ex) { Logger.getLogger(mp3play_control.class.getName()).log(Level.SEVERE, null, ex); } catch (CannotRealizeException ex) { Logger.getLogger(mp3play_control.class.getName()).log(Level.SEVERE, null, ex); } } }
videoplay.java
mp3play_control の動画版.動画を3種類だけ入力してみた.
- スーパーメトロイドのボムジャンプを収録した bombjump.avi 3IV2 256x224 60.00fps 1327Kbps
- 何度かの野球の投球シーン 0001.avi DivX 5 720x480 29.97fps 1043Kbps
- エンコードされていない動画ファイル 256x256 5.00fps 7864Kbps
package test; import java.awt.Component; import java.io.File; import java.io.IOException; import java.net.MalformedURLException; import java.net.URL; import java.util.logging.Level; import java.util.logging.Logger; import javax.media.CannotRealizeException; import javax.media.Manager; import javax.media.NoPlayerException; import javax.media.Player; import javax.swing.JFrame; public class videoplay { public static void main(String[] args) { try { JFrame frame = new JFrame(); File file = new File("resouce/bombjump.avi"); // 3IV2 256x224 60.00fps 1327Kbps // File file = new File("resouce/0001.avi"); // DivX 5 720x480 29.97fps 1043Kbps // File file = new File("resouce/90frame.avi"); // エンコードなし 256x256 5.00fps 7864Kbps URL url = file.toURL(); Player player = Manager.createRealizedPlayer(url); Component vc = player.getVisualComponent(); frame.getContentPane().add(vc, "Center"); Component cp = player.getControlPanelComponent(); frame.getContentPane().add(cp, "South"); frame.pack(); frame.setVisible((true)); player.start(); } catch (MalformedURLException ex) { Logger.getLogger(videoplay.class.getName()).log(Level.SEVERE, null, ex); } catch (IOException ex) { Logger.getLogger(videoplay.class.getName()).log(Level.SEVERE, null, ex); } catch (NoPlayerException ex) { Logger.getLogger(videoplay.class.getName()).log(Level.SEVERE, null, ex); } catch (CannotRealizeException ex) { Logger.getLogger(videoplay.class.getName()).log(Level.SEVERE, null, ex); } } }
1と2がダメだった.
run: Unable to handle format: 3IV2, 256x224, FrameRate=59.9, Length=172032 1068 extra bytes Exception in thread "main" java.lang.NullPointerException at java.awt.Container.addImpl(Container.java:1041) at java.awt.Container.add(Container.java:927) at test.videoplay.main(videoplay.java:31) 構築停止 (合計時間: 5 秒)
run: Unable to handle format: DX50, 720x480, FrameRate=29.9, Length=1036800 0 extra bytes Unable to handle format: mpeglayer3, 22050.0 Hz, 0-bit, Stereo, Unsigned, 12000.0 frame rate, FrameSize=8 bits Failed to realize: com.sun.media.PlaybackEngine@1372a1a Error: Unable to realize com.sun.media.PlaybackEngine@1372a1a 2009/07/13 22:48:18 test.videoplay main 致命的: null javax.media.CannotRealizeException at javax.media.Manager.blockingCall(Manager.java:2005) at javax.media.Manager.createRealizedPlayer(Manager.java:528) at test.videoplay.main(videoplay.java:29) 構築成功 (合計時間: 2 秒)
出力内容には温度差があるなあ.
device.java
JMF はデータ入力にはファイルだけでなく,カメラやマイクも利用できる.各デバイスを使用するにはその識別名が必要で,まずはこちらを取得してみようね,という内容だ.
package test; import java.util.Vector; import javax.media.CaptureDeviceInfo; import javax.media.CaptureDeviceManager; import javax.media.MediaLocator; import javax.media.format.AudioFormat; import javax.media.format.VideoFormat; public class device { public static void main(String[] args) { Vector vlist = CaptureDeviceManager.getDeviceList( new VideoFormat(VideoFormat.YUV)); for (int i = 0; i < vlist.size(); i++) { CaptureDeviceInfo vinfo = (CaptureDeviceInfo) vlist.elementAt(i); MediaLocator camera = vinfo.getLocator(); System.out.println(camera.toString()); } Vector alist = CaptureDeviceManager.getDeviceList( new AudioFormat(AudioFormat.LINEAR)); for (int i = 0; i < alist.size(); i++) { CaptureDeviceInfo ainfo = (CaptureDeviceInfo) alist.elementAt(i); MediaLocator mic = ainfo.getLocator(); System.out.println(mic.toString()); } } }
run: dsound:// javasound://44100 構築成功 (合計時間: 0 秒)
カメラなんて接続していないから,こんなものだろう.安い USB カメラでも接続したら増えるかな.