JavaFX 2 mediaplayer - функция поиска является неточной или не работает вообще - PullRequest
0 голосов
/ 12 апреля 2019

Я создаю музыкальный проигрыватель с JavaFX8 и Java 8, и я столкнулся с проблемой, аналогичной той, о которой упоминали ранее.Я хочу создать слайдер, который представляет временную шкалу песни.Пользователь может перетащить ползунок, чтобы изменить текущее время воспроизведения песни.У слайдера столько же тиков, сколько у аудиофайла секунд.

В настоящее время я поддерживаю файлы .m4a и .mp3.

В зависимости от формата файла, функция поиска либо немного неточна, либо чрезвычайно неточна, либо работает нормально.(подробности см. ниже)

Я уже переместил функцию поиска в основной поток JavaFX, как кто-то предложил по другому вопросу.Ничего не изменилось.

Я пытался игнорировать ползунок и просто использовать функцию поиска, если медиаплеер достиг определенной отметки времени.Например, когда медиаплеер превышает 10 секунд, я назвал mediaplayer.seek (Duration.toSeconds (25)).

Функция в основном потоке JavaFX, которая должна перейти к отметке времени, соответствующей значению ползунка (которое можно перетаскивать).

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), может произойти четыре различных результата: Если файлы a.mp3 файл:

1) новая точка воспроизведения в песне, например, 0: 24 с, но функция mediaplayer.getCurrentTime (). toSeconds дает мне, например, 0: 26 с в качестве текущего времени.0: 26 будет иметь правильное значение, так как это также значение, к которому я хотел перейти.Поэтому в конце песни функция getCurrentTime () возвращает отметки времени, которые превышают значение mediaplayer.getDuration ().

2) Та же ситуация, что и в 1), но на этот раз точка воспроизведениявсегда 0: 00 вместо 0: 24, пока не перепрыгните ~ 50% песни.Если я перепрыгну через эту отметку, то это некоторая случайная точка, которая все еще отключается на много секунд.

3) В некоторых случаях это работает

Если это файл .m4a:

1) Работает нормально, как и ожидалось

На данный момент я совершенно не в себе и не вижу, что может быть не так, за исключением того, что функция поиска имеет ошибку или как-тобольшинство моих mp3-файлов не работают.

Вот минимальный пример кода:

Для пути просто поместите mp3-файл и замените продолжительность поиска на что-то действительно близкое кконец песни, чтобы его можно было определить вручную, чтобы песня воспроизводилась дольше, чем должна.(например, 1 с)

Основной класс:

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>

Надеюсь, кто-то можетПомоги мне,

С наилучшими пожеланиями, Лука

...