JavaFX中不支持MP4吗?

问题描述 投票:5回答:1

所以我最近开始使用JavaFX尝试将视频和音频插入到我的java程序中。音频工作得很好,但由于某些原因我每次尝试播放视频文件时都会返回MEDIA_UNSUPPORTED异常。我已经阅读并看到视频文件需要是MP4(它是),所以我尝试将其转换为其他类型,然后使用几个不同的转换器将其重新转换为MP4(H.264和AAC)没有什么变化。

这是我正在使用的代码:

import java.net.URL;
import javax.swing.JFrame;
import javax.swing.SwingUtilities;
import javafx.application.Platform;
import javafx.beans.value.ChangeListener;
import javafx.beans.value.ObservableValue;
import javafx.embed.swing.JFXPanel;
import javafx.event.ActionEvent;
import javafx.event.EventHandler;
import javafx.scene.Scene;
import javafx.scene.control.Button;
import javafx.scene.layout.VBox;
import javafx.scene.media.Media;
import javafx.scene.media.MediaPlayer;
import javafx.scene.media.MediaView;
import javafx.util.Duration;


public class CallVideo extends JFrame{

public static final String VID_URL = "file:/C:/Users/Public/Videos/Videos/testCon.mp4"; //http://static.clipcanvas.com/sample/clipcanvas_14348_H264_320x180.mp4

private JFXPanel panel;

public CallVideo(String url)
{   
    panel = new JFXPanel();
    Platform.runLater(new Runnable()
    {
        public void run()
        {
            final Media clip = new Media(VID_URL);
            final MediaPlayer player = new MediaPlayer(clip);
            final MediaView viewer = new MediaView(player);
            viewer.setFitHeight(200);
            viewer.setFitWidth(200);
            final Button button = new Button("Bing Zzzzt!");
            button.setOnAction(new EventHandler<ActionEvent>() {
                @Override
                public void handle(ActionEvent event)
                {
                    viewer.getMediaPlayer().seek(Duration.ZERO);
                    viewer.getMediaPlayer().play();
                }
            });

        setMediaEventHandlers(viewer);
            VBox vid = new VBox();
            vid.getChildren().addAll(viewer, button);
            Scene aScene = new Scene(vid, 200, 200);
            panel.setScene(aScene);
        }
    });
    this.add(panel);
    this.setSize(500, 500);
    this.setLocationRelativeTo(null);
    this.setDefaultCloseOperation(EXIT_ON_CLOSE);
    this.setVisible(true);
}

private void setMediaEventHandlers(final MediaView view) {
    final MediaPlayer player = view.getMediaPlayer();

    System.out.println("Initial: " + player.getStatus());
    player.statusProperty().addListener(new ChangeListener<MediaPlayer.Status>() {
      @Override
      public void changed(ObservableValue<? extends MediaPlayer.Status> observable, MediaPlayer.Status oldStatus, MediaPlayer.Status curStatus) {
        System.out.println("Current: " + curStatus);
      }
    });

    if (player.getError() != null) {
      System.out.println("Initial Error: " + player.getError());
    }

    player.setOnError(new Runnable() {
      @Override public void run() {
        System.out.println("Current Error: " + player.getError());
      }
    });
  }

public static void main(String[] args)
{
    SwingUtilities.invokeLater(new Runnable()
    {
        public void run()
        {
            new CallVideo(VID_URL);
        }
    });
}

}

错误发生在初始化“Media”对象的行(构造函数的开头)。我完全不知道问题是什么。我已经看到有关音频播放的问题,但视频没有出现,但它甚至没有对我这样做...

如果有人需要它:

日食

JDK 7

JavaFX 2.0

Windows 7专业版

编辑:

首先,我注意到我实际上正在使用JavaFX 2.0 ......这可能是问题所在吗?

我已经测试了答案中提供的两个版本,并且在使用该答案提供的URL时都返回此错误(由statusListener调用):

Current Error: MediaException: MEDIA_UNSUPPORTED : com.sun.media.jfxmedia.MediaException: "Error enter code herelocator unsupported media format" : com.sun.media.jfxmedia.MediaException: "Error locator unsupported media format"

使用我自己的文件时,程序在调用Media构造函数时立即返回此错误,如前所述:

Exception in thread "AWT-EventQueue-0" MediaException: MEDIA_UNSUPPORTED : Unrecognized file signature!
at javafx.scene.media.Media.<init>(Media.java:382)
at CallVideo.<init>(CallVideo.java:27)
at CallVideo$5.run(CallVideo.java:90)
at java.awt.event.InvocationEvent.dispatch(Unknown Source)
at java.awt.EventQueue.dispatchEventImpl(Unknown Source)
at java.awt.EventQueue.access$000(Unknown Source)
at java.awt.EventQueue$3.run(Unknown Source)
at java.awt.EventQueue$3.run(Unknown Source)
at java.security.AccessController.doPrivileged(Native Method)
at java.security.ProtectionDomain$1.doIntersectionPrivilege(Unknown Source)
at java.awt.EventQueue.dispatchEvent(Unknown Source)
at java.awt.EventDispatchThread.pumpOneEventForFilters(Unknown Source)
at java.awt.EventDispatchThread.pumpEventsForFilter(Unknown Source)
at java.awt.EventDispatchThread.pumpEventsForHierarchy(Unknown Source)
at java.awt.EventDispatchThread.pumpEvents(Unknown Source)
at java.awt.EventDispatchThread.pumpEvents(Unknown Source)
at java.awt.EventDispatchThread.run(Unknown Source)

