Gravar vídeo com WebCam

Já procurei em vários tópicos mas não estou conseguindo achar uma resposta.

Meu atual formulário GUI mostra a imagem da webcam e é possível tirar fotos e salva-las no computador. Porém eu queria que quando o usuário apertasse ‘Gravar’ começasse a gravar e o botoão mudasse para ‘Parar’. Quando ele clicar de novo a gravação para e salva o arquivo.

As outras coisas eu sei fazer, como os Botões e o JFileChooser, mas eu só queria saber COMO GRAVAR?
OBS: Para tirar fotos uso o JFM.

Abraços, Gustavo Borba.

Sera que isto ajuda…
http://www.humatic.de/htools/dsj.htm
t+

E em JFM, não haveria um jeito?

Boa noite a todos.

Depois de voce intalar o Java Media Framework (JMF), baixe-o no link abaixo, voce então pode usar o código logo a seguir:

http://java.sun.com/javase/technologies/desktop/media/jmf/2.1.1/download.html.


import java.awt.Image;
import java.awt.BorderLayout;
import java.awt.Component;
import java.awt.GridLayout;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.image.RenderedImage;
import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import javax.imageio.ImageIO;
import javax.media.Buffer;
import javax.media.CaptureDeviceInfo;
import javax.media.CaptureDeviceManager;
import javax.media.Manager;
import javax.media.MediaLocator;
import javax.media.Player;
import javax.media.control.FrameGrabbingControl;
import javax.media.format.VideoFormat;
import javax.media.util.BufferToImage;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JOptionPane;
import javax.swing.JPanel;
import javax.swing.JRootPane;

public class WebCamCapture extends JFrame implements ActionListener {

    private static final long serialVersionUID = 1L;
    private Player player;
    private CaptureDeviceInfo di;
    private MediaLocator ml;
    private JPanel painelbotoes;
    private JButton start = null;
    private JButton capture = null;
    public JButton clearimage = null;
    public JButton confirm = null;
    public Buffer buf = null;
    public Image img = null;
    // public VideoFormat vf = null;
    public BufferToImage btoi = null;
    public Component webcam = null;

    public static void main(String args[]){
        JFrame wcam = new WebCamCapture();
        wcam.setTitle("Captura de Imagem");
    }

    public WebCamCapture(){
        setUndecorated(true);
        getRootPane().setWindowDecorationStyle(JRootPane.FRAME);
        setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        setLayout(new BorderLayout());
        painelbotoes = new JPanel();
        painelbotoes.setLayout(new GridLayout(1,4));
        start = new JButton("Iniciar");
        start.addActionListener(this);
        capture = new JButton("Capture");
        capture.addActionListener(this);
        capture.setEnabled(false);
        clearimage = new JButton("Limpar");
        clearimage.addActionListener(this);
        clearimage.setEnabled(false);
        confirm = new JButton("Gravar");
        confirm.addActionListener(this);
        confirm.setEnabled(false);
        painelbotoes.add(start);
        painelbotoes.add(capture);
        painelbotoes.add(clearimage);
        painelbotoes.add(confirm);
        add(painelbotoes, BorderLayout.NORTH);
        di = CaptureDeviceManager.getDevice("vfw//0");
        ml = new MediaLocator("vfw://0");
        pack();
        this.setSize(400,400);
        this.setLocationRelativeTo(this);
        this.setVisible(true);
    }

    public void playerClose(){
        player.close();
        player.deallocate();
        player = null;
    }

    public void actionPerformed(ActionEvent e){
        if (e.getSource()==start){
            try {
                player = Manager.createRealizedPlayer(ml);
                webcam = player.getVisualComponent();
                if (webcam!=null) add(webcam, BorderLayout.CENTER);
                player.start();
                validate();
            } catch(Exception ex){
                JOptionPane.showMessageDialog(null,"Não foi possível conectar ao dispositivo de captura\n"+ex.getMessage());
                ex.printStackTrace();
            }
            start.setEnabled(false);
            capture.setEnabled(true);
        } else if (e.getSource()==capture){
            FrameGrabbingControl fgc=(FrameGrabbingControl)player.getControl("javax.media.control.FrameGrabbingControl");
            buf = fgc.grabFrame();
            btoi = new BufferToImage((VideoFormat)buf.getFormat());
            img = btoi.createImage(buf);
            playerClose();
            capture.setEnabled(false);
            clearimage.setEnabled(true);
            confirm.setEnabled(true);
        } else if (e.getSource()==clearimage){
            remove(webcam);
            webcam = null;
            clearimage.setEnabled(false);
            confirm.setEnabled(false);
            start.setEnabled(true);
        } else if (e.getSource()==confirm){
            gravaImg(img);
            System.exit(0);
        }
    }

