
JavaFX多媒體(3)Metadata與Marker
JavaFX多媒體(2)使用Media播放音訊與影像 << 前情 接著上一篇JavaFX多媒體(2)介紹基本的JavaFX Media概念,本篇將說明多媒體的Metadata與Marker。 Metadata原意為Data about Data,中文直譯為有關資料的資料或描述資料的資料,國內學者對於Metadata有不同的譯名,常見的有元資料、詮釋資料、超資料等,中央研究院數位典藏與數位學習國家型科技計畫則譯為後設資料,特此說明。請參考以下網址之說明:Metadata。 在多媒體中,Metadata是指內嵌於音訊與影像檔案中的標籤 (Tag) 資料,常見的標籤與JavaFX所支援的媒體格式如下所示。 音訊類型,適用於MP3媒體格式:
影像類型,適用於FLV與FXM媒體格式:
欲處理Metadata,可使用Media類別的getMetadata()方法取得。由於媒體常會改變,特別是專輯中各音軌的Metadata資料均不同,因此在實作上,會將上述以getMetadata()方法所取得的Metadata資料,再以addListener()方法處理其改變事件,一旦資料改變時,再重新取得相關Metadata資料。 此外,須注意的是JavaFX目前支援取得Metadata資料的媒體格式分別為MP3音訊、FLV影像與FXM影像等,其餘尚未支援。 請參考以下範例,首先以Media類別的getMetadata()方法取得音訊檔案中的Metadata資料,接著以addListener()方法處理其改變事件,在事件中分別判斷各Metadata標籤資料是否改變,藉此更新其內容: media.getMetadata().addListener( new MapChangeListener<String, Object>() { @Override public void onChanged( MapChangeListener.Change<? extends String, ? extends Object> change) { if (change.wasAdded()) { String key = change.getKey(); Object value = change.getValueAdded(); if (key.equals("album")) { lblAlbum.setText("Album: " + value.toString()); } else if (key.equals("artist")) { lblArtist.setText("Artist: " + value.toString()); } else if (key.equals("composer")) { lblComposer.setText("Composer: " + value.toString()); } else if (key.equals("duration")) { lblDurations.setText("Duration: " + value.toString()); } else if (key.equals("genre")) { lblGenre.setText("Genre: " + value.toString()); } else if (key.equals("title")) { lblTitle.setText("Title: " + value.toString()); } else if (key.equals("year")) { lblYear.setText("Year: " + value.toString()); } else if (key.equals("image")) { imgCover.setImage((Image)value); } } } }); 此外,範例建立一分頁窗格顯示音訊檔案的Metadata資料: private BorderPane createMetadataPane() { lblAlbum = new Label(); lblAlbum.setText("N/A"); lblArtist = new Label(); lblArtist.setText("N/A"); lblComposer = new Label(); lblComposer.setText("N/A"); lblDurations = new Label(); lblDurations.setText("N/A"); lblGenre = new Label(); lblGenre.setText("N/A"); lblTitle = new Label(); lblTitle.setText("N/A"); lblYear = new Label(); lblYear.setText("N/A"); imgCover = new ImageView(); imgCover.setImage(new Image( getClass().getResourceAsStream("images/album.png"))); Reflection reflection = new Reflection(); reflection.setFraction(0.6); imgCover.setFitWidth(150); imgCover.setPreserveRatio(true); imgCover.setSmooth(true); imgCover.setEffect(reflection); GridPane gridpane = new GridPane(); gridpane.setPadding(new Insets(10)); gridpane.setHgap(20); gridpane.add(imgCover, 0, 0, 1, GridPane.REMAINING); gridpane.add(lblTitle, 1, 0); gridpane.add(lblAlbum, 1, 1); gridpane.add(lblArtist, 1, 2); gridpane.add(lblComposer, 1, 3); gridpane.add(lblGenre, 1, 4); gridpane.add(lblYear, 1, 5); gridpane.add(lblDurations, 1, 6); ColumnConstraints column1 = new ColumnConstraints(); ColumnConstraints column2 = new ColumnConstraints(); column2.setHgrow(Priority.ALWAYS); gridpane.getColumnConstraints().addAll(column1, column2); RowConstraints row1 = new RowConstraints(); row1.setValignment(VPos.TOP); gridpane.getRowConstraints().addAll( row1, row1, row1, row1, row1, row1, row1); BorderPane borderpane = new BorderPane(); borderpane.setLeft(gridpane); return borderpane; } 【執行結果】 請參考以下範例處理影像媒體的Metadata資料,程式與上述範例幾乎一樣,只是兩者所處理的Metadata標籤資料不同而已。此外,影像媒體並沒有image的Metadata標籤,但為與上述範例一致,因此亦加入圖像。須注意的是JavaFX僅支援FLV與FXM影像。 【執行結果】 接著說明Marker。 標記 (Marker) 是針對媒體額外附加文字說明,類似於字幕,雖然音訊與影像均可以加入標記,但由於音訊並無影像,因此在實作上僅針對影像處理。 欲處理標記,可使用Media類別的getMarkers()方法,getMarkers()方法回傳ObservableMap介面物件,其內容由字串與時間所組成,代表在特定「時間」處理指定的「標記字串」。其內容可由ObservableMap介面的put()方法依序加入。待標記處理完成之後,再以MediaPlayer類別的setOnMarker()方法處理。 請參考以下範例,示範在影像中附加標記字串。首先以Media類別的getMarkers()方法回傳ObservableMap介面物件,並以put()方法依序加入標記字串與時間: final ObservableMap<String, Duration> markers = media.getMarkers(); markers.put("Marker 1", Duration.millis(3000)); markers.put("Marker 2", Duration.millis(6000)); markers.put("Marker 3", Duration.millis(9000)); markers.put("Marker 4", Duration.millis(12000)); markers.put("Marker 5", Duration.millis(15000)); 接著以MediaPlayer類別的setOnMarker()方法處理標記字串: final Label lblMarker = new Label(); lblMarker.setFont(Font.font("Verdana", 12)); lblMarker.setTextFill(Color.WHITE); StackPane.setAlignment(lblMarker, Pos.CENTER); mediaplayer.setOnMarker(new EventHandler() { @Override public void handle(final MediaMarkerEvent e) { Platform.runLater(new Runnable() { @Override public void run() { lblMarker.setText(e.getMarker().getKey()); } }); } }); ... StackPane stackpane = new StackPane(); stackpane.getChildren().addAll(borderpane, lblMarker); // Set the Layout Pane of Scene Scene scene = new Scene(stackpane); 【執行結果】 【參考資料】 [1] Java Official Web Site
|