我已经更新了我上面使用的代码。

解决了!原因是我使用了一个不合适的JavaFX(可能还有JDK)。我不是真的控制那些东西,因为这些都是学校的电脑,但这让我感觉不错......谢谢你的帮助!我用最终代码更新了它。

java media-player javafx-2 mp4
1个回答
7
投票

在我修改你的程序以解决一些问题后,这对我有用。

我申请的一些更改:

  1. 查看视频需要使用MediaView,因此需要创建并添加到活动的JavaFX场景才能看到视频。
  2. 需要在JavaFX应用程序线程而不是主线程上创建一些JavaFX控件,否则您将获得java.lang.IllegalStateException: Toolkit not initialized
  3. 监视介质错误事件并添加一些诊断日志有助于解决介质编码问题。

仅限JavaFX的解决方案

您的程序将JavaFX嵌入到Swing应用程序中,该应用程序比在标准JavaFX应用程序中播放Media更复杂一些。用于在标准JavaFX应用程序中播放mp4的相应代码在我对Can't play mp4 converted file - JavaFX 2.1的回答中提供。除非您特别需要Swing(例如在现有的大型Swing应用程序中嵌入基于JavaFX的媒体播放器),否则建议仅使用JavaFX。

Oracle为Incorporating Media Assets Into JavaFX Applications提供了一个很好的教程。


JavaFX media package description记录了JavaFX支持的媒体播放编码,容器和协议。


使用JavaFX MediaPlayer从Swing App播放mp4视频的示例

请注意,该示例仅捕获可能的媒体错误的子集。对于可以捕获并记录所有介质错误的代码模板,请参阅JavaFX media error handling documentation

import javax.swing.*;
import javafx.application.Platform;
import javafx.beans.value.*;
import javafx.embed.swing.JFXPanel;
import javafx.event.*;
import javafx.geometry.Pos;
import javafx.scene.Scene;
import javafx.scene.control.*;
import javafx.scene.layout.VBox;
import javafx.scene.media.*;
import javafx.util.Duration;

public class VideoPlayer extends JFrame {

  public static final String VID_URL = 
    "http://static.clipcanvas.com/sample/clipcanvas_14348_H264_320x180.mp4";

  private static final int VID_WIDTH     = 320;
  private static final int VID_HEIGHT    = 180;
  private static final int PLAYER_WIDTH  = 320;
  private static final int PLAYER_HEIGHT = 265;

  private void play(final String url) {
    final JFXPanel panel = new JFXPanel();
    Platform.runLater(new Runnable() {
      @Override public void run() {
        initFX(panel, url);
      }
    });
    this.add(panel);
    this.setSize(PLAYER_WIDTH, PLAYER_HEIGHT);
    this.setLocationRelativeTo(null);
    this.setDefaultCloseOperation(EXIT_ON_CLOSE);
    this.setVisible(true);
  }

  private void initFX(JFXPanel panel, String url) {
    MediaView mediaView = createMediaView(url);

    final Scene playerScene = new Scene(
      createPlayerLayout(mediaView), 
      PLAYER_WIDTH, 
      PLAYER_HEIGHT
    );

    setMediaEventHandlers(
      mediaView
    );

    panel.setScene(playerScene);
  }

  private MediaView createMediaView(String url) {
    final Media clip = new Media(url);
    final MediaPlayer player = new MediaPlayer(clip);
    final MediaView view = new MediaView(player);
    view.setFitWidth(VID_WIDTH);
    view.setFitHeight(VID_HEIGHT);
    return view;
  }

  private VBox createPlayerLayout(final MediaView view) {
    final Button button = new Button("Play From Start");
    button.setOnAction(new EventHandler<ActionEvent>() {
      @Override public void handle(ActionEvent event) {
        view.getMediaPlayer().seek(Duration.ZERO);
        view.getMediaPlayer().play();
      }
    });

    final VBox layout = new VBox(8);
    layout.setAlignment(Pos.CENTER);
    layout.getChildren().addAll(
      view,
      button
    );

    layout.setStyle("-fx-background-color: linear-gradient(to bottom, derive(lightseagreen, -20%), lightseagreen);");

    return layout;
  }

  private void setMediaEventHandlers(final MediaView view) {
    final MediaPlayer player = view.getMediaPlayer();

    System.out.println("Initial: " + player.getStatus());
    player.statusProperty().addListener(new ChangeListener<MediaPlayer.Status>() {
      @Override
      public void changed(ObservableValue<? extends MediaPlayer.Status> observable, MediaPlayer.Status oldStatus, MediaPlayer.Status curStatus) {
        System.out.println("Current: " + curStatus);
      }
    });

    if (player.getError() != null) {
      System.out.println("Initial Error: " + player.getError());
    }

    player.setOnError(new Runnable() {
      @Override public void run() {
        System.out.println("Current Error: " + player.getError());
      }
    });
  }

  public static void main(String[] args) {
    SwingUtilities.invokeLater(new Runnable() {
      @Override public void run() {
        VideoPlayer player = new VideoPlayer();
        player.play(VID_URL);
      }
    });
  }
}

解决了!

很高兴看到原始海报能够使视频播放工作,最后的错误只是使用了不支持mp4播放的旧JavaFX版本(2.0)。更新到JavaFX 2.2+(支持mp4播放)修复了这个问题。

© www.soinside.com 2019 - 2024. All rights reserved.