I need to get an image as preview of the videos loaded by the users, it doesn't need to be a great thumbnail because it's just for a chat application, so I had in mind that when a user sends a message that contains an mp4 I process it and save a random frame as well.
I googled a bit and everyone is using ffmpeg but that's an external software and you can only interact with it with java, my project needs to be stand alone I don't want it to rely on the fact that the server has ffmpeg installed, so I went back in time and found JavaFX, but all the snippets online don't specify the version they're using and chatGPT is useless as always, can you guys show me how to do it or at least explain to me how it works so that I can code it myself? I'm using this dependency
   <dependency>
        <groupId>org.openjfx</groupId>
        <artifactId>javafx-controls</artifactId>
        <version>16</version> <!-- the version chatGPT wrote but you can change that -->
    </dependency>
if you have a different solution altogether that's great too I only care about saving a random frame from the video with the specified name at the specified path, thanks in advance
I tried this method but it gives plenty of errors probably because of a version mismatch
private byte[] getFrameFromVideo(String videoFilePath, int targetTimeSeconds) throws IOException {
        try {
            Media media = new Media(new File(videoFilePath).toURI().toString());
            MediaPlayer mediaPlayer = new MediaPlayer(media);
            CountDownLatch latch = new CountDownLatch(1);
            mediaPlayer.setOnReady(() -> {
                mediaPlayer.pause();
                mediaPlayer.setStartTime(mediaPlayer.getTotalDuration().multiply(targetTimeSeconds * 1.0 / media.getDuration().toSeconds()));
                mediaPlayer.setStopTime(mediaPlayer.getStartTime().add(mediaPlayer.getTotalDuration().multiply(1.0 / media.getDuration().toSeconds())));
                latch.countDown(); 
            });
            mediaPlayer.setOnEndOfMedia(() -> {
                BufferedImage bufferedImage = new BufferedImage(mediaPlayer.getMedia().getWidth(), mediaPlayer.getMedia().getHeight(), BufferedImage.TYPE_3BYTE_BGR);
                FXImage fxImage = mediaPlayer.snapshot(null);
                fxImage.pixelReaderProperty().get().getPixels(0, 0, (int) fxImage.getWidth(), (int) fxImage.getHeight(), javafx.scene.image.PixelFormat.getByteRgbInstance(), bufferedImage.getRaster().getDataBuffer());
                try {
                    ByteArrayOutputStream baos = new ByteArrayOutputStream();
                    ImageIO.write(bufferedImage, "png", baos);
                    mediaPlayer.dispose();
                    latch.countDown(); 
                    return baos.toByteArray();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            });
            mediaPlayer.play();
            latch.await();
        } catch (Exception e) {
            e.printStackTrace();
        }
        return null;
    }
                As you are using Maven, to use JavaFX Media, you need JavaFX media as a Maven dependency and also added to your Java module system.
You need to start the JavaFX runtime to correctly use the Media system.
JavaFX API calls to media should be made on the JavaFX application thread. The JavaFX application thread should never be slept or latched.
To play the media and ensure it is ready to take a snapshot at a chosen location:
MediaView node in a scene.mute the media player.seek API.status
of the media player.play the video from the sought point.After the status switches to playing, use Platform.runLater, to give the system time to render the required frame.  And in the runLater call perform the next steps:
snapshot of the MediaView node.stop the MediaPlayer.dispose of the player.Your snapshot gives you a JavaFX image you can directly display in a JavaFX ImageView.
If you need to save your snapshot image to disk:
Image to a BufferedImage
using the javafx-swing module.
javafx-media.jpg or png using ImageIO apis.
If your app is modular, then in your module-info include all of the required module dependencies to make this work:
javafx.mediajavafx.swingjava.desktopRecommended distribution
To get your app functionality to end users, it is recommended to either:
maven-javafx-plugin, to create a jlinked zip of your app for your target platform,
jlink.OR
jpackage system to create an installer for your app or if your app is not modular.
jpackage to package a non-modular application and create installers for various platforms is more complex than creating jlink zip distributions for modular applications.For either of the above methods, the user will generally not have to install any other software on the target machine in order to use your app.
References
Alternatives
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With