2012-08-03 6 views

cevap

9

Zarif bir çözüm için, bunu başarmak için android için ffmpeg kullanmanız gerekecek gibi görünüyor. Başka biri şu şekilde denedi: How to get the frame from video file in android; ve ffmpeg kullanması önerildi.

ı referans kılavuzu kontrol, ama burada açıklandığı gibi sadece MediaMetadataRetriever() kullanarak zaman içinde belirli bir konumda göreli (zaman damgası olmadan) bir kareyi kendisi için bir yol bulabiliriz: http://developer.android.com/reference/android/media/MediaMetadataRetriever.html#extractMetadata%28int%29

Eğer don' (bilmiyorum) muhtemelen da oldukça yavaş ...

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; 
} 

Bu değil elbette çok şık, ama muhtemelen ffmpeg yüklemek için uğraşmadan çalışacak: t aşağıdaki deneyebilirsiniz ffmpeg kullanmak istiyorum . Ama belki de ihtiyacın olan şey budur.

PS: sorununuzu uyan bir ffmpeg öğretici burada bulunabilir:

+1

Merhaba Stefan sayesinde, ama ben zaten bu çözümü denedim ve lanet yavaş çalışır ve garip sonuçlar sağlar. Daha fazla araştıracağım (örneğin, ffmpeg/ffprobe) ve bu konuyu güncel tutacağım. –

+0

Beklediğim şey bu. Bunu hızlandırmak için bir fikir 'time + = lastdistance' deniyor; 'set 'lastdistance = lastFrameTime - time setini kullandığınızda;' bir ana kare bulunursa, 'lastFrameTime + lastdistance - 1' hala son kare olup olmadığını kontrol edin. Eğer öyleyse, devam edin ... başka bir sonraki çerçeve – SDwarfs

+1

çapraz derlemek ffmpeg android üzerine bulmak için "yavaş arama" kullanın. I resimlerin listesini almak için -show_frames seçeneği ile ffprobe komutunu kullanın. Bu, tüm video türleri için çalışmalı ve oldukça hızlıdır. Önce PC'de kontrol et. [Eğer ffmpeg kurduysanız, ffprobe da sahip olmalısınız]. İhtiyacınız olan tüm bilgileri alacaksınız. Daha hızlı olan -show_packets var ve bilmek istediğiniz tek şey referans kareleri olmayan referanslar için yeterli olduğunu kanıtlayabilir. – av501

0

4.1+ ffmpeg devi çok daha hızlı yolları - Eğer getsyncsamples zaman damgalarını hesaplamak zorunda mp4parser daha hızlı altında yerli yapılır çünkü ve kod temizleyici

mp4parser olduğunu + Ayrıca can sıkıcı olan ve ffprobe ile eşleşmeyen getampledurations. Bu istenilen zamanda süreleri ve/veya belirli bir kareyi çerçeveleri, tüm anahtarı (senkronizasyon) olabilir MediaExtractor kullanarak doğru sonuçlar

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); 
} 
+0

bitmap'sini oluşturmak için kod çözücü/kodlayıcı içermiyor, bu projeye geri döndüğümde kontrol edeceğim. –

0

alır. + bazı daha faydalı veriler.

Daha sonra MediaMetadataRetriever -> getFrameAtTime ile Bitmap'ler çerçevesini alabilirsiniz. Burada

MediaExtractor kullanmak için bir örnek kod: çabalarınız için

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 ; 
İlgili konular