How to extract a frame from video using Java - java

Is there any solution to "Extract a frame from video file in Java using core library without importing external libraries"?
Say for I saw Image, BufferedStrategy, BufferCapabilities in Java AWT libraries.

The Java Media Framework API (JMF) enables audio, video and other time-based media operations, without use of any third party library.
Seeking frames inside a movie with JMF.
xuggler is a good third party library, widely used.

I think that you should use Xuggler from here or you can find it in maven.
In the github repository is a sample under demos with the file:
DecodeAndCaptureFrames.java

According to this answer on another question, you can do that without external libraries by leveraging features of JavaFX.
Quoting original answer below:
You can use the snapshot() of MediaView. First connect a mediaPlayer
to a MediaView component, then use mediaPlayer.seek() to seek the
video position. And then you can use the following code to extract the
image frame:
int width = mediaPlayer.getMedia().getWidth();
int height = mediaPlayer.getMedia().getHeight();
WritableImage wim = new WritableImage(width, height);
MediaView mv = new MediaView();
mv.setFitWidth(width);
mv.setFitHeight(height);
mv.setMediaPlayer(mediaPlayer);
mv.snapshot(null, wim);
try {
ImageIO.write(SwingFXUtils.fromFXImage(wim, null), "png", new File("/test.png"));
} catch (Exception s) {
System.out.println(s);
}

Related

How to put FFmpeg ffplay frame into my own Java application?

