Я создаю музыкальный проигрыватель с 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>
Надеюсь, кто-то можетПомоги мне,
С наилучшими пожеланиями, Лука