2012-02-17 14 views
27

¿Alguien puede recomendar una biblioteca Java que me permita crear un video programáticamente? En concreto, se haría lo siguiente:Biblioteca Java recomendada para crear un video programáticamente

  • tomar una serie de BufferedImages como los marcos
  • permiten un fondo WAV/MP3 a añadir
  • permita 'incidentales' WAV/MP3 a añadirse en forma arbitraria, programáticamente puntos especificados
  • salida el video en un formato común (MPEG, etc)

¿alguien puede recomendar algo? Para la mezcla de imagen/sonido, incluso viviría con algo que tomara una serie de fotogramas, y para cada fotograma tenía que proporcionar los bytes sin formato de datos de sonido sin comprimir asociados con ese fotograma.

P.S. Ni siquiera tiene que ser una "biblioteca de terceros" como tal si Java Media Framework tiene las llamadas para lograr lo anterior, pero de mi memoria incompleta tengo la sensación de que no es así.

+0

Usted puede probar esto. http://wiki.xuggle.com/MediaTool_Introduction – Ovilia

+0

Miré Xuggle, pero no lo hace la mitad quedar como un dolor en el culo de configurar. No estoy seguro de por qué estas personas tienen un bloqueo mental con solo darle un jar/dll/exe para descargar ... –

+0

P.S. Una solución que tengo por ahora, pendiente de algo mejor, es guardar los marcos como, por ejemplo, Los archivos PNG luego llaman a la utilidad de línea de comandos ffmpeg en los marcos. Supongo que eso es efectivamente lo que una biblioteca podría hacer bajo el capó de todos modos. –

Respuesta

5

He utilizado el código mencionado a continuación para realizar con éxito los elementos 1, 2 y 4 en su lista de requisitos en Java puro. Vale la pena echarle un vistazo y probablemente puedas averiguar cómo incluir el # 3.

http://www.randelshofer.ch/blog/2010/10/writing-quicktime-movies-in-pure-java/

+0

Definitivamente es funcionalmente similar a la especificación que mencioné. Como yo lo veo, la principal desventaja es que fusiona marcos individuales en lugar de usar un códec de video, por lo que terminas con archivos más grandes. Por otro lado, me gusta la idea de que no haya problemas de patentes. –

4

me encontré con una herramienta llamada ffmpeg que puede convertir archivos multimedia forman un formato a otro. Hay un filtro llamado libavfilter en ffmpeg que es el sustituto de vhook que permite que el video/audio sea modificado o examinado entre el decodificador y el codificador. Creo que debería ser posible ingresar marcos sin procesar y generar video. Investigué en cualquier implementación java de ffmpeg y encontré la página titulada "Getting Started with FFMPEG-JAVA" que es un contenedor JAVA alrededor de FFMPEG usando JNA.

+0

Gracias - ¡Definitivamente verifico esto en algún momento! –

-1

Pruebe JavaFX.

JavaFX incluye soporte para la representación de imágenes en múltiples formatos y soporte para la reproducción de audio y vídeo en todas las plataformas en las que se apoya JavaFX.

Here es un tutorial sobre la manipulación de las imágenes

Here es un tutorial sobre cómo crear presentaciones de diapositivas, líneas de tiempo y escenas.

Here es Preguntas frecuentes sobre la adición de sonidos.

La mayoría de estos están en JavaFX 1.3. Ahora JavaFX 2.0 está fuera.

0

¿Por qué no utilizar FFMPEG?

Parece que hay una capa Java para ello:

http://fmj-sf.net/ffmpeg-java/getting_started.php

Aquí es un ejemplo de cómo compilar varios medios de comunicación en un vídeo con FFMPEG:

http://howto-pages.org/ffmpeg/#multiple

Y , finalmente, los documentos:

http://ffmpeg.org/ffmpeg.html

+0

Así que por el momento estoy usando FFMPEG, aunque de una manera un poco torpe porque no he descubierto cómo usar todas las opciones. ATM Estoy guardando todos los cuadros como imágenes en una carpeta, y luego ejecuto FFMPEG en ellos. Supongo que hay una forma de canalizar los cuadros uno por uno directamente a FFMPEG sin tener que guardarlos, pero aún no lo he descubierto. Pensé que ya podría haber una biblioteca que hiciera esto, por ejemplo. –

1

