2016-07-05 93 views
8

Sto provando a catturare screenshot video da un'applicazione java. Ho scaricato la libreria sarxos/webcam-capture. Ho aggiunto al mio progetto il jar eseguibile. È un po 'confuso. Voglio catturare video da una semplice interfaccia javafx che ho creato. Il problema è che dopo aver installato lib e slf4 è stato necessario installare anche xuggle. Aggiungo xuggle nel percorso e il mio codice è il seguente:Cattura video utilizzando la webcam in Java

File file = new File("output.ts"); 

IMediaWriter writer = ToolFactory.makeWriter(file.getName()); 
Dimension size = WebcamResolution.QVGA.getSize(); 

writer.addVideoStream(0, 0, ICodec.ID.CODEC_ID_H264, size.width, size.height); 

Webcam webcam = Webcam.getDefault(); 
webcam.setViewSize(size); 
webcam.open(true); 

long start = System.currentTimeMillis(); 

for (int i = 0; i < 50; i++) { 

    System.out.println("Capture frame " + i); 

    BufferedImage image = ConverterFactory.convertToType(webcam.getImage(), BufferedImage.TYPE_3BYTE_BGR); 
    IConverter converter = ConverterFactory.createConverter(image, IPixelFormat.Type.YUV420P); 

    IVideoPicture frame = converter.toPicture(image, (System.currentTimeMillis() - start) * 1000); 
    frame.setKeyFrame(i == 0); 
    frame.setQuality(0); 

    writer.encodeVideo(0, frame); 

    // 10 FPS 
    Thread.sleep(100); 
} 

writer.close(); 

System.out.println("Video recorded in file: " + file.getAbsolutePath()); 

Tuttavia mi sto ricevendo il seguente:

Caused by: java.lang.UnsatisfiedLinkError: no xuggle-ferry in java.library.path 

EDIT2 Ho provato anche la biblioteca JxCapture. Aggiungo al mio progetto tutte le librerie necessarie corro il seguente codice: enter link description here, il codice ha funzionato bene riesco a memorizzare il video, però, alla fine, sto ricevendo il seguente errore:

8614 [JNIWrapper.ShutdownHook] ERROR com.jniwrapper.NativeResourceCollector - com.jniwrapper.FunctionExecutionException: Callback parameter types or their count are not correct at com.jniwrapper.Function.invokeVirtualFunc(Native Method)

Qualsiasi idea di cosa errore riguarda ?? Cos'è JNIWrapper.ShutdownHook? Ho provato il codice in 3 macchine diverse e questo è successo solo a uno di loro? Come posso gestire questa eccezione?

EDIT3: ho provato la proposta @bianite EDIT3. La GUI iniziato e ho due pulsanti di inizio e fine il pulsante di avvio ha aperto la macchina fotografica e quando ho provato a smettere ho ricevuto la seguente:

java.lang.NullPointerException: Pointer address of argument 0 is NULL. at org.bytedeco.javacpp.opencv_videoio$VideoWriter.write(Native Method) at org.bytedeco.javacv.OpenCVFrameRecorder.record(OpenCVFrameRecorder.java:105) at Test1.lambda$0(Test1.java:52) at java.lang.Thread.run(Unknown Source)

+0

Che cosa si intende per 'aggiungo xuggle nel percorso'? Come ho capito, ha le sue dipendenze e ha bisogno di alcuni binari precompilati, che è necessario fornire manualmente nel caso in cui non si usi Maven o qualcosa del genere. – whitesite

+0

Aggiungo al mio progetto eclipse webcam-capture quindi xuggle_3.4 poi slf4j e bridj-0.6.2. Non so cos'altro dovrei aggiungere. –

+1