I am getting live video feedback from Parrot AR.Drone 2.0. I am able to get the incoming video streams from drone(using command-ffplay tcp://192.168.1.1:5555) and successfully output the live video for me. I notice that ffplay will display its own frame along with the live video.
So, is that possible to "direct" or put the frame into our own Java frame in application? How could I achieve that if I wish to implement that function in my own JCheckBox? E.G. If I click JCheckBox, it should automatically get live video streams from drone and display for me in application instead of using ffplay frame?
This question is old but I just found it so I decided to write a possible solution for other users.
There are to ways to solve this one wrapping yourself the FFmpeg CLI for Java or using a wrapped FFmpeg library. The former will take a quite time and effort to make it. While the latter will be more practical to use.
For example, a nice library is JavaCV. You just need to add the maven repository to your project using the pom.xml file:
<dependency>
<groupId>org.bytedeco</groupId>
<artifactId>javacv-platform</artifactId>
<version>1.4.3</version>
</dependency>
Then you can create a SimplePlayer class and use the FFmpegFrameGrabber class to decode a frame that is converted into an image and displayed in your Java app.
public class SimplePlayer
{
private static volatile Thread playThread;
private AnimationTimer timer;
private int counter;
public SimplePlayer(String source, GrabberListener grabberListener)
{
if (grabberListener == null) return;
if (source.isEmpty()) return;
counter = 0;
playThread = new Thread(() -> {
try {
FFmpegFrameGrabber grabber = new FFmpegFrameGrabber(source);
grabber.start();
grabberListener.onMediaGrabbed(grabber.getImageWidth(), grabber.getImageHeight());
Java2DFrameConverter converter = new Java2DFrameConverter();
while (!Thread.interrupted()) {
Frame frame = grabber.grab();
if (frame == null) {
break;
}
if (frame.image != null) {
Image image = SwingFXUtils.toFXImage(converter.convert(frame), null);
Platform.runLater(() -> {
grabberListener.onImageProcessed(image);
});
}
grabber.stop();
grabber.release();
Platform.exit();
} catch (Exception exception) {
System.exit(1);
}
});
playThread.start();
}
public void stop()
{
playThread.interrupt();
}
}
You can find the full implementation in this GitHub repository.
You need to decode the almost-but-not-quite H264 video format that the AR.Drone uses. To do that, you need to do two things:
Handle the AR.Drone's custom video framing, which uses headers in their PaVE format. The format is documented in section 7.3 of the AR.Drone Developer Guide, but almost any of the existing AR.Drone libraries have code to handle PaVE headers.
Decode the H264 video frames that remain. Xuggler wraps native libraries with Java, and is probably the best, fastest way to decode H264. An alternative is the h264j library, which is pure Java, but is slower and has some decoding glitches.
For more info, see these related questions:
Xuggler and playing from live stream
https://stackoverflow.com/questions/30307003/use-a-xuggler-videostream-in-javacv

Playing media files using JAVA

I want to build a tread safe JAVA application which:
Play *.mp4 or other format HD media files (full-screen mode 1920x1080)
Add event bindings to applet (I'll be using touchscreen monitor)
I tried to search a lot, but found only outdated examples of JMF (VLCJ and etc.).
So I want you to ask from where to start building this applet.
What libraries I can include.
I found a similar project here: Media Shuffle
But I want my media files to be located in one folder and they appear in applications as icons which start selected video (VLC fullscreen or other cross-platform media player) to play on 1st touch. The second touch have to stop player and go to the main page.
Please, share your ideas how I can do that. Any code examples would be great.
I would recommend vlcj because i am sure it has all the formats you could need or have.Its not outdated at all and easy to start with.If you want to display a video graphically i dont think you could ever find so simple instructions like you mention but if you organize all steps that i will mention and explain in more depth you will see that vlcj is the best option for handling media like that (as it goes in my opinion).I also like and recommend JavaFx because of the effects you can make with that but its too difficult for me to setup and code in that stuff.
So, lets begin.Firstly, i would like to say that i have implemented the vlcj in a Swing-based application (in Windows) but that should not make you sad because for an immediate popup player that you mention we could just make a jdialog and place the video-surface in its contentPane.
Steps
1)So the first thing that should be done is to download vlc media player (we will need the 32 bit version that plays in both 32bit or 64bit computer environments).I had a terrible month trying to configure why my app wasnt loading the required libraries succesfully and found out that when you run a jar exetutable file it runs on 32-bit jvm(in eclipse was running in 64bit jvm and everything was ok.Thats why we need 32bit version), while i had 64-bit native libraries to load from.Anyways if you download and install 32bit vlc media player make somewhere a folder to include your project(lets say "C:/MyProject") inside MyProject create another folder and call it for instance "Needed"(here we will place all the required libraries for vlcj in order to work properly).Now from the contents of C:\Program Files (x86)\VideoLAN\VLC copy the plugins directory and the 4 dlls
(axvlc.dll,libvlc.dll,libvlccore.dll,npvlc.dll) and paste them inside your Needed folder
2)Now if you work in Eclipse IDE or similar you will need to make a folder in your project (lets say "lib") and inside that create another folder( name it "jars" ).In jars folder place the following jars: jna-3.5.1.jar, platform-3.5.1.jar,vlcj-2.2.0.jar.You can find these jars from vlcj google project.And then just include them to your classpath(either select them and right-click->add to build path or go to project properties->Java build path and add those 3 jars).Thats all for setup before we begin any coding with player setup.
3) You have to load now vlcj before starting using it.I just use this code to make that possible(i will explain it shortly dont worry).
public void LoadLibrary(){
SwingWorker loadWorker;
loadWorker = new SwingWorker(){
#Override
protected Object doInBackground() throws Exception {
// TODO Auto-generated method stub
Thread.sleep(2000);
path = new File("").getAbsolutePath().toString();
path = path.replace(".", "");
path = path.replace("\\", "//");
path = path+"//Needed";
if(RuntimeUtil.isWindows()){
NativeLibrary.addSearchPath(
"libvlc",path
);
Native.loadLibrary(RuntimeUtil.getLibVlcLibraryName(), LibVlc.class);
}
else if(RuntimeUtil.isNix()){
NativeLibrary.addSearchPath(
"libvlc",path
);
}
mediaPlayerFactory = new MediaPlayerFactory();
player = mediaPlayerFactory.newEmbeddedMediaPlayer();
CanvasVideoSurface videoSurface = mediaPlayerFactory.newVideoSurface(canvas);
player.setVideoSurface(videoSurface);
return null;
}
};
loadWorker.execute();
}
So what i do is to make a thread for Swing-based apps because you cannot play media if your media canvas is not displayable and everything in the constructor is fully built when its code is done.That means that before making the player we should first create a delay(mine is 2 seconds) for our constructor to end his job and our JFrame(or jWindow or jDialog etc) to become displayable.Next i calculate my path dynamically taking the path of my runnable jar(attention: not from workspace inside Eclipse) and entering the Needed folder to implement the required native libraries.Inside the if statement i tell the system to look for the libvlc.dll in the specific path i calculated and then load it and thus make one step forward to play media files.Outside if-else statement i actually create my player and place the canvas for its VideoSurface(canvas is a Canvas java.awt Object I use WindowsCanvas because i work only in windows, you could find for linux or mac a similar canvas(dont worry about that!)) Outside the Swing-Worker field(the thread) i just telling the thread to be executed (important as a call-function instruction).
4)To play a file i just use a button somewhere in my app to call an action event each time it is pressed so that we do something inside it.I for example make a JFileChooser to choose a media file from.You can easily search for it but here is my code:
final JFileChooser chooser = new JFileChooser();
FileNameExtensionFilter filter0 = new FileNameExtensionFilter(".wav", "wav");
FileNameExtensionFilter filter1 = new FileNameExtensionFilter(".mp3","mp3");
FileNameExtensionFilter filter2 = new FileNameExtensionFilter(".mpg","mpg");
FileNameExtensionFilter filter3 = new FileNameExtensionFilter(".mp4","mp4");
FileNameExtensionFilter filter4 = new FileNameExtensionFilter(".avi","avi");
FileNameExtensionFilter filter5 = new FileNameExtensionFilter(".flv","flv");
FileNameExtensionFilter filter6 = new FileNameExtensionFilter(".wmv","wmv");
FileNameExtensionFilter filter7 = new FileNameExtensionFilter(".3gp", "3gp");
FileNameExtensionFilter filter8 = new FileNameExtensionFilter(".swf", "swf");
FileNameExtensionFilter filter9 = new FileNameExtensionFilter(".mkv", "mkv");
FileNameExtensionFilter filter10 = new FileNameExtensionFilter(".flac", "flac");
FileNameExtensionFilter filter11 = new FileNameExtensionFilter("Music & Videos","wav","mp3","mpg","mp4","avi","flv","wmv","3gp","swf","mkv","flac","VOB");
FileNameExtensionFilter filter12 = new FileNameExtensionFilter("Music","wav","mp3","flac");
FileNameExtensionFilter filter13 = new FileNameExtensionFilter(".VOB", "VOB");
FileNameExtensionFilter filter14 = new FileNameExtensionFilter("Videos","mpg","mp4","avi","flv","wmv","3gp","swf","mkv","VOB");
chooser.setFileFilter(filter14);
chooser.setFileFilter(filter2);
chooser.setFileFilter(filter3);
chooser.setFileFilter(filter4);
chooser.setFileFilter(filter5);
chooser.setFileFilter(filter6);
chooser.setFileFilter(filter13);
chooser.setFileFilter(filter7);
chooser.setFileFilter(filter8);
chooser.setFileFilter(filter9);
chooser.setFileFilter(filter12);
chooser.setFileFilter(filter0);
chooser.setFileFilter(filter1);
chooser.setFileFilter(filter10);
chooser.setFileFilter(filter11);
int returnVal = chooser.showOpenDialog(getParent());
if(returnVal == JFileChooser.APPROVE_OPTION) {
System.out.println("You chose to open this file: " +
chooser.getSelectedFile().getName());
File myfile1 = chooser.getSelectedFile();
myfilepath1 = chooser.getSelectedFile().getAbsolutePath();
}
player.startMedia("file:///"+myfilepath1);
player.pause();
Those file filters are some of the media file types that vlcj can play for u.What i do is opening a file dialog to choose a file from and if i choose a file i hold its path(usefull for saying vlcj where to look for it).
5)Now to play the file u just have to type the following code :
player.play();
Maybe inside another action event of another Button.
6) if you finish writing those all you have to do is to export your project to a runnable jar file into your MyProject folder first created and run it (attention by double-clicking it (not from console(else it will be runned with 64bit jvm and you dont want that cause you have 32 bit natives and vlcj dont accept those conflicts)))
In Conclusion,i have to say that these steps worked for me.I hope they will help you go further in your app developement.
Regards,
PeGiannOS
First you have to
// create a player to play the media specified in the URL
Player mediaPlayer = Manager.createRealizedPlayer( mediaURL );
Now
mediaPlayer.start(); // start playing the media clip
I hope it work!
VLCJ isn't outdated, it's actively developed and immensely flexible and powerful in what it can achieve. I'm using it in my application to display a number of video streams inside the application at once, as well as doing things such as text overlays simultaneously. It's sometimes tricky to do this, but definitely possible.
There are a number of basic (up-to-date) examples to get you started with VLCJ here.

