2010-09-10 17 views
40

¿Cómo puedo crear un archivo de video a partir de una serie de imágenes/fotos en Android? ¿Se puede hacer esto con el SDK actual? o necesito una biblioteca de codec?Codifica una serie de imágenes en un video

+0

sugiero hacer esta pregunta en [StackOverflow para Sistemas Multimedia] (http://area51.stackexchange.com/proposals/91149/multimedia-systems) – Hamed

Respuesta

11

Estoy de acuerdo con Mark. Entre las bibliotecas de C/C++ se encuentran ffmpeg here o X264 here. Tengo que decir que no los he encontrado o que el NDK de Android es fácil de usar, pero probablemente sea porque realmente no sé mucho sobre C/C++ y JNI. Si está interesado en esta ruta, entonces la aplicación gratuita RockPlayer para Android tiene las bibliotecas compartidas previamente compiladas de ffmpeg listas para usar en Android. Afirman que estas bibliotecas solo usan componentes LGPL, pero tendrías que estar satisfecho con esto, supongo. Con respecto a Java, hay un puerto (de géneros) de ffmpeg llamado, como era de esperar, jffmpeg que puede acceder a here pero todavía llama a gran parte del framework ffmpeg existente, por lo que está de vuelta en tierra NDK. Es posible convertir una serie de imágenes en video con Java Media Framework (JMF) pero tiene los siguientes inconvenientes:

  1. Número limitado de formatos de video.
  2. No produce videos que se pueden reproducir en la mayoría de los teléfonos Android (si no en todos), p. H264 o MPEG4.
  3. El código JMF ahora es bastante antiguo, no ha progresado en mucho tiempo, está hinchado y no está bien estructurado, por lo que puede haber dependencias adicionales de Java que no estén empaquetadas en Android.

Otra opción que he visto utilizado es Adobe Air, pero es una carga útil de 17Mb, que algunos usuarios se quejan.

Hay muchas otras preguntas aquí en Stack Overflow con respecto a ffmpeg y Android NDK.

Buena suerte con el proyecto.

+1

¿Cómo puedo hacer esto con Adobe Air? –

+0

@Ilya_Gazman Lo siento, no tengo experiencia con Adobe Air. Simplemente encontré algunas referencias cuando estaba investigando este tema. –

+0

Ya veo. No creo que eso sea posible con ellos. No estoy familiarizado con ninguna biblioteca de aire que pueda hacer eso. –

4

No hay soporte incorporado para esto. Debería encontrar algún código fuente de Java que haga lo que necesita, o algún código C/C++ que pueda convertir en una biblioteca y usar a través del NDK. O bien, si el objetivo final es que el video esté en un servidor, cargue las imágenes/fotos y haga que el servidor cree el video.

4

ffmpeg es su ranger de rescate. Puede descargar el puerto FFMPEG para Android. Consulte la pregunta FFmpeg on Android para obtener más detalles.

El puerto es compatible con casi todo lo que usted necesitará siempre, incluyendo los formatos - formatos de imagen de entrada son GIF, JPG, PNG, BMP, etc y salida de vídeo formatos de ser AVI, MP4 (contenedores) con una gran cantidad de códecs.

+8

En toda mi búsqueda no pude encontrar un puerto ffmpeg para Android. Me pareció que tenía que descargar ffmpeg, ejecutar .config en él (para el sistema operativo de destino e incluir los códecs que quisiera) y luego compilarlo en una biblioteca compartida, donde luego tenía que escribir un contenedor JNI para hacer llamadas al mismo. - suponiendo que no haya ningún error en el camino. Tal vez sería lo suficientemente bueno como para compartir un enlace a la descarga de este puerto ffmpeg? –

1

Puede utilizar una biblioteca de código abierto llamada JCodec (http://jcodec.org) que contiene implementaciones de java puro de algunos formatos de video y códecs populares, incluidos: H.264 (AVC), MPEG 1/2, Apple ProRes, JPEG, MP4 (ISO BMF), MPEG PS, MPEG TS, Matroska.
Puede utilizar el CORREGIDO clase a continuación que utiliza JCodec de bajo nivel API:

public class SequenceEncoder { 
    private SeekableByteChannel ch; 
    private Picture toEncode; 
    private RgbToYuv420 transform; 
    private H264Encoder encoder; 
    private ArrayList<ByteBuffer> spsList; 
    private ArrayList<ByteBuffer> ppsList; 
    private CompressedTrack outTrack; 
    private ByteBuffer _out; 
    private int frameNo; 
    private MP4Muxer muxer; 

    public SequenceEncoder(File out) throws IOException { 
     this.ch = NIOUtils.writableFileChannel(out); 

     // Transform to convert between RGB and YUV 
     transform = new RgbToYuv420(0, 0); 

     // Muxer that will store the encoded frames 
     muxer = new MP4Muxer(ch, Brand.MP4); 

     // Add video track to muxer 
     outTrack = muxer.addTrackForCompressed(TrackType.VIDEO, 25); 

     // Allocate a buffer big enough to hold output frames 
     _out = ByteBuffer.allocate(1920 * 1080 * 6); 

     // Create an instance of encoder 
     encoder = new H264Encoder(); 

     // Encoder extra data (SPS, PPS) to be stored in a special place of 
     // MP4 
     spsList = new ArrayList<ByteBuffer>(); 
     ppsList = new ArrayList<ByteBuffer>(); 

    } 

    public void encodeImage(BufferedImage bi) throws IOException { 
     if (toEncode == null) { 
      toEncode = Picture.create(bi.getWidth(), bi.getHeight(), ColorSpace.YUV420); 
     } 

     // Perform conversion 
     for (int i = 0; i < 3; i++) 
      Arrays.fill(toEncode.getData()[i], 0); 
     transform.transform(AWTUtil.fromBufferedImage(bi), toEncode); 

     // Encode image into H.264 frame, the result is stored in '_out' buffer 
     _out.clear(); 
     ByteBuffer result = encoder.encodeFrame(_out, toEncode); 

     // Based on the frame above form correct MP4 packet 
     spsList.clear(); 
     ppsList.clear(); 
     H264Utils.encodeMOVPacket(result, spsList, ppsList); 

     // Add packet to video track 
     outTrack.addFrame(new MP4Packet(result, frameNo, 25, 1, frameNo, true, null, frameNo, 0)); 

     frameNo++; 
    } 

    public void finish() throws IOException { 
     // Push saved SPS/PPS to a special storage in MP4 
     outTrack.addSampleEntry(H264Utils.createMOVSampleEntry(spsList, ppsList)); 

     // Write MP4 header and finalize recording 
     muxer.writeHeader(); 
     NIOUtils.closeQuietly(ch); 
    } 

    public static void main(String[] args) throws IOException { 
     SequenceEncoder encoder = new SequenceEncoder(new File("video.mp4")); 
     for (int i = 1; i < 100; i++) { 
      BufferedImage bi = ImageIO.read(new File(String.format("folder/img%08d.png", i))); 
      encoder.encodeImage(bi); 
     } 
     encoder.finish(); 
    } 
} 
+8

Desafortunadamente, no podemos usar BufferedImage en Android. Android no tiene acceso a java.awt. *. – BVB

+0

@Stanislav cualquier solución en lugar de usar BufferedImage para android? – Ehsan

+0

@ user2204093 este fragmento de código está desactualizado. JCodec ahora tiene un puerto Android –

Cuestiones relacionadas