2016-10-25 3 views
1

ich versuche, eine MOV Video-Datei mit JavaFX zu öffnen:Spielen Sie ein Quicktime-Video mit JavaFX

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

Aber es wirft einen MediaException: MEDIA_UNSUPPORTED.

Wenn ich jedoch einfach die Dateierweiterung von .MOV zu .MP4 ändern, funktioniert es einwandfrei, und das Video wird ohne Fehler abgespielt.

Wie kann ich JavaFX zwingen, meine Datei abzuspielen, ohne sie umbenennen zu müssen?

+0

Können Sie mehr von Ihrem Stack-Trace veröffentlichen? Bearbeiten: NVM hat die Ursache gefunden. 'Media' ruft diese Methode von' Locator' auf, die die Ausnahme auslöst, die Sie erhalten http://pastebin.com/NkTFT2Tk –

Antwort

3

Nun, das war ein Spaß zwei Stunden. Bitte schön! Stellen Sie nur sicher, dass Sie eine Null-Byte-MP4-Datei wie im Beispiel haben. Es ist ziemlich wichtig, wie es funktioniert.

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(); 
     } 
    } 
} 

Wie es funktioniert: Normalerweise löst der Standard-Locator eine Ausnahme für den Inhaltstyp aus, und alles endet dort. Wenn Sie den Locator Media durch einen benutzerdefinierten ersetzen, können Sie mit contentType, length und uri manuell festlegen, dass der Locator ohne einen Piepton abgespielt werden soll.

+0

Dies ist ein Hack, aber ein cleverer Hack! – Patrick

+0

Wie immer können sich private Felder und Methoden von einer Java-Version zur nächsten ändern. Dies funktioniert möglicherweise nicht mit zukünftigen Java-Versionen. – VGR

+0

@VGR Ja, es wäre besser, den Java-Quellcode zu reparieren. Ich sollte vielleicht einen Fehlerbericht hinzufügen. – Patrick