Don't show file path when playing video using VLCJ

I'm using VLC and VLCJ to play video and audio files in my Java application, which works fine.
But there appears a text when playing the video; this text is the path of the played video.
I don't want it to appear when playing a video, so how do I disable this using Java?
Pass the option :no-video-title-show to disable media title on video. See http://wiki.videolan.org/VLC_command-line_help
Example using VLCJ 1.2.0:
String[] options = {
":sharpen-sigma=2.0",
":blur-factor=127",
":ipv4-timeout=3000",
":no-video-title-show",
":loop",
":file-caching="+getFileCaching(),
":sout-all",
":sout-keep"
};
gc.getMediaPlayer().setRepeat(true);
gc.getMediaPlayer().setPlaySubItems(true);
gc.getMediaPlayer().playMedia(media, options);
Update:
Recent libVLC 2.0.x changes to vout feature may cause no-video-title-show not to work on per-playitem configuration :no-video-title-show anymore and may need to be set as per-global configuration --no-video-title-show. Pass per-global configuration options in the VLCJ factory constructor MediaPlayerFactory(options) instead of mediaplayer's xxxMedia method.
libVLC 2.1 has new native API to do this - from libvlc_media_player.h:
LIBVLC_API
void libvlc_media_player_set_video_title_display( libvlc_media_player_t *p_mi, libvlc_position_t position, unsigned int timeout );
This is available in vlcj 2.4.1 - from MediaPlayer.java:
void setVideoTitleDisplay(libvlc_position_e position, int timeout);
This API should always be used in preference to using the unsupported "options" array.
Example:
mediaPlayer.setVideoTitleDisplay(libvlc_position_e.disable, 0);

