11

Androidの特定のビデオファイルのキーフレームのタイムスタンプのリストを提供できるAPIはありますか?

4

5 に答える 5

10

エレガントなソリューションの場合、これを実現するには、Android用のffmpegを使用する必要があるようです。他の誰かがそのようにそれを試しました: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

于 2012-08-15T15:31:12.177 に答える
5

正解はhttp://code.google.com/p/mp4parser/だと思います

アイソパーサーAPIは、MP4ファイル構造の読み取りと書き込みを行うことができます。これは、いわゆるボックスを処理する低レベルのツールですが、トラックや映画などの構造も処理します。

素晴らしいAPIとffmpegbehemothよりもはるかに高速です

于 2012-11-19T20:42:05.187 に答える
2

4.1+-下のネイティブで行われ、コードがよりクリーンであるため、mp4parserよりも高速です

mp4parserは、getsyncsamples + 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);
}
于 2015-04-13T15:40:21.463 に答える
0

@ryangordonのソリューションに基づいて構築します。seekTo指定されている場合でも、同じフレームをシークする場合SEEK_TO_NEXT_SYNCがあります。これを回避するには、フレームの繰り返しが開始されたら終了できます。

例えば:

    private fun getSyncFrameTimestamps(source: MediaExtractor): List<Long> {
        val result = mutableListOf<Long>()

        var lastSampleTime = -1L
        var sampleTime = source.sampleTime

        while (sampleTime >= 0L && sampleTime != lastSampleTime) {
            if (source.sampleFlags and MediaExtractor.SAMPLE_FLAG_SYNC != 0) {
                result.add(sampleTime)
            }
            source.seekTo(sampleTime + 1L, MediaExtractor.SEEK_TO_NEXT_SYNC)
            lastSampleTime = sampleTime
            sampleTime = source.sampleTime
        }

        return result
    }

これを呼び出す前にsource、データソースを設定し、ビデオトラックを選択する必要があることに注意してください。

于 2021-11-08T15:34:14.697 に答える
-1

MediaExtractorを使用すると、すべてのキー(同期)フレームの時間や特定のキーフレームを任意の時間に設定できます。+いくつかのより有用なデータ。

次に、MediaMetadataRetriever-> getFrameAtTimeによって、フレームビットマップを取得できます。

MediaExtractorを使用するためのサンプルコードは次のとおりです。

    mediaExtractor = new MediaExtractor() ;
    mediaExtractor.setDataSource(mediaPath);
    int numTracks = mediaExtractor.getTrackCount();
    for (int i = 0; i < numTracks; ++i) {
        MediaFormat format = mediaExtractor.getTrackFormat(i);
        String mime = format.getString(MediaFormat.KEY_MIME);
        if ( mime.startsWith("video") ) {
            mediaExtractor.selectTrack(i);
        }
        Log.i( "LOG_Extractor" , "track "+i+" "+mime );
    }

    currentTime = mediaPlayer.getCurrentPosition();
    mediaExtractor.seekTo( (long)currentTime*1000 , MediaExtractor.SEEK_TO_PREVIOUS_SYNC );
    previousKeyFrameTimeMilis = mediaExtractor.getSampleTime() /1000 ;
于 2018-03-10T05:14:15.753 に答える