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

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


person Rad The Mad    schedule 10.09.2010    source источник
comment
Я предлагаю задать этот вопрос в StackOverflow для мультимедийных систем.   -  person Hamed    schedule 19.09.2015


Ответы (4)


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

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

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

Здесь, в Stack Overflow, есть много других вопросов, касающихся ffmpeg и Android NDK.

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

person John J Smith    schedule 14.04.2011
comment
Как я могу сделать это с помощью Adobe Air? - person Ilya Gazman; 08.07.2014
comment
@Ilya_Gazman Извините, у меня нет опыта работы с Adobe Air. Я просто наткнулся на некоторые ссылки на него, когда исследовал эту тему. - person John J Smith; 08.07.2014
comment
Я понимаю. Я не думаю, что это возможно с ними. Я не знаком ни с одной воздушной библиотекой, которая может это сделать. - person Ilya Gazman; 08.07.2014

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

person CommonsWare    schedule 10.09.2010

ffmpeg — ваш спасатель. Вы можете скачать порт FFMPEG для Android. Дополнительные сведения см. в вопросе FFmpeg для Android.

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

person Gaurav Vaish    schedule 18.04.2011
comment
Во всех моих поисках я не смог найти порт ffmpeg для Android. Мне казалось, что вам нужно скачать ffmpeg, запустить на нем .config (для целевой ОС и включая любые кодеки, которые вы хотите), а затем встроить его в разделяемую библиотеку, которую затем вам нужно было написать обертка JNI, чтобы делать вызовы в нее - при условии, что вы не получили никаких ошибок по пути. Возможно, вы были бы достаточно любезны, чтобы поделиться ссылкой на загрузку этого порта ffmpeg? - person John J Smith; 20.04.2011

Вы можете использовать бесплатную библиотеку с открытым исходным кодом под названием JCodec ( http://jcodec.org ), которая содержит чистые реализации Java некоторых популярных видеоформаты и кодеки, в том числе: H.264 (AVC), MPEG 1/2, Apple ProRes, JPEG, MP4 (ISO BMF), MPEG PS, MPEG TS, Matroska.
Вы можете использовать ИСПРАВЛЕНО< /strong> класс ниже, использующий низкоуровневый 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();
    }
}
person Stanislav Vitvitskyy    schedule 13.05.2013
comment
К сожалению, мы не можем использовать BufferedImage на Android. Android не имеет доступа к java.awt.*. - person BVB; 21.06.2013
comment
@Stanislav, какое-нибудь решение вместо использования BufferedImage для Android? - person Ehsan; 07.09.2014
comment
@ user2204093 этот фрагмент кода устарел. JCodec теперь имеет порт для Android - person Andrew G; 08.09.2014
comment
@AndrewG Можете ли вы помочь мне с этим? Я могу создавать MP4, но это не MP4.h264, потому что я получаю сообщение об ошибке при микшировании со звуком, в то время как MP4.h264 работает отлично, я пытался больше недели, но не смог этого сделать. - person Ehsan; 09.09.2014
comment
@ user2204093, к сожалению, я в той же лодке. Я указал на это только потому, что видел информацию в другом сообщении SO и просматривал их веб-сайт. Их образцы / документация для Android, похоже, отсутствуют - person Andrew G; 09.09.2014
comment
Класс BufferedImage больше не доступен в Android (или никогда не был). - person mradzinski; 12.01.2015