原文引自:
http://www-128.ibm.com/developerworks/cn/java/wi-mvideo/最新一代的 iPod 媒體播放器在移動視頻編程領域開辟了一個新機會 —— 但是如何入門呢?本文介紹將 QuickTime for Java? 庫,以編程方式為 iPod 媒體播放器創建視頻內容時需要這個庫。
Apple iPod 是當今市場上的幾個媒體播放器之一,它能播放多種媒體,其中包括音頻、視頻和圖片。在美國和其他地方,iPod 引領著便攜媒體播放器市場,從誕生至今,已經售出 3千萬套 iPod ,這占據了整個媒體播放器市場 78% 以上的份額。雖然 iPod 的成功顯然是受 MP3 流行的推動,而且手機用戶拍攝和交易數字圖片到現在也有了一段時間,但移動視頻的市場仍然在形成中。早期進入移動視頻市場的潛在收益是顯而易見的,但對許多開發人員來說,他們要解決的問題是最好地應用這項新技術的方式和地方。
在這篇文章中,我首先將推薦一些移動視頻的實際(可能也是非常流行的)應用,然后演示兩個程序,讓您開始使用 QuickTime for Java API 為 iPod 創建視頻內容。這兩個程序可以讓您很容易地給現有的視頻文件添加標題,并將傳統的視頻文件轉換成與 iPod 兼容的格式。在文章末尾,將留給您一些示例代碼,可以用它們學習使用 QuickTime for Java API 進行視頻操作的更多內容。
為什么要用移動視頻?
圖 1. iPod 視頻播放器
便攜媒體播放器在特定人群(即年齡在 18 到 38 歲之間,具有一定的可支配收入的消費者)中特別流行。因為移動視頻對于便攜媒體播放器來是相對較新的東西,所以對大多數開發者來說,遇到的第一個問題就是: 為什么要創建移動視頻內容?除了移動媒體最明顯的娛樂要求之外,還有許多實際的使用情況:移動媒體既可以促進銷售,也可以給便攜媒體播放器和內容帶來一類新用戶。請想想以下這些情況:
- 房地產經紀人可以創建一段視頻,將視頻做成房產可用屬性和用錄制好的配音說明的一些功能的虛擬漫步。然后,潛在的住房買主可能會用便攜媒體播放器查看中意的屬性。在沒有時間尋找所有符合自己需求的房產的住宅搜索客戶中,這種極為節約時間的方式會變得非常流行。
- 汽車廠商和經銷商可以使用移動視頻發布所銷售的最新車型的視頻目錄。潛在客戶就會更熟悉中意的車型的特性和好處,而不必親自去經銷商那里。
- 學院和大學的官員可以用移動視頻格式向學生提供提供演講,輔助學生學習。
- 生產商可以為汽車、書架、玩具(等等)提供移動視頻格式的安裝說明。
顯然,這只是創建移動視頻內容的商業驅動力的幾個示例。這些示例中的共同之處就是向新市場介紹便攜媒體的潛力。現在,我們來看看允許用編程方式創建和編輯視頻文件的 Java API。
QuickTime for Java API
對于 Java 開發人員來說,支持數字媒體的創建、修改和回放的能力最強、功能最豐富的 API 就是 QuickTime for Java API。QuickTime for Java 最初是為 Macintosh 平臺創建的,但過去這幾年時間里,Windows 和 Mac 用戶也可以隨意使用它。當然,如果曾經用 Java 語言做過一些編程,那么您可能會問:為什么不可以只使用 Java 媒體框架 (JMF) API。
最初創建 JMF 是為了給 Java V1.0.2 的開發人員提供處理各種媒體的能力。但是,它的應用并不廣,它支持一些過時的媒體格式和編碼方式,例如 MPEG-2、AU、HotMedia 和 Flash 2。另一方面,QuickTime for Java 支持 QuickTime 可以播放的所有媒體格式和編碼方式。使用 QuickTime for Java API 可以訪問更新的媒體格式,其中包括 MPEG-4、MP3 音頻、H.264 和 Flash 5。實際上,下面就是 QuickTime 支持的視頻編碼方式的完整列表:
- 動畫
- Apple BMP
- Apple Pixlet
- Apple Video
- Cinepak
- Component video
- DV and DVC Pro NTSC
- DV PAL
- DVC Pro PAL
- Graphics
- H.261
- H.263
- H.264
- JPEG 2000
- Microsoft? OLE
- Microsoft Video 1
- Motion JPEG A
- Motion JPEG B
- MPEG-4 (Part 2)
- Photo JPEG
- Planar RGB
- PNG
- Sorenson Video 2
- Sorenson Video 3
- TGA
- TIFF
向視頻添加標題
如果是初次接觸 QuickTime for Java API 或者是初次處理數字媒體,那么向視頻片斷添加標題是一個好的起點。清單 1 顯示的 CaptionAdder.java
是一個簡單的程序,它接受視頻文件,然后向視頻添加一個文本字符串作為標題。
清單 1. CaptionAdder.javaimport quicktime.*;
import quicktime.io.*;
import quicktime.std.image.*;
import quicktime.std.movies.media.*;
import quicktime.std.movies.*;
import quicktime.std.*;
import quicktime.qd.*;
import quicktime.util.QTPointer;
import java.io.*;
public class CaptionAdder {
public static void main (String args[]) {
if (args.length != 1){
System.out.println("Usage: java CaptionAdder [input_filename]");
} else {
try {
QTSession.open();
System.out.println ("QuickTime version: " + QTSession.getMajorVersion() + "." +
QTSession.getMinorVersion());
QTFile qtfile = new QTFile(new File(args[0]));
DataRef urlMovie = new DataRef ("file://" + qtfile.getPath());
Movie movie = Movie.fromDataRef (urlMovie,StdQTConstants.newMovieActive);
float textTrackHeight = 32;
QDRect movieBounds = movie.getNaturalBoundsRect();
float movieWidth = movieBounds.getWidthF();
float movieHeight = movieBounds.getHeightF();
Track textTrack = movie.addTrack(movieWidth, textTrackHeight, 0);
Matrix textTrackMatrix = textTrack.getMatrix();
textTrackMatrix.translate (0, movieHeight - textTrackHeight);
textTrack.setMatrix (textTrackMatrix);
textTrack.setEnabled (true);
int movieTimeScale = movie.getTimeScale();
TextMedia textMedia = new TextMedia (textTrack, movieTimeScale);
QDRect textBounds = new QDRect (movieWidth, movieHeight);
textMedia.beginEdits();
TimeInfo sampleTime = new TimeInfo (0, movie.getDuration()/2);
String text = new String ("1234 Main St. - Listing price: $164,000");
TextMediaHandler textMediaHandler = textMedia.getTextHandler();
QTPointer textPointer = new QTPointer ( text.length() + 1, true );
textPointer.copyFromArray ( 0, text.getBytes(), 0, text.length() );
textMediaHandler.addTextSample (
textPointer,
QDFont.getFNum("Times"),
16,
0,
QDColor.white,
QDColor.black,
QDConstants.teCenter,
textBounds,
StdQTConstants.dfClipToTextBox | StdQTConstants.dfKeyedText,
0,0,0,
null,
sampleTime.duration );
textMedia.endEdits();
textTrack.insertMedia (sampleTime.time, 0, sampleTime.duration, 1 );
OpenMovieFile outStream = OpenMovieFile.asWrite (qtfile);
movie.updateResource (outStream, StdQTConstants.movieInDataForkResID,
qtfile.getName());
} catch (Exception e) {
e.printStackTrace();
QTSession.close();
System.exit(0);
}
QTSession.close();
// end else
}
System.out.println ("complete.");
//end method
}
}
|
關于代碼
幾乎每個 QuickTime for Java 應用程序都一樣,所有的實際動作都發生在 QTSession.open()
和 QTSession.close()
語句之間。在調用 QTSession.open()
時,QuickTime 引擎可以初始化其自身。如果沒有先調用 QTSession.open()
,就想調用其他 QuickTime for Java 類,那么您會獲得拋出到命令行中的非常難看的堆棧跟蹤。
QuickTime for Java API 中使用的核心對象之一是 quicktime.std.movies.Movie
對象。如果初次使用 QuickTime for Java,那么需要認識到,在 quicktime.std.movies.Movie
對象和硬盤上可能存在的 file_name.mov
之間有一點細微的區別。重要的是,可以創建 quicktime.std.movies.Movie
對象,并且無需要在硬盤上創建 file_name.mov
文件該對象就可以存在。
quicktime.std.movies.Movie
對象可由多個軌道 組成,這些軌道是獨立的媒體源(例如音頻、視頻、靜態圖片或文本)。在 CaptionAdder.java()
中,在創建了 quicktime.std.movies.Track
對象后,我在 textMedia.beginEdits()
語句和 textMedia.endEdits()
語句之間添加了文本標題。在這個示例中,我用 quicktime.std.movies.TimeInfo
對象設置標題在視頻中顯示的時間長度,以及什么時候開始顯示標題。我想讓文本標題在視頻的前半段顯示,所以我把 TimeInfo
設為從 0 開始,并通過 movie 的持續時間將它設置為運行到一半時結束。
使用 CaptionAdder.java
那么該如何使用 CaptionAdder.java
呢?首先,調用 CaptionAdder.java
非常簡單直接。在向類路徑中添加了 QuickTime for Java 庫之后,需要做的就是提供想要編輯的文件的名稱。例如,假設想向 圖 2 所示的房地產清單視頻添加標題。
圖 2. 沒有標題的房地產視頻示例截圖
要向這個文件添加標題,只需如 清單 2 中所示那樣運行 CaptionAdder.java 程序即可。
清單 2. 使用 CaptionAdder.javajava CaptionAdder listing22345.mov
|
結果顯示在 圖 3 中。
圖 3. 添加了標題的房地產視頻示例
轉換成 iPod 格式
在有了使用 QuickTime for Java API 創建和操作視頻內容的基礎之后,下一個主要障礙就是把內容轉換成與 iPod 兼容的格式。不論使用攝像機、從活動視頻源錄制,還是創建動畫序列,視頻內容都不會立即與 iPod 視頻播放器兼容。iPod 對于它播放的媒體的類型有點挑剔。表 1 顯示了 iPod 環境支持的視頻格式和設置。
表 1. iPod 兼容內容的視頻設置 視頻格式 | 數據率 | 尺寸 | 幀率 |
H.264 視頻 | 最高 768 Kbps | 320 x 240 像素 | 30 fps |
MPEG-4 視頻 | 最高 2.5 Mbps | 480 x 480 像素 | 30 fps |
讓問題更復雜的是,對于視頻中的音軌,它只支持高級音頻編碼 (AAC),所以如果想在 iPod 上播放視頻,不僅僅要轉換傳統視頻內容。幸運的是,可以求助于 MovieConverter.java
,它是轉換傳統視頻內容到 iPod 兼容格式的一個方便工具。MovieConverter.java
如 清單 3 中所示。
清單 3. MovieConverter.javaimport java.awt.*;
import java.awt.event.*;
import javax.swing.*;
import java.io.IOException;
import quicktime.*;
import quicktime.io.*;
import quicktime.qd.*;
import quicktime.std.*;
import quicktime.std.clocks.*;
import quicktime.std.StdQTConstants;
import quicktime.std.image.*;
import quicktime.std.movies.*;
import quicktime.std.movies.media.*;
import quicktime.std.qtcomponents.*;
import quicktime.util.*;
import quicktime.app.view.*;
public class MovieConverter extends JFrame implements Errors, ActionListener{
QTComponent component = null;
JPanel jpanel = null;
Button selectButton = null;
public static void main (String args[]) {
try{
new MovieConverter();
} catch(Exception e){
System.out.println(e);
}
}
public MovieConverter(){
super("Movie Converter");
try {
QTSession.open();
} catch (Exception e) {
e.printStackTrace();
QTSession.close();
}
jpanel = new JPanel();
this.setContentPane(jpanel);
selectButton = new Button ("Select a File to Convert");
selectButton.addActionListener(this);
jpanel.add (selectButton);
addWindowListener(new WindowAdapter () {
public void windowClosing (WindowEvent e) {
QTSession.close();
dispose();
}
public void windowClosed (WindowEvent e) {
System.exit(0);
}
});
this.pack();
this.setVisible(true);
}
public void actionPerformed (ActionEvent event) {
exportMovie();
}
void displayMovie (Movie m) throws QTException {
component = QTFactory.makeQTComponent (new MovieController (m));
jpanel.add ((Component)component);
jpanel.remove(selectButton);
pack();
}
void exportMovie () {
try{
FileDialog fileDialog = new FileDialog (this,
"Choose Movie to Export...", FileDialog.LOAD);
fileDialog.show();
if (fileDialog.getFile() == null)
return;
QTFile movieFile = new QTFile (fileDialog.getDirectory()
+ fileDialog.getFile());
Movie movie = Movie.fromFile (OpenMovieFile.asRead(movieFile));
if (component != null) {
component.setMovieController(new MovieController(movie));
} else {
displayMovie (movie);
}
new Thread (new Exporter(movie)).start();
} catch (QTException err) {
err.printStackTrace();
}
}
}
|

 |

