Issue
I would need to be able to seek to a position before playback of a video is started with JavaFx 16
When MediaPlayers seek() or setStartTime() is called before play() it is breaking video output and no frames are updated anymore (sound is still playing).
The duration of the video is known and not indefinite. No errors are printed by the listener nor any meaningful stalling (only sometimes in the beginning when video is loaded via https), but the same issue appears for local files as well. So I think this can be ruled out. I am building and running the app with Maven, mvn clean javafx:run
.
I tried to call those methods separately and also one after each other inside the ready listener and outside in the start method.
I am using JDK 11 (11.0.11+9-Ubuntu-0ubuntu2), maven 3.6.3 and openjfx 16 at GNU/Linux (Ubuntu 21.04)).
I assembled a minimal example and do I do anything wrong in the following code? Do you know how this could be handled or worked around? Thanks in advance.
App.java
package org.openjfx;
import javafx.application.Application;
import javafx.scene.control.Label;
import javafx.scene.Group;
import javafx.scene.media.Media;
import javafx.scene.media.MediaPlayer;
import javafx.scene.media.MediaView;
import javafx.scene.Scene;
import javafx.stage.Stage;
import javafx.util.Duration;
import javafx.event.EventHandler;
import javafx.scene.input.KeyEvent;
import javafx.scene.input.KeyCode;
public class App extends Application {
private Scene scene;
private MediaPlayer mediaPlayer;
private final Runnable onReadyStateListener = new Runnable() {
@Override
public void run() {
registerMinimalKeyEventHandling();
// Calling seek or setStartTime will break video playback, frames won't be updated anymore (and only the sound keeps playing)
Duration startTime = new Duration(6000L);
mediaPlayer.seek(startTime);
mediaPlayer.setStartTime(startTime);
mediaPlayer.play();
}
};
@Override
public void start(Stage stage) {
scene = new Scene(new Group(), 1600, 900);
stage.setScene(scene);
// The same issue occurs to local as well as remote videos
//Media media = new Media("file:///tmp/big_buck_bunny_720p_10mb.mp4");
Media media = new Media("https://sample-videos.com/video123/mp4/720/big_buck_bunny_720p_10mb.mp4");
mediaPlayer = new MediaPlayer(media);
mediaPlayer.setOnReady(onReadyStateListener);
mediaPlayer.setOnStalled(onStalledListener);
mediaPlayer.setOnError(onErrorListener);
MediaView mediaView = new MediaView(mediaPlayer);
mediaView.setFitWidth(1600);
mediaView.setFitHeight(900);
((Group) scene.getRoot()).getChildren().add(mediaView);
stage.show();
}
private void registerMinimalKeyEventHandling() {
scene.setOnKeyPressed(new EventHandler<KeyEvent>() {
@Override
public void handle(KeyEvent event) {
if (event.getCode() == KeyCode.SPACE) {
if (mediaPlayer.getStatus() == MediaPlayer.Status.PLAYING) {
mediaPlayer.pause();
return;
}
mediaPlayer.play();
} else if (event.getCode() == KeyCode.RIGHT) {
Duration seekTo = mediaPlayer.getCurrentTime().add(new Duration(1000L));
if (seekTo.greaterThan(mediaPlayer.getMedia().getDuration()) ) {
mediaPlayer.stop();
return;
}
mediaPlayer.seek(seekTo);
}
}
});
}
private final Runnable onStalledListener = new Runnable() {
@Override
public void run() { System.out.println(mediaPlayer.getCurrentTime().toString() + ": Video stalled"); }
};
private final Runnable onErrorListener = new Runnable() {
@Override
public void run() { System.out.println( mediaPlayer.getCurrentTime().toString() + ": Error occurred (" + mediaPlayer.getError().getLocalizedMessage() + ")"); }
};
public static void main(String[] args) { launch(); }
}
The test video is big_buck_bunny_720p_10mb.mp4 from sample-videos.com. This video playes without any problem in VLC (3.0.12 Vetinari) and mplayer (1.4) and seeking to other positions is possible.
Output of ffprobe:
Input #0, mov,mp4,m4a,3gp,3g2,mj2, from '/tmp/SampleVideo_1280x720_10mb.mp4':
Metadata:
major_brand : isom
minor_version : 512
compatible_brands: isomiso2avc1mp41
creation_time : 1970-01-01T00:00:00.000000Z
encoder : Lavf53.24.2
Duration: 00:01:02.32, start: 0.000000, bitrate: 1347 kb/s
Stream #0:0(und): Video: h264 (Main) (avc1 / 0x31637661), yuv420p, 1280x720 [SAR 1:1 DAR 16:9],
959 kb/s, 25 fps, 25 tbr, 12800 tbn, 50 tbc (default)
Metadata:
creation_time : 1970-01-01T00:00:00.000000Z
handler_name : VideoHandler
Stream #0:1(und): Audio: aac (LC) (mp4a / 0x6134706D), 48000 Hz, 5.1, fltp, 383 kb/s (default)
Metadata:
creation_time : 1970-01-01T00:00:00.000000Z
handler_name : SoundHandler
Project setup:
pom.xml
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>org.openjfx</groupId>
<artifactId>sample</artifactId>
<version>1.0.0</version>
<properties>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<maven.compiler.source>11</maven.compiler.source>
<maven.compiler.target>11</maven.compiler.target>
</properties>
<dependencies>
<dependency>
<groupId>org.openjfx</groupId>
<artifactId>javafx-controls</artifactId>
<version>16</version>
</dependency>
<dependency>
<groupId>org.openjfx</groupId>
<artifactId>javafx-media</artifactId>
<version>16</version>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<version>3.8.0</version>
<configuration>
<release>11</release>
</configuration>
</plugin>
<plugin>
<groupId>org.openjfx</groupId>
<artifactId>javafx-maven-plugin</artifactId>
<version>0.0.3</version>
<configuration>
<mainClass>org.openjfx.App</mainClass>
</configuration>
</plugin>
</plugins>
</build>
</project>
module-info.java
module org.openjfx {
requires javafx.controls;
requires javafx.media;
exports org.openjfx;
}
Solution
This is a known bug, which is a regression bug introduced in JavaFX 14. It was resolved in JavaFX 17. The best fix is to change your JavaFX version to 17 (or later; 17 is the current version at the time of writing). If that is not possible for some reason, reverting to version 13 or earlier will work, though you will see longer wait times before the video is ready.
In the pom, change to
<dependencies>
<dependency>
<groupId>org.openjfx</groupId>
<artifactId>javafx-controls</artifactId>
<version>17</version>
</dependency>
<dependency>
<groupId>org.openjfx</groupId>
<artifactId>javafx-media</artifactId>
<version>17</version>
</dependency>
</dependencies>
Answered By - James_D
Answer Checked By - Senaida (JavaFixing Volunteer)