Как получить список фреймов ключевых кадров (синхронизирующих кадров) для видеофайла в Android?

Есть ли какой-либо API, который может дать мне список штампов времени ключевых кадров для данного видеофайла в Android?

Ответ 1

Я верю, что правильный ответ http://code.google.com/p/mp4parser/

API-интерфейс isoparser может читать и писать файловую структуру MP4. Это инструмент низкого уровня, имеющий дело с так называемыми ящиками, но он также касается структуры, такой как дорожки и фильмы.

Хороший API и способы намного быстрее, чем ffmpeg behemoth

Ответ 2

Для элегантного решения кажется, что вам нужно использовать ffmpeg для Android, чтобы достичь этого. Кто-то еще пробовал это так: Как получить фрейм из видеофайла в android; и было предложено использовать ffmpeg.

Я проверил справочное руководство, но мог найти способ получить только ключевой кадр (без метки времени) относительно данной позиции во времени с помощью MediaMetadataRetriever(), как описано здесь: http://developer.android.com/reference/android/media/MediaMetadataRetriever.html#extractMetadata%28int%29

Если вы не хотите использовать ffmpeg, вы можете попробовать следующее:

private ArrayList<int> getKeyFrameTimestamps(String filename) {
  ArrayList<int> timeStamps = new ArrayList<int>();

  try {
    MediaMetadataRetriever mRetriever = new MediaMetadataRetriever();
    mRetriever.setDataSource(getDataSource(filename));
    mRetriever.getFrameAtTime(i, MediaMetadataRetriever.OPTION_CLOSEST_SYNC);

    Bitmap lastFame = mRetriever.getFrameAtTime(0, MediaMetadataRetriever.OPTION_NEXT_SYNC);
    result.add(0);

    for(int time=1; frame ; ++time) {
      Bitmap frame = mRetriever.getFrameAtTime(time, MediaMetadataRetriever.OPTION_PREVIOUS_SYNC);
      if (frame && !frame.sameAs(lastFrame)) {
        result.add(time);
        lastFrame = frame;
      }
    }
  } catch (Exception e) {  /* TODO: HANDLE THIS */ }

  return timeStamps;
}

Это, конечно, не очень элегантно, но, вероятно, будет работать без хлопот, чтобы установить ffmpeg... Вероятно, он тоже довольно медленный (я не знаю). Но, возможно, это именно то, что вам нужно.

PS: учебник ffmpeg, который подходит для вашей проблемы, можно найти здесь: http://dranger.com/ffmpeg/tutorial07.html

Ответ 3

4.1+ - быстрее, чем mp4parser, потому что сделано в native underneath и код чище

mp4parser вам нужно вычислить временные метки из getyncsamples + getsampledurations, что также раздражает, и они не совпадают с ffprobe. это дает точные результаты

MediaExtractor extractor = new MediaExtractor();
extractor.setDataSource(getVideoPath());

int trackindex = MediaExtractorUtil.selectVideoTrack(extractor);
extractor.selectTrack(trackindex);

while (extractor.getSampleTime() != -1) {
    long sampleTime = extractor.getSampleTime();

    // check not really necessary but JIC
    if ((extractor.getSampleFlags() & MediaExtractor.SAMPLE_FLAG_SYNC) > 0) {
        mKeyframeTimestampsMS.add(sampleTime / 1000);
    }

    extractor.seekTo(sampleTime + 1, MediaExtractor.SEEK_TO_NEXT_SYNC);
}