How to make video in Java captured from webcam through lti-Civil CaptureDeviceStream?

Can I do it only with the lti-Civil classes or I need FMJ or JMF ?
do I use the actual Stream or set of captured Images from CaptureObserver?
Thanks.
captureStream = system.openCaptureDeviceStream(info.getDeviceID());
captureStream.setObserver(new CaptureObserver(){
public void onError(CaptureStream arg0, CaptureException arg1) {
}
public void onNewImage(CaptureStream streamSource, Image image) {
try
{
imageFrame.setImage(AWTImageConverter.toBufferedImage(image));
bufferedImage = AWTImageConverter.toBufferedImage(image);
}
catch (Throwable t)
{ t.printStackTrace(); }
}
});
captureStream.start();
If I understand your question correctly, the introduction on Lti-civil site have the answer:
LTI-CIVIL is a Java library for capturing images from a video source such as a USB camera. It provides a simple API and does not depend on or use JMF! The FMJ project integrates LTI CIVIL into the JMF architecture by providing a civil: datasource. For more information, visit screenshots and project status sections of this website
As far as I can see your code is not using any JMF specific classes so the above code should work with plain LTI-CIVIL.
EDIT:
Based on your clarification, I think you will need additional support for encoding the video as LTI-CIVIL seems to be focused solely on capturing. Out of FMJ and JMF, FMJ is probably a better choice as JMF's development appears to be ceased. For other alternatives see this section of wikipedia article about JMF

How to play sound in JavaFX?

I'm experimenting with JavaFX making a small game.
I want to add sound.
How?
I tried MediaPlayer with media defined with relative source attribute like:
attribute media = Media{
source: "{__FILE__}/sound/hormpipe.mp3"
}
attribute player = MediaPlayer{
autoPlay:true
media:media
}
It doesn't play.
I get
FX Media Object caught Exception com.sun.media.jmc.MediaUnavailableException: Media unavailable: file: ... Sound.class/sound/hormpipe.mp3
Just a guess, but is that file "hornpipe.mp3" and not "hormpipe.mp3" (with an m)?
var player = javafx.scene.media.MediaPlayer {
repeatCount: javafx.scene.media.MediaPlayer.REPEAT_FOREVER
media: Media { source: "{\_\_DIR\_\_}clip.wav"
};
};
player.play();
You have to incluye the audio file in the build/compiled directory so Netbeans can pack it into the jar file.
Just a guess, but I think your {__FILE__} will expand to the name of your file. Try replacing it with {__DIR__}.
Also note that {__DIR__} includes the trailing /, so try this instead:
attribute media = Media{
source: "{__DIR__}sound/hormpipe.mp3"}
EDIT: I did some digging, and apparently, the source of a Media object has to be either a remote URL, or an absolute file path, since media files aren't allowed in JARs (something I hope gets changed with future releases, since I really like JavaFX and want to be able to make desktop apps with it). See: JavaFX FAQs.
This worked for me:
MediaPlayer audio = new MediaPlayer(
new Media(
new File("file.mp3").toURI().toString()));
Source file should be in project's root directory (not src, not dist).
OK, having used this question to get MP3 audio working (kinda), I've learned the following (not much).
1) Audio for compressed formats is very platform dependent. My continually upgraded Mint 17.1->18 machine plays mp3 fine using Media and MediaPlayer. Fresh installs of Mint 18 won't (with the dev tools).
So use .wav files.
Media sound=new Media(new File("noises/roll.wav").toURI().toString());
MediaPlayer mediaPlayer=new MediaPlayer(sound);
mediaPlayer.play();
2) One of the things you need to be aware of with Media/MediaPlayer is that in order to play multiple times (repeatedly or all at once ie, on a button press/whatever in a game) you have to spawn N number of MediaPlayer objects, and each one will play once and then stop.
So use javafx.scene.media.AudioClip
AudioClip soundMyNoise = new AudioClip(new File("noises/roll.wav").toURI().toString());
soundMyNoise.play();
AudioClip also has its issues, which include storing the raw audio data in RAM all at once instead of buffering. So there is the possibility of excessive memory use.
No matter which method you end up going with, one thing to be critically aware of was mentioned by daevon earlier - the path issue. With NetBeans, you have NetBeansProjects/yourproject/src/yourproject/foo.java. The sounds in the example above go in NetBeansProjects/yourproject/noises/roll.wav

Categories

Resources