    public void gravaImg(Image imagem){
        File arquivo = new File("C:/Temp/Teste.jpg");
        try {
            if (!arquivo.exists()){
              FileOutputStream fo = new FileOutputStream(arquivo);
            }
            ImageIO.write((RenderedImage)imagem, "JPG", arquivo);
        } catch(IOException ex){
            JOptionPane.showMessageDialog(null, "Não foi possível encontrar o caminho especificado");
            ex.printStackTrace();
        }
    }

}

Execute e vê se é o que voce queria.

A jmf usa o vídeo for windows(vfw), que está para ser excluído das próximas versões do windows(7 em diante). A dsj usa directshow e pinta o vídeo em cima do direct3d, com a vmr9. Além da dsj ser bem mais simples de se usar.

A aplicação abaixo realiza uma simples captura para um arquivo de vídeo.

[code]/**
dsj demo code.
You may use, modify and redistribute this code under the terms laid out in the header of the DSJDemo application.
copyright 2005-7
N.Peters
humatic GmbH
Berlin, Germany
**/

import de.humatic.dsj.*;

public class SimpleCapture implements java.beans.PropertyChangeListener {

private DSCapture graph;

public SimpleCapture() {}

public void createGraph() {

	javax.swing.JFrame f = new javax.swing.JFrame("dsj SimpleCapture");

	DSFilterInfo[][] dsi = DSCapture.queryDevices();

	graph = new DSCapture(DSFiltergraph.RENDER_NATIVE, dsi[0][2], false, DSFilterInfo.doNotRender(), this);

	f.add(java.awt.BorderLayout.CENTER, graph.asComponent());

	f.add(java.awt.BorderLayout.SOUTH, new SwingMovieController(graph));

	final javax.swing.JButton toFile = new javax.swing.JButton("set capture file");

	toFile.addActionListener(new java.awt.event.ActionListener() {

		public void actionPerformed(java.awt.event.ActionEvent e) {

			if (graph.getState() == DSCapture.PREVIEW) {

				graph.setCaptureFile("captureTest.asf", DSFilterInfo.doNotRender(), DSFilterInfo.doNotRender(), true);

				toFile.setText("set preview");

				graph.record();

			} else {

				graph.setPreview();

				toFile.setText("set capture file");

			}

		}

	});

	f.add(java.awt.BorderLayout.NORTH, toFile);

	f.pack();

	f.setVisible(true);

	javax.swing.JFrame jf = new javax.swing.JFrame("Device control");

	jf.setLayout(new java.awt.GridLayout(0,1));

	if (((DSCapture)graph).getActiveVideoDevice() != null && ((DSCapture)graph).getActiveVideoDevice().getControls() != null) {

		for (int i = CaptureDeviceControls.BRIGHTNESS; i < CaptureDeviceControls.FOCUS; i++) try { jf.add(((DSCapture)graph).getActiveVideoDevice().getControls().getController(i, 0, true)); }catch (Exception ex){}

	}

	if (((DSCapture)graph).getActiveAudioDevice() != null) for (int i = CaptureDeviceControls.MASTER_VOL; i < CaptureDeviceControls.TREBLE; i++) try { jf.add(((DSCapture)graph).getActiveAudioDevice().getControls().getController(i, 0, true)); }catch (Exception ex){}

	if (jf.getContentPane().getComponentCount() == 0) return;

	jf.pack();

	jf.setVisible(true);

	/**
	Don't do this at home. This demo relies on dsj closing and disposing off filtergraphs when the JVM exits. This is
	OK for a "open graph, do something & exit" style demo, but real world applications should take care of calling
	dispose() on filtergraphs they're done with themselves.
	**/

	f.setDefaultCloseOperation(javax.swing.WindowConstants.EXIT_ON_CLOSE);

}

public void propertyChange(java.beans.PropertyChangeEvent pe) {

	System.out.println("received event or callback from "+pe.getPropagationId());

}

public static void main(String[] args){

	new SimpleCapture().createGraph();

}

}[/code]

Olá, discorpio.

Esse código eu já tenho. Eu gostaria é de gravar um VÍDEO.

Abraços, Gustavo Borba.

