I want to get a frame sample (jpeg) from a video file (mov) with java. Is there an easy way to do this. When I search in google all I can find is to make mov from multiple jpgs. I dont know maybe I cannot find the right keywords.
I know that the original question is solved, nevertheless, I am posting this answer in case anyone else got stuck like I did.
Since yesterday, I have tried everything, and I mean everything to do this. All available Java libraries are either out of date, not maintained anymore or lack any kind of usable documentation (seriously??!?!)
I tried JFM (old and useless), JCodec (no documentation whatsoever), JJMpeg (looks promising but is very difficult and cumbersome to use due to lack of Java-class documentation), OpenCV auto-Java builds and a few bunch of other libraries that I cannot remember.
Finally, I decided to take a look at JavaCV's (Github link) classes and voila! It contains FFMPEG bindings with detailed documentations.
<dependency>
<groupId>org.bytedeco</groupId>
<artifactId>javacv</artifactId>
<version>1.0</version>
</dependency>
Turns out there is a very easy way to extract video frames from a video file to a BufferedImage and by extension a JPEG file. The class FFmpegFrameGrabber could be easily used for grabbing individual frames and converting them to BufferedImage. A code sample is as follows:
FFmpegFrameGrabber g = new FFmpegFrameGrabber("textures/video/anim.mp4");
g.start();
Java2DFrameConverter converter = new Java2DFrameConverter();
for (int i = 0 ; i < 50 ; i++) {
Frame frame = g.grabImage(); // It is important to use grabImage() to get a frame that can be turned into a BufferedImage
BufferedImage bi = converter.convert(frame);
ImageIO.write(bi, "png", new File("frame-dump/video-frame-" + System.currentTimeMillis() + ".png"));
}
g.stop();
Basically, this code dumps the first 50 frames of the video and saves them as a PNG file. The good thing is that the internal seek function, works on actual frames not keyframes (a problem that I had with JCodec)
You can refer to the JavaCV's homepage to find out more about other classes that can be used for capturing frames from WebCams etc. Hope this answer helps :-)
Xuggler does the job. They even give a sample code which does exactly what I need. Link is below
http://xuggle.googlecode.com/svn/trunk/java/xuggle-xuggler/src/com/xuggle/mediatool/demos/DecodeAndCaptureFrames.java
And I've modified the code in this link such that it saves only the first frame of the video.
import javax.imageio.ImageIO;
import java.io.File;
import java.awt.image.BufferedImage;
import com.xuggle.mediatool.IMediaReader;
import com.xuggle.mediatool.MediaListenerAdapter;
import com.xuggle.mediatool.ToolFactory;
import com.xuggle.mediatool.event.IVideoPictureEvent;
import com.xuggle.xuggler.Global;
/**
* * #author aclarke
* #author trebor
*/
public class DecodeAndCaptureFrames extends MediaListenerAdapter
{
private int mVideoStreamIndex = -1;
private boolean gotFirst = false;
private String saveFile;
private Exception e;
/** Construct a DecodeAndCaptureFrames which reads and captures
* frames from a video file.
*
* #param filename the name of the media file to read
*/
public DecodeAndCaptureFrames(String videoFile, String saveFile)throws Exception
{
// create a media reader for processing video
this.saveFile = saveFile;
this.e = null;
IMediaReader reader = ToolFactory.makeReader(videoFile);
// stipulate that we want BufferedImages created in BGR 24bit color space
reader.setBufferedImageTypeToGenerate(BufferedImage.TYPE_3BYTE_BGR);
// note that DecodeAndCaptureFrames is derived from
// MediaReader.ListenerAdapter and thus may be added as a listener
// to the MediaReader. DecodeAndCaptureFrames implements
// onVideoPicture().
reader.addListener(this);
// read out the contents of the media file, note that nothing else
// happens here. action happens in the onVideoPicture() method
// which is called when complete video pictures are extracted from
// the media source
while (reader.readPacket() == null && !gotFirst);
if (e != null)
throw e;
}
/**
* Called after a video frame has been decoded from a media stream.
* Optionally a BufferedImage version of the frame may be passed
* if the calling {#link IMediaReader} instance was configured to
* create BufferedImages.
*
* This method blocks, so return quickly.
*/
public void onVideoPicture(IVideoPictureEvent event)
{
try
{
// if the stream index does not match the selected stream index,
// then have a closer look
if (event.getStreamIndex() != mVideoStreamIndex)
{
// if the selected video stream id is not yet set, go ahead an
// select this lucky video stream
if (-1 == mVideoStreamIndex)
mVideoStreamIndex = event.getStreamIndex();
// otherwise return, no need to show frames from this video stream
else
return;
}
ImageIO.write(event.getImage(), "jpg", new File(saveFile));
gotFirst = true;
}
catch (Exception e)
{
this.e = e;
}
}
}
import java.awt.image.BufferedImage;
import java.io.File;
import java.io.IOException;
import javax.imageio.ImageIO;
import org.bytedeco.javacpp.opencv_core.IplImage;
import org.bytedeco.javacv.FFmpegFrameGrabber;
import org.bytedeco.javacv.FrameGrabber.Exception;
public class Read{
public static void main(String []args) throws IOException, Exception
{
FFmpegFrameGrabber frameGrabber = new FFmpegFrameGrabber("C:/Users/Digilog/Downloads/Test.mp4");
frameGrabber.start();
IplImage i;
try {
i = frameGrabber.grab();
BufferedImage bi = i.getBufferedImage();
ImageIO.write(bi,"png", new File("D:/Img.png"));
frameGrabber.stop();
} catch (Exception e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
Here's how with BoofCV:
String fileName = UtilIO.pathExample("tracking/chipmunk.mjpeg");
MediaManager media = DefaultMediaManager.INSTANCE;
ConfigBackgroundBasic configBasic = new ConfigBackgroundBasic(30, 0.005f);
ImageType imageType = ImageType.single(GrayF32.class);
BackgroundModelMoving background = FactoryBackgroundModel.movingBasic(configBasic, new PointTransformHomography_F32(), imageType);
SimpleImageSequence video = media.openVideo(fileName, background.getImageType());
ImageBase nextFrame;
while(video.hasNext()) {
nextFrame = video.next();
// Now do something with it...
}
maybe this will help you:
Buffer buf = frameGrabber.grabFrame();
// Convert frame to an buffered image so it can be processed and saved
Image img = (new BufferToImage((VideoFormat) buf.getFormat()).createImage(buf));
buffImg = new BufferedImage(img.getWidth(this), img.getHeight(this), BufferedImage.TYPE_INT_RGB);
//TODO saving the buffImg
for more informations:
How to take single snapshots from a webcam?
Below it is shown the essential code to request frames from media files.
For the complete source code and video demo:
"Media File Processing" example using Marvin Framework..
public class MediaFileExample implements Runnable{
private MarvinVideoInterface videoAdapter;
private MarvinImage videoFrame;
public MediaFileExample(){
try{
// Create the VideoAdapter used to load the video file
videoAdapter = new MarvinJavaCVAdapter();
videoAdapter.loadResource("./res/snooker.wmv");
// Start the thread for requesting the video frames
new Thread(this).start();
}
catch(MarvinVideoInterfaceException e){e.printStackTrace();}
}
#Override
public void run() {
try{
while(true){
// Request a video frame
videoFrame = videoAdapter.getFrame();
}
}catch(MarvinVideoInterfaceException e){e.printStackTrace();}
}
public static void main(String[] args) {
MediaFileExample m = new MediaFileExample();
}
}
Related
I am in the process of creating a small video editor and currently trying to get video files to display in the preview window. To do that, I want to get a frame of a video at a specific position using JavaCVs FFmpegFrameGrabber.
I have figured out a way of doing this, by setting the frameNumber variable of the grabber to the needed frame. However, this results in only the first frame of the file being displayed and some information about the file being printed out repeatedly (tell me if you need to see it, it's just kind of long and messy) alongside the error:
[swscaler # 000001927a7d3000] bad src image pointers
This is my frame grabbing class:
public class Video {
private FFmpegFrameGrabber grabber;
private final static Java2DFrameConverter converter = new Java2DFrameConverter();
public Video(File file) {
this.grabber = new FFmpegFrameGrabber(file);
try {
this.grabber.start();
} catch (Exception e) {
e.printStackTrace();
}
}
public BufferedImage grabFrame(int framePos) throws Exception {
BufferedImage frame;
grabber.grabImage(); // Without this done before, the image is just black
grabber.setFrameNumber(framePos);
frame = converter.convert(grabber.grabImage());
return frame;
}
}
I am very thankful for your answers!
I am making a screen recording application with Xuggler. I've basically encapsulated Java Code Geeks' Xuggler tutorial code into a runnable class for the actual recording. It should run just like the tutorial, but I'm getting some (actually a ton of) errors. The link to that code is here: JavaCodeGeeks. I'm not trying to take credit for this entire block of code.
Here is what I have so far:
import java.awt.AWTException;
import java.awt.Dimension;
import java.awt.Rectangle;
import java.awt.Robot;
import java.awt.Toolkit;
import java.awt.image.BufferedImage;
import java.io.File;
import java.util.concurrent.TimeUnit;
import javax.swing.JOptionPane;
import src.dtf.gui.GUI;
import com.xuggle.mediatool.IMediaWriter;
import com.xuggle.mediatool.ToolFactory;
import com.xuggle.xuggler.ICodec;
public class ScreenRecorder implements Runnable {
//Booleans to run and to pause. (Pausing not implemented yet)
boolean running = true;
boolean paused = false;
//Some variables
private GUI gui;
private Toolkit tk;
private String path, name, outputFilename;
private int fps;
private long startTime;
private Rectangle recArea;
private Dimension bounds;
//Declare the MediaWriter
private IMediaWriter writer;
//Constructor
public ScreenRecorder(GUI gui) {
//Set the GUI to the one that I'm using (Another class
this.gui = gui;
//Initialize variables, based on previous user input.
tk = Toolkit.getDefaultToolkit();
path = gui.getPath();
name = JOptionPane.showInputDialog("Please enter a name for your video file:");
outputFilename = path + "\\" + name + ".mp4";
fps = gui.getFPS();
if (gui.fullscreenChecked()) {
recArea = new Rectangle(0, 0, tk.getScreenSize().width,
tk.getScreenSize().height);
} else {
recArea = gui.getArea();
}
bounds = new Dimension(recArea.width, recArea.height);
}
//Start method
public void start() {
gui.disableButtons();
gui.changeRecordButton(false);
running = true;
}
//Run method
public void run() {
//Initialize
init();
long lastTime = System.currentTimeMillis();
int updateTime = 1000 / fps;
startTime = System.nanoTime();
while (running) {
//Limit updates
if (System.currentTimeMillis() - lastTime >= updateTime) {
//Ensure the recording is not paused
if (!paused) {
//If the user has stopped, stop
if (!gui.isRecording()) {
stop();
}
//Take a screenshot and convert it
BufferedImage frame = takeScreenshot();
BufferedImage bgrScreen = convertImage(frame, BufferedImage.TYPE_3BYTE_BGR);
//Encode video
writer.encodeVideo(0, bgrScreen, System.nanoTime() - startTime, TimeUnit.NANOSECONDS);
System.out.println("Recording...");
} else if (paused) {
System.out.println("Paused...");
}
}
}
}
private void init() {
//Make sure the given directory exists
checkFile();
//Ensure there is not already a file of the same name
checkFilename();
//Make the writer
writer = ToolFactory.makeWriter(outputFilename);
writer.addVideoStream(0, 0, ICodec.ID.CODEC_ID_MPEG4, bounds.width, bounds.height);
}
//Method for checking if the directory exists
private void checkFile() {
if (!(new File(path).exists())) {
gui.resetPath();
JOptionPane.showMessageDialog(gui, "ERROR: File path does not exist!");
System.out.println("ERRR");
stop();
}
}
//Method for checking if the given filename exists
private void checkFilename() {
if (new File(path + "\\" + name + ".mp4").exists()) {
JOptionPane.showMessageDialog(gui, "ERROR: File already exists!!");
stop();
}
}
//Method for converting the BufferedImage (Thanks JavaCodeGeeks)
private BufferedImage convertImage(BufferedImage b, int targetType) {
BufferedImage image;
if (b.getType() == targetType) {
image = b;
} else {
image = new BufferedImage(b.getWidth(), b.getHeight(), targetType);
image.getGraphics().drawImage(b, 0, 0, null);
}
return image;
}
//Method for taking a screenshot
private BufferedImage takeScreenshot() {
try {
Robot r = new Robot();
return r.createScreenCapture(recArea);
} catch (AWTException e) {
e.printStackTrace();
return null;
}
}
//Stop method
public void stop() {
gui.enableButtons();
gui.changeRecordButton(true);
//Make sure the writer has been initialized. (Not an incorrect filename or anything)
if (writer != null) {
//Close the writer
writer.close();
}
//End thread
running = false;
}
}
And here's the error that's thrown:
17:46:48.076 [Thread-2] ERROR org.ffmpeg - [mp4 # 000000000028F660] no streams
17:46:48.123 [Thread-2] ERROR com.xuggle.xuggler - Error: could not write header for container (../../../../../../../csrc/com/xuggle/xuggler/Container.cpp:827)
I tried to fix it by adding the isHeaderWritten() if statement in the stop method, but that never gets called at all, so it must be somewhere else (or within that if statement). I don't know what line of my code throws the error, because it only gives me these two errors, which point to Xuggler, not my code. When I execute this, it creates an mp4 file but its size is 0 bytes and the file won't play. I could really use some help because I have no idea what these errors even mean, so it's hard to debug them. Thanks!
We're probably going to get in trouble for not honoring the Q&A-format of this website, so I'm just going to list some things you can try.
The error you are getting regarding the header is also raised when you don't specifically call writeHeader(). You are also getting an error concerning a 'missing stream'. This suggests that Xuggler is missing some information it needs to properly add the video stream and open the writer. So start by debugging your Java application to figure out which specific line is causing the error.
Also, try rendering each output frame to a JFrame, just before you write it. This will allow you to verify whether the BufferedImages you want to write have the proper content.
The file you write to is an MP4, which will make Xuggler draw a couple of conclusions on desired output parameters, but you best not rely on that. Try setting the pixel format, bitrate, frame rate and time base yourself. This is why suggested you use a buffer: you would be able to write frames at a specific interval, which will guarantee the proper frame rate. The way you've set it up now will result in a variable frame rate, which some codecs and containers will not appreciate. The type of buffer isn't that relevant, you could even use an ArrayList. But naturally some data structures will be more efficient than others.
Some codecs and file containers are a lot more forgiving than others. So try out some other codecs as well, such as H.264. You could try changing the file container as well, but MP4 usually works fine in Xuggler.
This is unrelated to your current problem, because this has nothing to do with the output file being empty. But you should watch out for the timestamps with which you write frames. The first video frame should be at timestamp 0, but because you capture and encode in the same while-loop, the first frame will have a much higher timestamp. Also, when you pause, your application won't write any frame but the timestamp will still increase. This will cause a 'hole' in your video when you later resume recording, a small time window without any video data.
I'm using OpenCV for a object detection project. I'm trying to read frames from a stored video file using VideoCapture, but in OpenCV Java there is no current implementation. I followed instructions in this post: open video file with opencv java, to edit the source files of OpenCV Java to allow this functionality. The problem is I don't know how to recompile the files? - since I just added the downloaded opencv jar file into my eclipse project originally.
You should probably try JavaCV, an OpenCV wrapper for Java.
This post shows what you need to download/install to get things working on your system, but I'm sure you can find more updated posts around the Web.
One of the demos I present during my OpenCV mini-courses contains a source code that uses JavaCV to load a video file and display it on a window:
import static com.googlecode.javacv.cpp.opencv_core.*;
import static com.googlecode.javacv.cpp.opencv_imgproc.*;
import static com.googlecode.javacv.cpp.opencv_highgui.*;
import com.googlecode.javacv.OpenCVFrameGrabber;
import com.googlecode.javacv.FrameGrabber;
public class OpenCV_tut4
{
public static void main(String[] args)
{
FrameGrabber grabber = new OpenCVFrameGrabber("demo.avi");
if (grabber == null)
{
System.out.println("!!! Failed OpenCVFrameGrabber");
return;
}
cvNamedWindow("video_demo");
try
{
grabber.start(); // initialize video capture
IplImage frame = null;
while (true)
{
frame = grabber.grab(); // capture a single frame
if (frame == null)
{
System.out.println("!!! Failed grab");
break;
}
cvShowImage("video_demo", frame);
int key = cvWaitKey(33);
if (key == 27) // ESC was pressed, abort!
break;
}
}
catch (Exception e)
{
System.out.println("!!! An exception occurred");
}
}
}
I am trying to merge some pptx documents programmatically using java. I figured out how to do this in essence using Apache POI but the documents I am trying to merge do not work.
After significant searching and trial and error I figured out that the reason for this is that the pptx documents do not have theme information (i.e., if I click into powerpoint and check the slide master view it's blank). If I goto the themes in the Design Ribbon and select 'office theme' or another theme then save. the files will merge charmingly. Otherwise, I run into the following error:
Exception in thread "main" java.lang.IllegalArgumentException: Failed to fetch default style for otherStyle and level=0
at org.apache.poi.xslf.usermodel.XSLFTextParagraph.getDefaultMasterStyle(XSLFTextParagraph.java:1005)
at org.apache.poi.xslf.usermodel.XSLFTextParagraph.fetchParagraphProperty(XSLFTextParagraph.java:1029)
at org.apache.poi.xslf.usermodel.XSLFTextParagraph.isBullet(XSLFTextParagraph.java:654)
at org.apache.poi.xslf.usermodel.XSLFTextParagraph.copy(XSLFTextParagraph.java:1044)
at org.apache.poi.xslf.usermodel.XSLFTextShape.copy(XSLFTextShape.java:631)
at org.apache.poi.xslf.usermodel.XSLFSheet.appendContent(XSLFSheet.java:358)
at com.apsiva.main.Snippet.main(Snippet.java:28)
The following is the code I ran:
package com.apsiva.main;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import org.apache.poi.xslf.usermodel.SlideLayout;
import org.apache.poi.xslf.usermodel.XMLSlideShow;
import org.apache.poi.xslf.usermodel.XSLFSlide;
import org.apache.poi.xslf.usermodel.XSLFSlideLayout;
public class Snippet {
/** Merge the pptx files in the array <decks> to the desired destination
* chosen in <outputPath> */
public static void main(String[] args) {
try {
FileInputStream empty = new FileInputStream("C:/Users/Alex/workspace/OutputWorker/tmp/base2.pptx");
XMLSlideShow pptx;
pptx = new XMLSlideShow(empty);
XSLFSlideLayout defaultLayout = pptx.getSlideMasters()[0].getLayout(SlideLayout.TITLE_AND_CONTENT);
FileInputStream is = new FileInputStream("C:/Users/Alex/workspace/OutputWorker/tmp/noWork.pptx");
// FileInputStream is = new FileInputStream("C:/Users/Alex/workspace/OutputWorker/tmp/works2.pptx");
XMLSlideShow src = new XMLSlideShow(is);
is.close();
for (XSLFSlide srcSlide: src.getSlides()){
pptx.createSlide(defaultLayout).appendContent(srcSlide);
}
FileOutputStream out = new FileOutputStream("C:/POI-TEST-OUTPUT.pptx");
pptx.write(out);
out.close();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
I want to get these files to merge and I believe the solution is to programmatically assign the theme to the files. How can it be done?
Thank you for your consideration!
In some cases when you have generated pptx files (ex. JasperReport exports) then some invalid values might be added for different fields. For example line spacing, which can be percent, and special characters, and the apache poi xslf doesn't know how to handle these values. When opening the file, PowerPoint automatically adjusts these values to valid ones. When using apache poi, you have to individually identify these fields and adjust them manually.
I had a similar issue, but with line spacing, and did a workaround, by setting the values for each paragraph like this:
List<XSLFShape> shapes = srcSlide.getShapes();
for (XSLFShape xslfShape: shapes) {
if (xslfShape instanceof XSLFTextShape){
List<XSLFTextParagraph> textParagraphs = ((XSLFTextShape) xslfShape).getTextParagraphs();
for (XSLFTextParagraph textParagraph: textParagraphs) {
textParagraph.setLineSpacing(10d);
}
}
}
This worked like a charm.
A more effective way to do this is to do it directly on the XML object:
List<CTShape> ctShapes = srcSlide.getXmlObject().getCSld().getSpTree().getSpList();
for (CTShape ctShape : ctShapes) {
List<CTTextParagraph> ctTextParagraphs = ctShape.getTxBody().getPList();
for (CTTextParagraph paragraph : ctTextParagraphs) {
if (paragraph.getPPr().getLnSpc() != null) {
paragraph.getPPr().unsetLnSpc();
}
}
}
/ApachePOI/src/ooxml/java/org/apache/poi/xslf/usermodel/XSLFTextParagraph.java
CTTextParagraphProperties getDefaultMasterStyle()
add
if( o.length == 0 ) {
return null;
}
I know this is a repeat question.
check original one here or here.
So my code is just the copy paste :
import javafx.scene.media.*;
class Gui {
public static void main(String[] args) {
try{
Media hit = new Media("skin.mp3");
MediaPlayer mediaPlayer = new MediaPlayer(hit);
mediaPlayer.play();
}catch(Exception e){
e.printStackTrace();
}
}
}
The exception which i'm getting is :
java.lang.IllegalArgumentException: uri.getScheme() == null!
at com.sun.media.jfxmedia.locator.Locator.<init>(Locator.java:217)
at javafx.scene.media.Media.<init>(Media.java:364)
at Gui.main(gui.java:6)
I'm compiling & running it correctly i.e. by including the jfxrt.jar file in classpath
Note: I'm just using notepad instead of any IDE.
So can anyone tell me the reason of IllegalArgumentException
Thankx
UPDATE : By using file://e:/skin.mp3 it worked fine but left me with another exception :
MediaException: MEDIA_INACCESSIBLE : e
at javafx.scene.media.Media.<init>(Unknown Source)
at Gui.main(gui.java:6)
So if you can put some light on this exception.
By the way i've checked the song, its not corrupt because it is playing nicely in vlc.
From the JavaFX API docs
The supplied URI must conform to RFC-2396 as required by java.net.URI.
Only HTTP, FILE, and JAR URIs are supported.
So, I suspect from reading the docs, you need to supply a URI path.
Something like file://path/to/file/skin.mp3 will probably work.
There are a few problems with the code in this question.
The class needs to be public.
JavaFX 2 applications need to extend the Application class.
JavaFX 2 applications should define a start method.
The locator for the media being created should be a full URI as noted by MadProgrammer.
Even though the question has a javafx-2 tag, I wonder if it is written for JavaFX 1.x JavaFX Script (which is now an unsupported programming language and incompatible with JavaFX 2). If so, I'd recommend coding in Java and using JavaFX 2.x for this rather than JavaFX Script.
On Windows a file representation of an absolute locator of a URI has three slashes after the file protocol. For example, the following is valid:
file:///C:/Users/Public/Music/skin.mp3
For some reason, a single slash will also work (I guess internally Java will interpolate the extra // for the protocol specifier on files or perhaps there is something I don't understand in the URL specification which means that you don't need a // after the protocol).
file:/C:/Users/Public/Music/skin.mp3
One way to check the file uri for something is valid to ask if the file uri exists
System.out.println("File " + filename + " exists? " + new File(filename).exists());
After you know your file uri is valid, you can convert it to a string using.
file.toURI().toURL().toExternalForm()
Here is a short sample program for playing some audio in JavaFX using a MediaPlayer with a little bit of error handling, so that it is easier to understand if something goes wrong.
import java.io.File;
import java.net.MalformedURLException;
import javafx.application.Application;
import javafx.scene.Scene;
import javafx.scene.control.Label;
import javafx.scene.layout.StackPane;
import javafx.scene.media.*;
import javafx.scene.paint.Color;
import javafx.stage.Stage;
/** plays an audio in JavaFX 2.x */
public class SimpleAudioPlayer extends Application {
public static void main(String[] args) { launch(args); }
#Override public void start(Stage stage) throws MalformedURLException {
final Label status = new Label("Init");
MediaPlayer mediaPlayer = createMediaPlayer(
"C:/Users/Public/Music/Sample Music/Future Islands - Before the Bridge.mp3",
status
);
StackPane layout = new StackPane();
layout.getChildren().addAll(status);
stage.setScene(new Scene(layout, 600, 100, Color.CORNSILK));
stage.show();
if (mediaPlayer != null) {
mediaPlayer.play();
}
}
/**
* creates a media player using a file from the given filename path
* and tracks the status of playing the file via the status label
*/
private MediaPlayer createMediaPlayer(final String filename, final Label status) throws MalformedURLException {
File file = new File(filename);
if (!file.exists()) {
status.setText("File does not exist: " + filename);
}
final String mediaLocation = file.toURI().toURL().toExternalForm();
Media media = new Media(mediaLocation);
MediaPlayer mediaPlayer = new MediaPlayer(media);
mediaPlayer.setOnError(new Runnable() {
#Override public void run() {
status.setText("Error");
}
});
mediaPlayer.setOnPlaying(new Runnable() {
#Override public void run() {
status.setText("Playing: " + mediaLocation);
}
});
mediaPlayer.setOnEndOfMedia(new Runnable() {
#Override public void run() {
status.setText("Done");
}
});
return mediaPlayer;
}
}
Here is a link to an additional example of a JavaFX 2.x media player which plays all of the mp3 files in a given directory sequentially.