Usted puede tratar de una biblioteca códec puro Java llamada JCodec.
Tiene un codificador y MP4 H.264 muxor muy básico (AVC). Aquí hay un código de muestra completo tomado de sus muestras: TranscodeMain.

private static void png2avc(String pattern, String out) throws IOException { 
    FileChannel sink = null; 
    try { 
     sink = new FileOutputStream(new File(out)).getChannel(); 
     H264Encoder encoder = new H264Encoder(); 
     RgbToYuv420 transform = new RgbToYuv420(0, 0); 

     int i; 
     for (i = 0; i < 10000; i++) { 
      File nextImg = new File(String.format(pattern, i)); 
      if (!nextImg.exists()) 
       continue; 
      BufferedImage rgb = ImageIO.read(nextImg); 
      Picture yuv = Picture.create(rgb.getWidth(), rgb.getHeight(), ColorSpace.YUV420); 
      transform.transform(AWTUtil.fromBufferedImage(rgb), yuv); 
      ByteBuffer buf = ByteBuffer.allocate(rgb.getWidth() * rgb.getHeight() * 3); 

      ByteBuffer ff = encoder.encodeFrame(buf, yuv); 
      sink.write(ff); 
     } 
     if (i == 1) { 
      System.out.println("Image sequence not found"); 
      return; 
     } 
    } finally { 
     if (sink != null) 
      sink.close(); 
    } 
} 

Esta muestra es más sofisticado y en realidad muestra multiplexado de tramas codificadas en el archivo MP4:

private static void prores2avc(String in, String out, ProresDecoder decoder, RateControl rc) throws IOException { 
    SeekableByteChannel sink = null; 
    SeekableByteChannel source = null; 
    try { 
     sink = writableFileChannel(out); 
     source = readableFileChannel(in); 

     MP4Demuxer demux = new MP4Demuxer(source); 
     MP4Muxer muxer = new MP4Muxer(sink, Brand.MOV); 

     Transform transform = new Yuv422pToYuv420p(0, 2); 

     H264Encoder encoder = new H264Encoder(rc); 

     MP4DemuxerTrack inTrack = demux.getVideoTrack(); 
     CompressedTrack outTrack = muxer.addTrackForCompressed(TrackType.VIDEO, (int) inTrack.getTimescale()); 

     VideoSampleEntry ine = (VideoSampleEntry) inTrack.getSampleEntries()[0]; 
     Picture target1 = Picture.create(ine.getWidth(), ine.getHeight(), ColorSpace.YUV422_10); 
     Picture target2 = null; 
     ByteBuffer _out = ByteBuffer.allocate(ine.getWidth() * ine.getHeight() * 6); 

     ArrayList<ByteBuffer> spsList = new ArrayList<ByteBuffer>(); 
     ArrayList<ByteBuffer> ppsList = new ArrayList<ByteBuffer>(); 
     Packet inFrame; 
     int totalFrames = (int) inTrack.getFrameCount(); 
     long start = System.currentTimeMillis(); 
     for (int i = 0; (inFrame = inTrack.getFrames(1)) != null && i < 100; i++) { 
      Picture dec = decoder.decodeFrame(inFrame.getData(), target1.getData()); 
      if (target2 == null) { 
       target2 = Picture.create(dec.getWidth(), dec.getHeight(), ColorSpace.YUV420); 
      } 
      transform.transform(dec, target2); 
      _out.clear(); 
      ByteBuffer result = encoder.encodeFrame(_out, target2); 
      if (rc instanceof ConstantRateControl) { 
       int mbWidth = (dec.getWidth() + 15) >> 4; 
       int mbHeight = (dec.getHeight() + 15) >> 4; 
       result.limit(((ConstantRateControl) rc).calcFrameSize(mbWidth * mbHeight)); 
      } 
      spsList.clear(); 
      ppsList.clear(); 
      H264Utils.encodeMOVPacket(result, spsList, ppsList); 
      outTrack.addFrame(new MP4Packet((MP4Packet) inFrame, result)); 
      if (i % 100 == 0) { 
       long elapse = System.currentTimeMillis() - start; 
       System.out.println((i * 100/totalFrames) + "%, " + (i * 1000/elapse) + "fps"); 
      } 
     } 
     outTrack.addSampleEntry(H264Utils.createMOVSampleEntry(spsList, ppsList)); 

     muxer.writeHeader(); 
    } finally { 
     if (sink != null) 
      sink.close(); 
     if (source != null) 
      source.close(); 
    } 
} 
Cuestiones relacionadas