Как я могу создать видеофайл из серии изображений/фотографий на Android? Можно ли это сделать с текущим SDK? или мне нужна библиотека кодеков?
Кодировать серию изображений в видео
Ответы (4)
Я согласен с Марком. Среди библиотек C/C++ есть ffmpeg здесь или X264 здесь. Я должен сказать, что не нашел их или Android NDK простыми в использовании, но это, вероятно, потому, что я мало знаю о C/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 МБ, на которую жалуются некоторые пользователи.
Здесь, в Stack Overflow, есть много других вопросов, касающихся ffmpeg и Android NDK.
Удачи с проектом.
Для этого нет встроенной поддержки. Вам нужно либо найти исходный код Java, который делает то, что вам нужно, либо код C/C++, который вы можете превратить в библиотеку и использовать через NDK. Или, если конечной целью является размещение видео на сервере, загрузите изображения/фотографии и попросите сервер создать видео.
ffmpeg
— ваш спасатель. Вы можете скачать порт FFMPEG для Android. Дополнительные сведения см. в вопросе FFmpeg для Android.
Порт поддерживает почти все, что вам когда-либо понадобится, включая форматы — входные форматы изображений — GIF, JPG, PNG, BMP и т. д., а выходные форматы видео — AVI, MP4 (контейнеры) с большим количеством кодеков.
Вы можете использовать бесплатную библиотеку с открытым исходным кодом под названием 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();
}
}
BufferedImage
больше не доступен в Android (или никогда не был).
- person mradzinski; 12.01.2015