首页 > 解决方案 > JavaFX 2 媒体播放器 - 搜索功能不准确或根本不起作用

问题描述

我正在使用 JavaFX8 和 Java 8 创建一个音乐播放器,我遇到了一个问题,类似于其他人之前提到的问题。我想创建一个代表歌曲时间线的滑块。用户可以拖动滑块来更改歌曲的当前播放时间。滑块的刻度与音频文件的秒数一样多。

我目前支持 .m4a 和 .mp3 文件。

根据文件格式,搜索功能可能会稍微不准确、极不准确或工作正常。(详细信息见下文)

正如有人在另一个问题上建议的那样,我已经将 seek 函数移到了 JavaFX 主线程中。没有改变任何东西。

我试图忽略滑块,如果媒体播放器达到某个时间戳,只需使用搜索功能。例如,当媒体播放器超过 10 秒时,我调用了 mediaplayer.seek(Duration.toSeconds(25))。

主 JavaFX Thread 中的函数,它应该跳转到与滑块值对应的时间戳(可拖动)。

public void seekToSecond(){
         currentSongmediaPlayer.seek(Duration.seconds(uiController.getSliderValue()));
}

这是根据媒体播放器当前的时间戳更新滑块位置的代码。只要媒体播放器的状态等于“正在播放”,它就会在 JavaFX 后台服务中运行。但它不应该对音频文件的播放时间有任何影响。

if(uiController.getDragged()) {
  uiController.setTimeLineDraggedFalse();
}
uiController.setSliderPosition((int)currentSongmediaPlayer.getCurrentTime().toSeconds());

sleep(100);   //sleep for 1/10 of a second

当我使用 mediaplayer.seek(double time) 函数时,可能会出现四种不同的结果: 如果文件是 .mp3 文件:

1) 歌曲中的新播放点是例如 0:24s,但是 mediaplayer.getCurrentTime().toSeconds 函数给了我例如 0:26s 作为当前时间。0:26s 应该是正确的值,因为这也是我想要跳转到的值。因此在歌曲结束时,getCurrentTime() 函数返回时间戳,该时间戳高于 mediaplayer.getDuration() 值。

2) 情况与 1) 相同,但这次播放点始终是 0:00s 而不是 0:24s,只要不跳过约 50% 的歌曲即可。如果我跳过这个标记,那么它是一个随机点,仍然相差很多秒。

3)在少数情况下它有效

如果是 .m4a 文件:

1)它工作正常,正如预期的那样

在这一点上,我完全一无所知,看不出有什么问题,除了不知何故搜索功能有错误或不知何故我的大多数 mp3 文件都不起作用。

这是一个最小的代码示例:

对于路径,只需放置一个 mp3 文件并用非常接近歌曲结尾的内容替换 in seek 的持续时间,以便手动检测到歌曲播放的时间比应有的时间长。(例如1s)

主要类:

package sample;

import java.io.File;
import javafx.application.Application;
import javafx.fxml.FXMLLoader;
import javafx.scene.Group;
import javafx.scene.Parent;
import javafx.scene.Scene;
import javafx.scene.media.Media;
import javafx.scene.media.MediaPlayer;
import javafx.scene.media.MediaView;
import javafx.stage.Stage;
import javafx.util.Duration;

public class Main extends Application {

    static MediaPlayer player;

    @Override
    public void start(Stage primaryStage) throws Exception{
        MediaView mv = new MediaView();
        File file = new File("path/to/file.mp3");
        Media media = new Media(file.toURI().toString());
        player = new MediaPlayer(media);
        Parent root = FXMLLoader.load(getClass().getResource("sample.fxml"));
        Scene scene = new Scene(root, 600, 400);
        ((Group) scene.getRoot()).getChildren().add(mv);
        primaryStage.setTitle("Hello World");
        primaryStage.setScene(scene);
        primaryStage.show();
        player.seek(Duration.seconds(40));
        player.play();
    }

    public static void seekTest(){
        System.out.println("hi");
        player.seek(Duration.seconds(/*time where it is manually detectable, that the second is not correct (e.g. 1s before end of song)*/));
    }

    public static void main(String[] args) {
        launch(args);
    }
}

fxml 控制器:

package sample;

import javafx.fxml.FXML;

public class Controller {


   @FXML
   public void buttonPressed(){
      Main.seekTest();
   }

}

我的 fxml

<?xml version="1.0" encoding="UTF-8"?>

<?import javafx.scene.Group?>
<?import javafx.scene.control.Button?>
<?import javafx.scene.layout.AnchorPane?>

<Group xmlns="http://javafx.com/javafx/8.0.172-ea" xmlns:fx="http://javafx.com/fxml/1" fx:controller="sample.Controller">
   <children>
      <AnchorPane layoutX="-7.0" layoutY="-7.0" prefHeight="200.0" prefWidth="200.0">
         <children>
            <Button layoutX="85.0" layoutY="88.0" mnemonicParsing="false" onAction="#buttonPressed" text="Button" />
         </children>
      </AnchorPane>
   </children>
</Group>

希望可以有人帮帮我,

最好的问候,卢卡

标签: javajavafxjavafx-2mp3

解决方案


推荐阅读