java - 如何在玩 JavaFx 之前寻找视频位置

标签 java javafx video-player

在使用 JavaFx 16 开始播放视频之前,我需要能够找到一个位置
当 MediaPlayers seek() 或 setStartTime() 在 play() 之前被调用时,它会中断视频输出并且不再更新任何帧(声音仍在播放)。
视频的持续时间是已知的,而不是无限期的。监听器不会打印任何错误,也不会出现任何有意义的停顿(仅在开始时通过 https 加载视频时才出现),但本地文件也会出现相同的问题。所以我觉得这个可以排除。我正在使用 Maven 构建和运行应用程序,mvn clean javafx:run .
我尝试分别在就绪监听器内部和 start 方法外部依次调用这些方法。
我在 GNU/Linux (Ubuntu 21.04) 上使用 JDK 11 (11.0.11+9-Ubuntu-0ubuntu2)、maven 3.6.3 和 openjfx 16。
我组装了一个最小的例子,我在下面的代码中做错了什么吗?你知道如何处理或解决这个问题吗?提前致谢。
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(); }

}
测试视频是来自 sample-videos.com 的 big_buck_bunny_720p_10mb.mp4。
该视频在 VLC (3.0.12 Vetinari) 和 mplayer (1.4) 中播放没有任何问题,并且可以寻找其他位置。
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>

模块信息.java
module org.openjfx {
    requires javafx.controls;
    requires javafx.media;
    exports org.openjfx;
}

最佳答案

这是一个 known bug ,这是 JavaFX 14 中引入的回归错误。它已在 JavaFX 17 中解决。最好的解决方法是将您的 JavaFX 版本更改为 17(或更高版本;17 是撰写本文时的当前版本)。如果由于某种原因无法做到这一点,则可以恢复到版本 13 或更早版本,但在视频准备好之前您会看到更长的等待时间。
在pom中,更改为

<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>

关于java - 如何在玩 JavaFx 之前寻找视频位置,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/69558917/

相关文章:

java - 用 Java 将用户输入发送到控制台

Flutter video_播放多个视频

javascript - 捕获和处理 HTML5 视频事件

java - 从本地方法抽象内部类扩展后,无法将内部类中的方法设置为私有(private)

java - 使用 AES 加密/解密,salt 大小为 32

java - 如何访问和读取一个对象的子对象的值?

按 Enter 键后 JavaFX 切换文本字段

java - TreeView Java FX : hide a node

layout - 将 TextArea 高度绑定(bind)到其内容

java - 如何使用 vlcj 在 JAVA (swing) jframe 中播放 mp4 视频?还有其他方法可以在 JAVA 中播放 mp4 吗?