#java #javafx #video-player
Вопрос:
Мне нужно было бы иметь возможность искать позицию до того, как начнется воспроизведение видео с помощью JavaFX 16
Когда медиаплееры ищут() или setStartTime() вызываются перед воспроизведением (), это нарушает вывод видео, и кадры больше не обновляются (звук все еще воспроизводится).
Продолжительность видео известна и не является неопределенной. Прослушиватель не печатает ошибок и не создает каких-либо существенных задержек (только иногда в начале, когда видео загружается по протоколу https), но та же проблема возникает и для локальных файлов. Поэтому я думаю, что это можно исключить. Я создаю и запускаю приложение с помощью Maven, mvn clean javafx:run
.
Я попытался вызвать эти методы отдельно, а также один за другим внутри готового прослушивателя и снаружи в методе запуска.
Я использую JDK 11 (11.0.11 9-Ubuntu-0ubuntu2), maven 3.6.3 и openjfx 16 в GNU/Linux (Ubuntu 21.04)).
Я собрал минимальный пример и делаю ли я что-нибудь не так в следующем коде? Знаете ли вы, как это можно было бы решить или обойти? Заранее спасибо.
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(); }
}
Тестовое видео big_buck_bunny_720p_10mb.mp4 от sample-videos.com.
Это видео воспроизводится без каких-либо проблем в VLC (3.0.12 Vetinari) и mplayer (1.4), и возможен поиск других позиций.
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
Настройка проекта:
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;
}
Ответ №1:
Это известная ошибка, которая является ошибкой регрессии, введенной в JavaFX 14. Это было решено в JavaFX 17. Лучшее решение — изменить версию JavaFX на 17 (или более позднюю; 17-текущая версия на момент написания статьи). Если по какой-либо причине это невозможно, будет работать возврат к версии 13 или более ранней, хотя вы увидите более длительное время ожидания, прежде чем видео будет готово.
В пом измените на
<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>