|
使用 MovieConverter.java
使用 MovieConverter.java
非常簡單。在 圖 4 中,可以看到一個關于如何使用 Internet 的虛擬學術培訓視頻的截屏(從 Google 的主頁開始)。實際的影片文件是 AVI 格式,并且還包括授課錄音的音軌。
圖 4. 示例學術培訓視頻的截屏
用 MovieConverter.java
程序將這個視頻文件轉換成 iPod 兼容的格式很容易。在啟動 MovieConverter.java
之后,首先選擇要轉換的文件。然后指定新創建的文件的名稱,如 圖 5 中所示。
圖 5. MovieConverter.java 請求新文件的名稱
在指定了新視頻文件的名稱之后,應用程序顯示一個影片設置總結屏幕,如 圖 6 中所示。在這個屏幕上,有修改編碼方式、壓縮算法的選項,甚至可以對媒體應用視頻過濾器。
圖 6. 影片設置總結
在 圖 7 中,可以看到 MovieConverter 的視頻設置窗口,在這個窗口中,可以選擇視頻編碼方式,而提供了轉換后的視頻預覽。
圖 7. 視頻設置窗口
設置好之后,MovieConverter 生成可以在 iPod 視頻播放器上播放的新視頻文件。還要注意的是,MovieConverter.java
是個功能豐富且強大的應用程序。不但可以用它生成能夠在 iPod 媒體播放器上播放的視頻內容,還能用它把傳統視頻轉換成 QuickTime 支持的其他視頻格式。
結束語
在數年之后,iPod 很有可能會領導便攜媒體播放器市場。目前這代 iPod 媒體播放器中添加了視頻內容,這開辟了許多令人興奮的營銷和商業機會。在這篇文章中,我提供了移動視頻內容的一些實際和商業上的應用,介紹了 QuickTime for Java API,并演示了如何用編程方式操縱移動視頻文件,并將它轉換成與視頻 iPod 兼容的格式。
參考資料
學習獲得產品和技術討論關于作者
 |

|  | Bruce Hopkins 是 Bluetooth for Java (Apress) 一書的作者,也是 JB-22 開發包的制作者。他畢業于底特律的 Wayne 州立大學,擁有電子和計算機工程的學士學位。他目前是 Gestalt LLC 的技術架構師,專攻分布式計算、Web 服務和無線技術。您可以通過他的郵箱 bhopkins@gestalt-llc.com 與他聯系。 |