使用JavaFX播放QuickTime视频

时间:2016-10-25 20:22:31

标签: java video javafx media quicktime

我尝试用JavaFX打开MOV视频文件:

Media media = new Media ("file:/tmp/file.MOV");

但它会抛出一个MediaException:MEDIA_UNSUPPORTED。

但是,如果我只是将文件扩展名从.MOV更改为.MP4​​,则效果非常好,视频播放时没有错误。

如何强制JavaFX播放我的文件而不必重命名?

1 个答案:

答案 0 :(得分:3)

这是一个有趣的两个小时。干得好!只需确保您有一个零字节mp4文件,如示例中所示。它是如何运作的关键。

public class TestFrame extends Application {
    public static void main(String[] args) {
        launch(args);
    }

    @Override
    public void start(Stage primaryStage) throws Exception {
        StackPane root = new StackPane();
        File actualFile = new File("shelter.mov");
        File emptyfile = new File("blank.mp4");
        Media media = new Media(emptyfile.toURI().toString());
        copyData(media, actualFile);
        MediaPlayer mediaPlayer = null;
        try {
            mediaPlayer = new MediaPlayer(media);
        } catch (Exception e) {
            e.printStackTrace();
        }
        mediaPlayer.setAutoPlay(true);
        MediaView mediaView = new MediaView(mediaPlayer);
        root.getChildren().add(mediaView);
        Scene scene = new Scene(root, 720, 480);
        primaryStage.setTitle("Hello World!");
        primaryStage.setScene(scene);
        primaryStage.show();
    }

    private void copyData(Media media, File f) {
        try {
            Field locatorField = media.getClass().getDeclaredField("jfxLocator");
            // Inside block credits:
            // http://stackoverflow.com/questions/3301635/change-private-static-final-field-using-java-reflection
            {
                Field modifiersField = Field.class.getDeclaredField("modifiers");
                modifiersField.setAccessible(true);
                modifiersField.setInt(locatorField, locatorField.getModifiers() & ~Modifier.FINAL);
                locatorField.setAccessible(true);
            }
            CustomLocator customLocator = new CustomLocator(f.toURI());
            customLocator.init();
            customLocator.hack("video/mp4", 100000, f.toURI());
            locatorField.set(media, customLocator);
        } catch (NoSuchFieldException | SecurityException | IllegalArgumentException | IllegalAccessException e) {
            e.printStackTrace();
        } catch (URISyntaxException e) {
            e.printStackTrace();
        }
    }

    static class CustomLocator extends Locator {
        public CustomLocator(URI uri) throws URISyntaxException {
            super(uri);
        }

        @Override
        public void init() {
            try {
                super.init();
            } catch (Exception e) {
            }
        }

        public void hack(String type, long length, URI uri){
            this.contentType = type;
            this.contentLength = length;
            this.uri = uri;
            this.cacheMedia();
        }
    }
}

工作原理:通常情况下,默认的Locator会引发有关内容类型的异常,并且它们都会在那里结束。将Media的定位器替换为自定义定位器,然后手动设置contentType,length和uri,使其无需窥视即可播放。