Подтвердить что ты не робот

Кодировать серию изображений в видео

Как создать видеофайл из серии изображений/фотографий на Android? Можно ли это сделать с помощью текущего SDK? или мне нужна библиотека кодеков?

4b9b3361

Ответ 1

Я согласен с Марком. Среди библиотек C/С++: ffmpeg здесь или X264 здесь, Должен сказать, что я не нашел их или Android NDK простыми в использовании, но, вероятно, потому, что я действительно мало знаю о C/С++ и JNI. Если вас интересует этот маршрут, то бесплатное приложение RockPlayer для Android имеет готовые общие библиотеки из ffmpeg, готовые для использования на Android. Они утверждают, что в этих библиотеках используются только компоненты LGPL, но вам, наверное, придется удовлетворить себя этим. Что касается Java, то есть порт (рода) ffmpeg, вызывающий неудивительно, jffmpeg, который вы можете получить здесь, но он по-прежнему обращается к большую часть существующей структуры ffmpeg, так что вы вернулись на землю NDK. Можно преобразовать серию изображений в видео с помощью Java Media Framework (JMF), но имеет следующие недостатки:

  • Ограниченное количество видеоформатов.
  • Не воспроизводит видео, которое можно воспроизводить на большинстве (если не на всех) телефонах Android, например. H264 или MPEG4.
  • Код JMF теперь довольно старый, он не прогрессирует в течение длительного времени, раздутый и недостаточно структурированный, поэтому могут быть дополнительные зависимости Java, которые не упакованы в Android.

Другим вариантом, который я видел, является Adobe Air, но это полезная нагрузка 17 Мб, которую некоторые пользователи жалуются.

Здесь есть много других вопросов о переполнении стека в отношении ffmpeg и Android NDK.

Удачи вам в проекте.

Ответ 2

Для этого нет встроенной поддержки. Вам нужно будет либо найти какой-то исходный код Java, который делает то, что вам нужно, либо некоторый код C/С++, который вы можете превратить в библиотеку и использовать через NDK. Или, если конечная цель заключается в том, чтобы видео находилось на сервере, загрузите изображения/фотографии и создайте сервер для создания видео.

Ответ 3

ffmpeg - ваш спасатель. Вы можете загрузить порт FFMPEG для Android. Подробнее см. В вопросе FFmpeg на Android.

Порт поддерживает почти все, что вам когда-либо понадобится, включая форматы - форматы входных изображений, представляющие собой GIF, JPG, PNG, BMP и т.д., а также видеоформаты, являющиеся AVI, MP4 (контейнеры) с большим количеством кодеков.

Ответ 4

Вы можете использовать бесплатную библиотеку с открытым исходным кодом под названием JCodec (http://jcodec.org), которая содержит чистые java-реализации некоторых популярных видеоформатов и кодеков, в том числе: H.264 (AVC), MPEG 1/2, Apple ProRes, JPEG, MP4 (ISO BMF), MPEG PS, MPEG TS, Matroska.
Вы можете использовать класс CORRECTED, который использует API низкого уровня JCodec:

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