[quote=GustavoBorba]Olá, discorpio.

Esse código eu já tenho. Eu gostaria é de gravar um VÍDEO.

Abraços, Gustavo Borba.[/quote]

[code]/**
dsj demo code.
You may use, modify and redistribute this code under the terms laid out in the header of the DSJDemo application.
copyright 2005-7
N.Peters
humatic GmbH
Berlin, Germany
**/

import de.humatic.dsj.*;

public class SimpleCapture implements java.beans.PropertyChangeListener {

private DSCapture graph;

public SimpleCapture() {}

public void createGraph() {

	javax.swing.JFrame f = new javax.swing.JFrame("dsj SimpleCapture");

	DSFilterInfo[][] dsi = DSCapture.queryDevices();

	graph = new DSCapture(DSFiltergraph.RENDER_NATIVE, dsi[0][2], false, DSFilterInfo.doNotRender(), this);

	f.add(java.awt.BorderLayout.CENTER, graph.asComponent());

	f.add(java.awt.BorderLayout.SOUTH, new SwingMovieController(graph));

	final javax.swing.JButton toFile = new javax.swing.JButton("set capture file");

	toFile.addActionListener(new java.awt.event.ActionListener() {

		public void actionPerformed(java.awt.event.ActionEvent e) {

			if (graph.getState() == DSCapture.PREVIEW) {

				graph.setCaptureFile("captureTest.asf", DSFilterInfo.doNotRender(), DSFilterInfo.doNotRender(), true);

				toFile.setText("set preview");

				graph.record();

			} else {

				graph.setPreview();

				toFile.setText("set capture file");

			}

		}

	});

	f.add(java.awt.BorderLayout.NORTH, toFile);

	f.pack();

	f.setVisible(true);

	javax.swing.JFrame jf = new javax.swing.JFrame("Device control");

	jf.setLayout(new java.awt.GridLayout(0,1));

	if (((DSCapture)graph).getActiveVideoDevice() != null && ((DSCapture)graph).getActiveVideoDevice().getControls() != null) {

		for (int i = CaptureDeviceControls.BRIGHTNESS; i < CaptureDeviceControls.FOCUS; i++) try { jf.add(((DSCapture)graph).getActiveVideoDevice().getControls().getController(i, 0, true)); }catch (Exception ex){}

	}

	if (((DSCapture)graph).getActiveAudioDevice() != null) for (int i = CaptureDeviceControls.MASTER_VOL; i < CaptureDeviceControls.TREBLE; i++) try { jf.add(((DSCapture)graph).getActiveAudioDevice().getControls().getController(i, 0, true)); }catch (Exception ex){}

	if (jf.getContentPane().getComponentCount() == 0) return;

	jf.pack();

	jf.setVisible(true);

	/**
	Don't do this at home. This demo relies on dsj closing and disposing off filtergraphs when the JVM exits. This is
	OK for a "open graph, do something & exit" style demo, but real world applications should take care of calling
	dispose() on filtergraphs they're done with themselves.
	**/

	f.setDefaultCloseOperation(javax.swing.WindowConstants.EXIT_ON_CLOSE);

}

public void propertyChange(java.beans.PropertyChangeEvent pe) {

	System.out.println("received event or callback from "+pe.getPropagationId());

}

public static void main(String[] args){

	new SimpleCapture().createGraph();

}

}[/code]

Ocorre esse erro:

[quote]Exception in thread “main” java.lang.ArrayIndexOutOfBoundsException: 2
at app.createGraph(app.java:15)
at app.main(app.java:89)
Java Result: 1
[/quote]

[quote=GustavoBorba]Ocorre esse erro:

[quote]Exception in thread “main” java.lang.ArrayIndexOutOfBoundsException: 2
at app.createGraph(app.java:15)
at app.main(app.java:89)
Java Result: 1
[/quote][/quote]

Porque sua máquina deve ter apenas 1 dispositivo de captura.

graph = new DSCapture(DSFiltergraph.RENDER_NATIVE, dsi[0][2], false, DSFilterInfo.doNotRender(), this);

pode usar assim

graph = new DSCapture(DSFiltergraph.RENDER_NATIVE, dsi[0][0], false, DSFilterInfo.doNotRender(), this);

Se você receber o erro novamente, coloque um breakepoint na linha, e veja em qual índice do vetor dsi está o dispositivo de vídeo.

[color=darkblue]Tem o Source no final :[/color]

Record Movies with Java Media Framework (JMF)