2010-09-10 12 views
40

Come posso creare un file video da una serie di immagini/foto su Android? Questo può essere fatto con l'attuale SDK? o ho bisogno di una libreria di codec?Codifica una serie di immagini in un video

+0

suggerisco di fare questa domanda in [StackOverflow per Sistemi Multimediali] (http://area51.stackexchange.com/proposals/91149/sistemi multimediali) – Hamed

risposta

11

Sono d'accordo con Mark. Tra le librerie C/C++ ci sono ffmpeg here o X264 here. Devo dire che non li ho trovati o che l'NDK di Android è facile da usare, ma probabilmente è perché non so molto di C/C++ e JNI. Se sei interessato a questa rotta, l'app gratuita di RockPlayer per Android include le librerie condivise predefinite di ffmpeg, pronte per l'uso su Android. Sostengono che queste librerie usano solo componenti LGPL ma dovresti accontentarti di questo, immagino. Riguardo a Java, c'è una porta (di sorta) di ffmpeg chiamata, non sorprendentemente, jffmpeg che è possibile accedere a here ma continua a richiamare gran parte del framework ffmpeg esistente, quindi si torna in NDK land. È possibile convertire una serie di immagini in video con Java Media Framework (JMF) ma presenta i seguenti inconvenienti:

  1. Numero limitato di formati video.
  2. Non produce video che possono essere riprodotti sulla maggior parte (se non tutti) i telefoni Android, ad es. H264 o MPEG4.
  3. Il codice JMF ora è piuttosto vecchio, non ha progredito da molto tempo, è gonfio e non ben strutturato, quindi potrebbero esserci ulteriori dipendenze Java che non sono pacchettizzate in Android.

Un'altra opzione che ho visto è Adobe Air, ma è un carico utile di 17 Mb che alcuni utenti si lamentano.

Ci sono molte altre domande qui su Stack Overflow riguardanti ffmpeg e Android NDK.

Buona fortuna con il progetto.

+1

Come posso fare questo con Adobe Air? –

+0

@Ilya_Gazman Spiacente, non ho esperienza con Adobe Air. Ho semplicemente trovato alcuni riferimenti ad esso mentre stavo ricercando questo argomento. –

+0

Capisco. Non faccio niente che sia possibile con loro. Non ho familiarità con nessuna libreria aerea in grado di farlo. –

4

Non esiste un supporto integrato per questo. Dovresti trovare un codice sorgente Java che faccia ciò che ti serve, o un codice C/C++ che puoi trasformare in una libreria e utilizzare tramite NDK. Oppure, se l'obiettivo finale è che il video sia su un server, caricare le immagini/foto e fare in modo che il server crei il video.

4

ffmpeg è il tuo ranger di soccorso. Puoi scaricare la porta FFMPEG per Android. Fare riferimento alla domanda FFmpeg on Android per ulteriori dettagli.

La porta supporta quasi tutto ciò di cui avrete mai bisogno, inclusi i formati: i formati di immagine di input sono GIF, JPG, PNG, BMP ecc. E i formati di output video sono AVI, MP4 (contenitori) con molti codec.

+8

In tutta la mia ricerca non sono riuscito a trovare una porta ffmpeg per Android. Mi è sembrato che dovessi scaricare ffmpeg, eseguire .config su di esso (per il sistema operativo di destinazione e includendo qualsiasi codec che volevi) e poi costruirlo in una libreria condivisa che dovevi poi scrivere un wrapper JNI per effettuare chiamate in esso - Supponendo che tu non abbia avuto errori lungo la strada. Forse saresti abbastanza bravo da condividere un link per il download di questa porta ffmpeg? –

1

È possibile utilizzare una libreria open source gratuita denominata JCodec (http://jcodec.org) che contiene pure implementazioni java di alcuni formati e codec video popolari, tra cui: H.264 (AVC), MPEG 1/2, Apple ProRes, JPEG, MP4 (ISO BMF), MPEG PS, MPEG TS, Matroska.
È possibile utilizzare la CORRETTO classe inferiore a quello utilizza JCodec basso livello 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

Purtroppo non possiamo usare BufferedImage su Android. Android non ha accesso a java.awt. *. – BVB

+0

@Stanislav qualsiasi soluzione invece di usare BufferedImage per Android? – Ehsan

+0

@ user2204093 questo snippet di codice non è aggiornato. JCodec ora ha una porta Android –

Problemi correlati