40 votes

Encoder une série d'Images dans une Vidéo

Comment puis-je créer un fichier vidéo à partir d'une série d'images/photos sur Android? Cela peut être fait avec le SDK actuel? ou dois-je besoin d'une bibliothèque de codec?

Merci.

11voto

John J Smith Points 5051

Je suis d'accord avec Marc. Parmi les bibliothèques C/C++ sont ffmpeg ici ou X264 ici. Je dois dire que je havn'pas trouvé ou l'Android NDK facile à utiliser, mais c'est probablement parce que je ne connais pas vraiment sur le C/C++ et de la JNI. Si vous êtes intéressé par cette route, puis la RockPlayer application gratuite pour Android a la pré-construit des bibliothèques partagées de ffmpeg prêt pour une utilisation sur Android. Ils prétendent ces bibliothèques uniquement utiliser la LGPL) tous les composants, mais vous auriez à vous satisfaire sur ce, je suppose. En ce qui concerne Java, il y a un port (de toutes sortes) de ffmpeg appelée, sans surprise, jffmpeg auquel vous pouvez accéder ici mais encore, elle appelle à une grande partie de l'existant ffmpeg cadre, de sorte que vous êtes de retour dans le NDK terre. Il est possible de convertir une série d'images pour la vidéo avec le Java Media Framework (JMF), mais elle a les inconvénients suivants:

  1. Nombre limité de formats vidéo.
  2. Ne pas produire des vidéos qui peuvent être lus sur la plupart (si pas tous) des téléphones Android par exemple, H264 ou MPEG4.
  3. JMF code est maintenant assez vieux, n'a pas progressé dans un temps long, est pléthorique et mal structurées de sorte qu'il peut être supplémentaire Java dépendances qui ne sont pas emballés dans Android.

Une autre option que je l'ai vu utilisé est Adobe Air, mais c'est un 17Mb de charge utile certains utilisateurs se plaignent.

Il ya beaucoup d'autres questions ici, sur un Débordement de Pile concernant ffmpeg et Android NDK.

Bonne chance avec le projet.

4voto

MasterGaurav Points 4753

ffmpeg est votre rescue rangers. Vous pouvez télécharger le FFMPEG port pour android. Reportez-vous à la question FFMPEG sur Android pour plus de détails.

Le port prend en charge presque tout ce que vous aurez jamais besoin, y compris les formats d'entrée d'image formats GIF, JPG, PNG, BMP, etc et la sortie vidéo formats AVI, MP4 (conteneurs) avec beaucoup de codecs.

4voto

CommonsWare Points 402670

Il n'y a pas de prise en charge intégrée pour cela. Vous devez soit trouver quelques du code source Java qui fait ce que vous avez besoin, ou certains code C/C++, vous pouvez transformer en une bibliothèque et de l'utilisation par le NDK. Ou, si l'objectif final est pour que la vidéo soit sur un serveur, téléchargez les images/photos et demander au serveur de créer la vidéo.

1voto

Vous pourrez utiliser gratuitement la bibliothèque open source appelé JCodec ( http://jcodec.org ) qui contient des implémentations java de certains formats de vidéo populaires et de codecs, notamment: H. 264 ( AVC ), MPEG 1/2, Apple ProRes, JPEG, MP4 ISO ( BMF ), MPEG PS, MPEG TS, Matroska.
Vous pouvez utiliser le CORRIGÉ de classe ci-dessous qui utilise JCodec API de bas niveau:

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();
    }
}

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X