Je veux obtenir un échantillon d'image (jpeg) à partir d'un fichier vidéo (mov) avec Java. Y a-t-il un moyen facile de faire ceci. Lorsque je recherche dans google, tout ce que je peux trouver est de faire du mov à partir de plusieurs jpgs. Je ne sais pas, je ne trouve peut-être pas les bons mots clés.
Xuggler fait le travail. Ils donnent même un exemple de code qui fait exactement ce dont j'ai besoin. Le lien est ci-dessous
Et j'ai modifié le code dans ce lien de sorte qu'il enregistre uniquement la première image de la vidéo.
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;
}
}
}
Je sais que la question d'origine est résolue, néanmoins, je poste cette réponse au cas où quelqu'un d'autre serait coincé comme je l'ai fait.
Depuis hier, j'ai tout essayé et je veux dire tout pour le faire. Toutes les Java sont obsolètes, ne sont plus maintenues ou manquent de documentation utilisable (sérieusement ??!?!)
J'ai essayé JFM (ancien et inutile), JCodec (pas de documentation du tout), JJMpeg (semble prometteur mais est très difficile et lourd à utiliser en raison du manque de documentation de classe Java), de versions OpenCV auto-Java et de quelques autres bibliothèques dont je ne me souviens pas.
Enfin, j'ai décidé de jeter un œil aux classes de JavaCV ( lien Github ) et le tour est joué! Il contient des liaisons FFMPEG avec des documentations détaillées.
<dependency>
<groupId>org.bytedeco</groupId>
<artifactId>javacv</artifactId>
<version>1.0</version>
</dependency>
Il s'avère qu'il existe un moyen très simple d'extraire des images vidéo d'un fichier vidéo vers un BufferedImage
et, par extension, un fichier JPEG. La classe FFmpegFrameGrabber pourrait être facilement utilisée pour saisir des images individuelles et les convertir en BufferedImage
. Un exemple de code est le suivant:
FFmpegFrameGrabber g = new FFmpegFrameGrabber("textures/video/anim.mp4");
g.start();
for (int i = 0 ; i < 50 ; i++) {
ImageIO.write(g.grab().getBufferedImage(), "png", new File("frame-dump/video-frame-" + System.currentTimeMillis() + ".png"));
}
g.stop();
Fondamentalement, ce code vide les 50 premières images de la vidéo et les enregistre en tant que fichier PNG. La bonne chose est que la fonction de recherche interne fonctionne sur les images réelles et non sur les images clés (un problème que j'ai eu avec JCodec)
Vous pouvez vous référer à la page d'accueil de JavaCV pour en savoir plus sur les autres classes qui peuvent être utilisées pour capturer des cadres à partir de WebCams, etc. J'espère que cette réponse vous aidera :-)
Voici comment avec 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...
}
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();
}
}
}
peut-être que cela vous aidera:
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
pour plus d'informations:
Ci-dessous, il est montré le code essentiel pour demander des trames à partir de fichiers multimédias.
Pour le code source complet et la démonstration vidéo:
"Traitement des fichiers multimédias" exemple utilisant Framework Marvin ..
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();
}
}