My MediaPlayer only plays the sound once. When I type audio.play() twice, it still only plays once. How do I get it to play again when I call audio.play()?
When I tried looking this up, most of the solutions were for Android. Where they recommended to use AudioFocus, however as my code is just Java and not Android that did not work.
I also tried to use "audio.stop()", in between the two .play()s. But that still did'nt change anything.
import javafx.scene.media.Media;
import javafx.scene.media.MediaPlayer;
import java.io.File;
public class audio {
public static void main(String[] args) {
com.sun.javafx.application.PlatformImpl.startup(()->{});
MediaPlayer audio = new MediaPlayer(
new Media(
new File("C:\\Users\\User\\Pictures\\Java Projects\\FlappyBird\\sfx_wing.mp3").toURI().toString()));
audio.play();
audio.play();
}
}
Currently, the first time I run "audio.play()", the sound correctly plays. But when I play it again, it doesn't play.
Use audio.seek(audio.getStartTime()); to play it again. Check the documentation if you have trouble understanding this line.
Related
I was creating what I deemed to be a quite simple program that played a .wav file in Java, but the sound is not playing when the program is started. All of my imports seem to be good, and I am not too sure why it is not playing, and I am starting to wonder if it is a problem with where I placed my files. I have attached both my code, and a screenshot of the location of my files for this project here. Please tell me if more information is needed. Any help is appreciated.
package javaSounds;
import java.io.File;
import javax.sound.sampled.AudioSystem;
import javax.sound.sampled.Clip;
public class JavaSounds {
public static void main(String[] args) {
File explosion = new File("explosion.wav");
PlaySound(explosion);
}
static void PlaySound(File Sound) {
try {
Clip clip = AudioSystem.getClip();
clip.open(AudioSystem.getAudioInputStream(Sound));
clip.start();
} catch (Exception e) {
}
}
}
The problem is not the addressing but that the program finishes and closes before the sound gets played.
The command clip.start() launches and plays the sound on a daemon thread. These threads, even while running concurrently, will not hold a Java program open. Since there is nothing else happening in the program, everything shuts down and nothing is heard.
A simple way to test this is to add the command Thread.sleep(..) after starting the clip. A more usual practice is to trigger the sound from a GUI, where the presence of the GUI keeps the java program alive for the duration of the clip.
If your sound doesn't play with the addition of a sleep pause, then we can look at the addressing. By the way, it's better to get your AudioInputStream from a URL than from a File. If you plan to jar your program and include audio resources as part of the jar, File will be unable to locate those internal resources.
I have Java 8 installed correctly and it is the oracle version (NOT OpenJDK). My IDE is Eclipse. When I run the following code in a JavaFX project,
import java.io.File;
import javafx.embed.swing.JFXPanel;
import javafx.scene.media.Media;
import javafx.scene.media.MediaPlayer;
public class TestPlayer {
static JFXPanel fxPanel =new JFXPanel();
private Media song;
private MediaPlayer mediaPlayer ;
public TestPlayer(String filePath) {
song=new Media(new File(filePath).toURI().toString());
mediaPlayer = new MediaPlayer(song);
}
public void play() {
this.mediaPlayer.play();
}
public static void main(String[] args) {
new TestPlayer("song\\1.mp3").play();
}
}
the mediaPlayer can only play song for several seconds, then no sound and no exception thrown.
Then I changed the line 8 from
private Media song;
to
private static Media song;
And the modified code ran successfully.
I want to know the reason although the problem solved. These 2 following screenshots are taken in the debug mode of Eclipse
Before modification:
After modification:
The difference is "JFXMedia Player EventQueueThread".
You are seeing a garbage collection issue of the media player thread - JFXMedia Player EventQueueThread. Iv'e used VisualVM to monitor the threads and GC.
Your code starts the MediaPlayer and returns, leaving the instance references eligible for GC. Here I have forced a GC a few seconds after launch (at 6:44:57):
and at the same time the JFXMedia Player EventQueueThread stopped:
By making the Media or MediaPlayer static you are tying them to the class loader instead of to the class instance, thus they are not eligible for collection. Generally, you should subclass Application when using JavaFX classes. The class's JavaDoc states:
Threading
JavaFX creates an application thread for running the application start
method, processing input events, and running animation timelines.
The Java launcher loads and initializes the specified Application
class on the JavaFX Application Thread. If there is no main method in
the Application class, or if the main method calls
Application.launch(), then an instance of the Application is then
constructed on the JavaFX Application Thread.
When running your code this way, GC can't collect the JFXMedia Player EventQueueThread. Again, I initiated a GC (at 7:19:04)
and now the thread is still alive:
Notice that the main thread is also there along with the JavaFX-Launcher.
For a true deep analysis you must inspect a heap dump, but hopefully this insight is enough for the scope of the question.
package musictesting;
import java.io.File;
import javafx.scene.media.MediaPlayer;
import javafx.scene.media.Media;
public class playsound {
public static void testsound(){
String musicFileName = "ROQUE.mp3";
Media sound = new Media(new File(musicFileName).toURI().toString());
Media song = new Media(Paths.get(musicFileName).toUri().toString());
MediaPlayer mediaPlayer = new MediaPlayer(sound);
mediaPlayer.play();
}
public static void main(String [] args){
testsound();
}
}
For a group assignment I've been deligated to make the music that plays for a game developed in Java, I've been looking at some ways to play audio files and it seems like JavaFX is the way to go. I just wanted to run like a simple test player but I get the following error:
Exception in thread "main" MediaException: MEDIA_UNAVAILABLE : C:\Users\Dylan\Documents\stuffinaround\musictesting\ROQUE.mp3 (The system cannot find the file specified)
at javafx.scene.media.Media.<init>(Unknown Source)
at musictesting.playsound.testsound(playsound.java:13)
at musictesting.playsound.main(playsound.java:19)
The file ROQUE.mp3 is in my source/bin folders.
I've tried different code people have posted online, this seems pretty straight ahead. What am I doing wrong?
Thanks in advance
Anyone having trouble with this should check out this thread, initializing JavaFX from a separate method or class fixes this, I'm not sure I understand the ins and outs yet but it works for now!
How to use JavaFX MediaPlayer correctly?
I have spent hours today looking up how to get some form of audio in eclipse and have had trouble every step of the way. Currently I have something that should work but I get an error:
Exception in thread "main" java.lang.IllegalArgumentException: expected file name as argument
at com.sun.javafx.css.parser.Css2Bin.main(Css2Bin.java:44)
I have basically copied this from someone who had it working. I would like to say that the FX lib is added where it should be. I know this isn't fancy but I was just trying the basics.
package b;
import java.io.File;
import javafx.scene.media.Media;
import javafx.scene.media.MediaPlayer;
public class test {
public static void main(String[] args){
String uriString = new File("C:\\Users\\Mike\\workspace\\b\\src\\hero.mp3").toURI().toString()
MediaPlayer player = new MediaPlayer( new Media(uriString));
player.play();
}}
I have also tried many different path names in case it was wrong with no luck, I also just tried to copy and paste the path name that i got in eclipse by going to properties ex: /b/src/hero.mp3. Help would be appreciated to get me out of this nightmare.
The files located outside the workspace should be included with file:// prefix. A simple example demonstrating the functionality is
public class Reproductor extends Application {
public static void main(String[] args) {
launch(args);
}
#Override
public void start(Stage stage) throws Exception {
Media media = new Media("file:///Movies/test.mp3"); //replace /Movies/test.mp3 with your file
MediaPlayer player = new MediaPlayer(media);
player.play();
}
}
If the file is into the resources/music this will work and the application will be portable,.mp3 inside the .jar:
Media media = null;
try {
media = new Media(getClass().getResource("/music/hero.mp3").toURI().toString());
} catch (URISyntaxException e) {
e.printStackTrace();
}
I suspect you have a issue with referencing embedded resources. An embedded resource is any file which is contained within the application context (ie. In this case, stored within the application Jar).
In order to obtain a reference to these resources, you need to use Class#getResource, which returns a URL, which you can then use to load the resource depending on your requirements, for example...
public class Main extends Application {
#Override
public void start(Stage primaryStage) {
String path = Test.class.getResource("/Kalimba.mp3").toString();
Media media = new Media(path);
MediaPlayer mp = new MediaPlayer(media);
mp.play();
System.out.println("Playing...");
}
public static void main(String[] args) {
launch(args);
}
}
Now, I couldn't get it to work until I wrapped in a Application context...
JavaFX EMBED an MP3 into the jar (in the jar) with NetBeans
I programmed my very first JavaFX package in NetBeans, and then I wanted to add sound, an mp3 music file, embedded in the jar, inside the jar, so that I could email the jar to my friends and the music would play on their computers. Thank you StackOverflow for your help. Thanks especially to the member who said “put your music file IN THE JAR, getResourceAsStream() is the API you want to use.” He put me on the right track, although I ended up using getResource(). It works.
STEP 1: Firstly, I got the music to play when I hit run in NetBeans.
STEP 2: I wanted the music to loop (repeat). Eventually I got that right, thanks to the members of StackOverflow. Please see my source code.
STEP 3: Finally I got the mp3 to EMBED in the jar. Now, this is important. At first the music played on my computer, but the jar read it off my hard disc. When I changed the name of the mp3, then the jar crashed, it would not run, it could not find the mp3. I had to embed the mp3 into the jar, put it inside the jar (in the jar) otherwise it would not play on somebody else’s computer. That’s where getResource() did the trick.
STEP 4: Then I emailed my jar to friends. Some service providers don’t trust a jar, they sent the emails back to me, undelivered. Other service providers don’t have a problem and delivered the emails. So, what did I do? I changed the name of the *.jar to *.mp4 and the emails were delivered, I asked my friends to change it back from *.mp4 to *.jar. It worked.
Here is my source code. I’m sure it’s not perfect, but it works, thanks to StackOverflow.
/* Of course, one needs to import the following gizmo’s (and others): */
import javafx.util.Duration;
import javafx.scene.media.Media;
import javafx.scene.media.MediaPlayer;
/* I want to EMBED the music inside the jar (in the jar).
The secret seems to be getResource. The source code starts here,
to EMBED the sound (DollyParton.mp3) into the jar: */
//************************ begin the music ***********************
#Override public void start(Stage primaryStage) throws Exception {
init(primaryStage);
primaryStage.show();
play();
}
public static void main(String[] args) {
launch(args);
}
MediaPlayer musicplayer; {
/* Put your music file IN THE JAR, "getResourceAsStream()" is
the API you want to use. Put the DollyParton.mp3 into the Windows
folder src/rockymountain. NetBeans automatically copies the mp3
to the folder build/classes/rockymountain. */
Media mp3MusicFile = new Media(getClass().getResource("DollyParton.mp3").toExternalForm());
musicplayer = new MediaPlayer(mp3MusicFile);
musicplayer.setAutoPlay(true);
musicplayer.setVolume(0.9); // from 0 to 1
//***************** loop (repeat) the music ******************
musicplayer.setOnEndOfMedia(new Runnable() {
public void run() {
musicplayer.seek(Duration.ZERO);
}
});
//*************** end of loop (repeat) the music **************
}
//**************************** end of music *************************
I put the mp3 into the Windows folder src/rockymountain. Then NetBeans automatically copied the mp3 to the folder build/classes/rockymountain. NetBeans does not copy the mp3 to the folder /resources, a file that I created unnecessarily, because someone said so. The /resources folder is not needed, it remains empty.
Create a Java ARchive (jar) file using NetBeans as follows:
Right-click on the Project name
Select Properties
Click Packaging
Check Build JAR after Compiling
Check Compress JAR File
Click OK to accept changes
Right-click on the Project name
Select Clean and Build
The JAR file is built. To view it inside NetBeans:
Click the Files tab
Expand ProjectName >> dist (distribution). The jar file is inside the dist folder.
Try to add --add-modules=javafx.controls,javafx.media in your VM options.
I tried this three lines and it worked!
Media sound = new Media(new File("src/music/menu.mp3").toURI().toString());
MediaPlayer player = new MediaPlayer(sound);
player.play();
First you need to put the code in try and catch to catch any error, second you must
define the JFXPanel to define it to the media package and the tool kit ,so this is the code:
package test1;
import java.io.File;
import javafx.scene.media.Media;
import javax.swing.JOptionPane;
import javafx.scene.media.MediaPlayer;
import javafx.embed.swing.JFXPanel;
public static void main(String[] args) {
try {
JFXPanel j = new JFXPanel();
String uriString = new File(""C:\\Users\\Mike\\workspace\\b\\src\\hero.mp3"").toURI().toString();
MediaPlayer Player = new MediaPlayer(new Media(uriString));
Player.play();
} catch (Exception ex) {
JOptionPane.showMessageDialog(null, ex);
}
}
and a good info for you can put only file name
inside the File() exp: String uri = new File("hero.mp3").toURI().toString();
I have written a code using vlcj which is intended to take screenshots of a video periodically. When I try to output the length of the video, it prints 0. What is the issue ?
import uk.co.caprica.vlcj.binding.LibVlc;
import uk.co.caprica.vlcj.player.MediaPlayerFactory;
import uk.co.caprica.vlcj.player.embedded.EmbeddedMediaPlayer;
import uk.co.caprica.vlcj.runtime.RuntimeUtil;
import com.sun.jna.Native;
import com.sun.jna.NativeLibrary;
public class ScreenShotCapture {
public static void main(String[] args){
NativeLibrary.addSearchPath(RuntimeUtil.getLibVlcLibraryName(), "C:\\Program Files\\VideoLAN\\VLC");
Native.loadLibrary(RuntimeUtil.getLibVlcLibraryName(), LibVlc.class);
MediaPlayerFactory mediaPlayerFactory = new MediaPlayerFactory();
final EmbeddedMediaPlayer mediaPlayer =mediaPlayerFactory.newEmbeddedMediaPlayer();
mediaPlayer.playMedia("E:\\videos\\Avenged Sevenfold - So Far Away [Music Video].mp4");
mediaPlayer.setSnapshotDirectory("E:\\vidoes");
long length = mediaPlayer.getTime();
long interval = length / 21;
for(long i = 1;i <= length;i+= interval){
mediaPlayer.setTime(i);
mediaPlayer.saveSnapshot();
}
}
}
The media length is not immediately available, it will become available some time after the media has started playing when the decoder works out what the length is. That is just inherently how VLC works.
Just about everything works asynchronously, which means you must base your code on events rather than writing code in only a procedural way.
When the length changes a native event gets generated, ultimately causing a MediaPlayerEventListener#lengthChanged event to fire. When that event has fired, the call to mediaPlayer.getLength() should return a non-zero value.
The next issue is that you invoke saveSnapshot immediately after you invoke setTime. Again, setTime works asynchronously so you can not assume that the media player has reached the desired time when that method returns. You have to wait for a timeChanged event and check if your time has been reached (actually passed) yet or not.
The final issue, that may or may not be important depending on your use-case, is that the call to saveSnapshot is itself asynchronous so essentially you have requested a snapshot but it has not been generated yet. This time you need to wait for the snapshotTaken event. Only when that event has been received has the snapshot actually been saved to disk.
So basically you need to think differently and implement an event-based approach instead.
One example of that is in this vlcj example that generates snapshots: https://github.com/caprica/vlcj/blob/vlcj-3.0.1/src/test/java/uk/co/caprica/vlcj/test/condition/ConditionTest.java
If you don't like that example, then you can implement it just by responding to the events in your own MediaPlayerEventListener implementation.
An aside: you can also use the VLC "Scene" filter to generate snapshots in a reliable way.
I assume it's not caused by your spelling mistake in setting the snapshot directory?