Fondamentalmente, ['UnsatisfiedLinkError'] (https://docs.oracle.com/javase/8/docs/api/java/lang/UnsatisfiedLinkError.html) significa che xuggle non riesce a trovare le librerie richieste. Se leggi [xuggle download instructions] (http://www.xuggle.com/downloads), vedrai che devi fornire tutte le sue dipendenze e binari precompilati. Usare Maven sarebbe molto più facile. – whitesite

risposta

4

Ti manca slf4-api-ver.jar nel classpath. Ad ogni modo aggiungendo solo l'API non sarà sufficiente avrete anche bisogno di un provider come slf4j-simple-ver.jar. L'ultima a disposizione sono la versione 1.7.21 e può essere scaricata da qui http://www.slf4j.org/download.html

+0

Ho scaricato il file zip e aggiungo semplicemente slf4j-simple-1.7.21.jar al mio progetto. Ancora ho avuto lo stesso errore :(! –

+0

Hai letto questo https://github.com/sarxos/webcam-capture/issues/114? –

+0

Sì, ma ho ancora errori. –

4

Ok, questo è quello che ho ottenuto con questa JavaCV library e loro esempi:

public class Test extends Application { 

public void start(Stage primaryStage) throws Exception { 

    OpenCVFrameGrabber capture = OpenCVFrameGrabber.createDefault(0); 
    capture.start(); 

    OpenCVFrameConverter.ToIplImage converter = new OpenCVFrameConverter.ToIplImage(); 
    Java2DFrameConverter javaConverter = new Java2DFrameConverter(); 

    VBox root = new VBox(); 
    Canvas canvas = new Canvas(); 
    canvas.setHeight(capture.getImageHeight()); 
    canvas.setWidth(capture.getImageWidth()); 
    root.getChildren().add(canvas); 
    Scene scene = new Scene(root, capture.getImageWidth(), capture.getImageHeight()); 

    primaryStage.setTitle("Live video"); 
    primaryStage.setScene(scene); 
    primaryStage.show(); 

    Thread videoProcessor = new Thread(() -> { 
     File output = new File("C:/Work/test.avi"); 
     OpenCVFrameRecorder recorder = new OpenCVFrameRecorder(output, capture.getImageWidth(), capture.getImageHeight()); 
     try { 
      recorder.setVideoCodec(opencv_videoio.CV_FOURCC((byte) 'M', (byte) 'J', (byte) 'P', (byte) 'G')); 
      recorder.start(); 
      while (true) { 
       if(Thread.currentThread().isInterrupted()){ 
        break; 
       } 
       Frame frame = capture.grab(); 
       Platform.runLater(()->{ 
        BufferedImage image = javaConverter.getBufferedImage(frame, 1.0, false, null); 
        canvas.getGraphicsContext2D().drawImage(SwingFXUtils.toFXImage(image, null),0,0); 
       }); 
       recorder.record(frame); 
      } 
      recorder.stop(); 
      capture.release(); 
      recorder.release(); 
     } catch (Exception e) { 
      e.printStackTrace(); 
     } 
    }); 

    primaryStage.setOnCloseRequest(e->{ 
     videoProcessor.interrupt(); 
    }); 

    videoProcessor.start(); 

} 

public static void main(String[] args) throws Exception { 
    launch(args); 
} 

} 

Cattura video da web cam e lo traduce dal vivo e nello stesso tempo scrive su file. È necessario includere la loro libreria in classpath usando Maven o l'installazione manuale e anche tutti i vasi dall'archivio zip binario. Forse non hai bisogno di tutti loro, ma non ho scavato in profondità.
È possibile giocare con le impostazioni e ricercare esempi e fonti. Da quello che ho visto è una libreria piuttosto potente.
Modifica
Proprio il video parte di elaborazione:

Thread videoProcessor = new Thread(() -> { 
     OpenCVFrameGrabber capture = null; 
     FrameRecorder recorder = null; 
     try { 

      File output = new File("C:/Work/test2.avi"); 
      capture = OpenCVFrameGrabber.createDefault(0); 
      capture.start(); 
      recorder = FrameRecorder.createDefault(output, capture.getImageWidth(), capture.getImageHeight()); 
      recorder.setFrameRate(8); 
      recorder.setVideoCodec(opencv_videoio.CV_FOURCC((byte) 'M', (byte) 'J', (byte) 'P', (byte) 'G')); 
      recorder.start(); 
      long l = System.currentTimeMillis(); 
      while (true) { 
       if(Thread.currentThread().isInterrupted()){ 
        break; 
       } 
       recorder.record(capture.grab()); 

      } 
     } catch (Exception e) { 
      e.printStackTrace(); 
     } finally { 
      try { 
       recorder.stop(); 
       capture.release(); 
       recorder.release(); 
      } catch (Exception e) { 
       e.printStackTrace(); 
      } 
     } 
    }); 

devi avviare il processo videoProcessor.start() da qualche parte e poi interromperlo per interrompere la registrazione videoProcessor.interrupt(). Potrebbe anche essere necessario impostare la corretta frequenza dei fotogrammi del registratore per regolarla sui fps della fotocamera.
Edit 2
Codice di dispositivi disponibili di uscita:

int n = org.bytedeco.javacpp.videoInputLib.videoInput.listDevices(); 
for (int i = 0; i < n; i++) { 
    System.out.println(i + " = " + org.bytedeco.javacpp.videoInputLib.videoInput.getDeviceName(i)); 
} 

Edit 3
Se lavori webcam-acquisizione, che si può usare per catturare immagini e utilizzare javaCV per registrare queste immagini in file video (più o meno come l'esempio nella tua domanda, solo javaCV invece di xuggler).Questa è una piccola applicazione JavaFX, che ha due pulsanti: 'Start' inizia il filo videoProcessing per catturare video e gli interrupt 'Stop' questa discussione:

import com.github.sarxos.webcam.Webcam; 
import javafx.application.Application; 
import javafx.scene.Scene; 
import javafx.scene.control.Button; 
import javafx.scene.layout.VBox; 
import javafx.stage.Stage; 
import org.bytedeco.javacpp.opencv_videoio; 
import org.bytedeco.javacv.Java2DFrameConverter; 
import org.bytedeco.javacv.OpenCVFrameRecorder; 


import java.awt.Dimension; 
import java.awt.image.BufferedImage; 
import java.io.File; 

public class Test1 extends Application { 

public void start(Stage primaryStage) throws Exception { 

    final double FPS = 25; 
    final int WIDTH = 640; 
    final int HEIGHT = 480; 
    Webcam webcam = Webcam.getDefault(); 
    webcam.setViewSize(new Dimension(WIDTH, HEIGHT)); 

    Java2DFrameConverter javaConverter = new Java2DFrameConverter(); 

    VBox root = new VBox(); 
    Button b1 = new Button("Start"); 
    Button b2 = new Button("Stop"); 

    root.getChildren().addAll(b1, b2); 
    Scene scene = new Scene(root, 300,200); 
    primaryStage.setTitle("Test"); 
    primaryStage.setScene(scene); 

    Runnable r =() -> { 
     File output = new File("C:/Work/test.avi"); 
     OpenCVFrameRecorder recorder = new OpenCVFrameRecorder(output, WIDTH, HEIGHT); 
     recorder.setFrameRate(FPS); 
     try { 
      recorder.setVideoCodec(opencv_videoio.CV_FOURCC((byte) 'M', (byte) 'J', (byte) 'P', (byte) 'G')); 
      recorder.start(); 
      webcam.open(); 
      while (true) { 
       if(Thread.currentThread().isInterrupted()){ 
        break; 
       } 
       BufferedImage image = webcam.getImage(); 
       recorder.record(javaConverter.getFrame(image)); 
       try { 
        Thread.sleep(1000/(long)FPS); 
       } catch (InterruptedException ie) { 
        break; 
       } 
      } 
      recorder.stop(); 
      recorder.release(); 
      webcam.close(); 
     } catch (Exception e) { 
      e.printStackTrace(); 
     } 
    }; 

    b1.setOnAction(e->{ 
     Thread t = new Thread(r); 
     t.start(); 
     b2.setOnAction(e2->t.interrupt()); 
    }); 

    primaryStage.show(); 
} 

public static void main(String[] args) throws Exception { 
    launch(args); 
} 

} 
+0

Come posso catturare solo il video, io sono poco confuso da tutto quel codice, voglio solo archiviare sul mio disco rigido il video –

+0

@JoseRamon Usa solo la parte di elaborazione video Vedi la modifica – whitesite

+0

Ho provato il codice. Quando ho il codice all'interno della discussione non funziona su tutto.Se uso il codice senza il filo la mia macchina fotografica si apre solo per un fotogramma e quindi si sta chiudendo senza il video da memorizzare –

Problemi correlati