2013-02-27 2 views
8

Я пытаюсь извлечь все кадры из видео.
Следующим кодом я хочу получить первые 30 кадров видео, но я получил только первый кадр 30 раз.Извлечь растровое изображение из видео в android

private ArrayList<Bitmap> getFrames(String path) { 
    try { 
     ArrayList<Bitmap> bArray = new ArrayList<Bitmap>(); 
     bArray.clear(); 
     MediaMetadataRetriever mRetriever = new MediaMetadataRetriever(); 
     mRetriever.setDataSource("/sdcard/myvideo.mp4");      

     for (int i = 0; i < 30; i++) { 
      bArray.add(mRetriever.getFrameAtTime(1000*i, 
         MediaMetadataRetriever.OPTION_CLOSEST_SYNC)); 
     } 
     return bArray; 
    } catch (Exception e) { return null; } 
} 

Теперь, как я могу получить все кадры из видео?

+0

Время, указанное 'getFrameAtTime', находится в микросекундах, поэтому для видео с частотой 30 кадров в секунду между кадрами будет около 33333 микросекунды. Последний кадр, который ваш код пытается прочитать, составляет 30000 микросекунд - т. Е. Вы даже не переместились ко второму кадру (в зависимости от частоты кадров, конечно). Другое дело, что 'OPTION_CLOSEST_SYNC' извлекает _keyframe_ ближе всего к указанному вами времени. Как правило, меньше кадровых кадров, чем общие кадры в сжатом видео. – Michael

+0

Привет @ Майкл, мое видео с 30 кадрами в секунду. и теперь я использую следующий код для вытяжных растровых изображений .... для (INT I = 0; я <10; я ++) { \t \t \t \t bArray.add (mRetriever.getFrameAtTime (33333 * я, \t \t \t \t \t \t MediaMetadataRetriever.OPTION_CLOSEST_SYNC)); \t } но ничего не изменится .. здесь я получил только первый кадр в растровом файле. –

+1

Как я писал в своем первом комментарии, вы извлекаете ключевой кадр, ближайший к данному времени, когда вы используете 'OPTION_CLOSEST_SYNC'. Маловероятно, что видео содержит 10 или более кадров для каждого ключевого кадра. Используйте 'OPTION_CLOSEST', если вы хотите получить какой-то фрейм, а не только ключевые кадры. – Michael

ответ

2

Поддержка видео в Android SDK ограничена, а извлечение кадра для видео в формате H264 возможно только для ключевых кадров. Чтобы извлечь произвольный фрейм, вам понадобится библиотека, например FFmpegMediaMetadataRetriever, которая использует собственный код для извлечения данных из видео. Это очень быстро, поставляется с предварительно скомпилированными исполняемыми файлами (для ARM и x86), поэтому вам не нужно вникать в C++ и make-файлы, лицензируется под Apache 2.0 и поставляется с демо-приложением Android.

Существует также чистая библиотека Java, JCodec, но она медленнее, и когда я использовал ее в прошлом году, цвета извлеченного кадра были искажены.

+0

Я пробовал JCodec, но я не мог получить ничего, кроме ключевых кадров из замедленного движения 240pps mp4. В итоге я использовал привязки Java для opencv, класс VideoCapture. Я считаю, что он использует ffmpeg под обложками. Мне удалось получить все фреймы, а также метку времени каждого знамени и общее количество кадров. ПРЕДУПРЕЖДЕНИЕ - это был java sdk, я еще не пробовал новейший opencv для Android. – medloh

0

getFrameAt получить данные в миллисекундах, но вы увеличиваете .001 миллисекунды за цикл.

for(int i=1000000;i<millis*1000;i+=1000000) // for incrementing 1s use 1000 
    { 
     bArray.add(mRetriever.getFrameAtTime(i, 
         MediaMetadataRetriever.OPTION_CLOSEST_SYNC)); 
    } 

изменить его, как указано выше. Выше - образец для создания того, что вы хотите. Я также ответил на это here

Смежные вопросы