2013-06-04 51 views
5

Mam nagrywanie wideo MediaRecorder i jestem bardzo zdezorientowany przez efekt setCaptureRate().Android MediaRecorder setCaptureRate() i prędkość odtwarzania wideo

Konkretnie, przygotowuję moje MediaRecorder następująco:

mMediaRecorder = new MediaRecorder(); 
mCamera.stopPreview(); 
mCamera.unlock(); 
mMediaRecorder.setCamera(mCamera); 
mMediaRecorder.setVideoSource(MediaRecorder.VideoSource.CAMERA); 
mMediaRecorder.setProfile(CamcorderProfile.QUALITY_TIME_LAPSE_480P); 
mMediaRecorder.setCaptureRate(30f); 
mMediaRecorder.setOrientationHint(270); 
mMediaRecorder.setOutputFile(...); 
mMediaRecorder.setPreviewDisplay(...); 
mMediaRecorder.prepare(); 

I rekord na pięć sekund (z CountDownTimer, ale to bez znaczenia), a to jest plik, który zostaje wygenerowany:

$ ffmpeg -i ~/CaptureRate30fps.mp4 
... 
Seems stream 0 codec frame rate differs from container frame rate: 180000.00 (180000/1) -> 30.00 (30/1) 
Input #0, mov,mp4,m4a,3gp,3g2,mj2, from '/home/mspitz/CaptureRate30fps.mp4': 
    Metadata: 
    major_brand  : isom 
    minor_version : 0 
    compatible_brands: isom3gp4 
    creation_time : 2013-06-04 00:52:00 
    Duration: 00:00:02.59, start: 0.000000, bitrate: 5238 kb/s 
    Stream #0.0(eng): Video: h264 (Baseline), yuv420p, 720x480, 5235 kb/s, PAR 65536:65536 DAR 3:2, 30 fps, 30 tbr, 90k tbn, 180k tbc 
    Metadata: 
     creation_time : 2013-06-04 00:52:00 

Należy pamiętać, że czas trwania wynosi około 3 sekundy. Obraz wideo jest również odtwarzany znacznie szybciej, tak jakby to było 5 sekund wideo wepchniętym w 3.

Teraz, jeśli nagrywam, przygotowując mój plik multimedialny dokładnie tak, jak powyżej, ale odejmując linię setCaptureRate (30f), otrzymuję plik taki jak to:

$ ffmpeg -i ~/NoSetCaptureRate.mp4 
... 
Seems stream 0 codec frame rate differs from container frame rate: 180000.00 (180000/1) -> 90000.00 (180000/2) 
Input #0, mov,mp4,m4a,3gp,3g2,mj2, from '/home/mspitz/NoSetCaptureRate.mp4': 
    Metadata: 
    major_brand  : isom 
    minor_version : 0 
    compatible_brands: isom3gp4 
    creation_time : 2013-06-04 00:50:41 
    Duration: 00:00:04.87, start: 0.000000, bitrate: 2803 kb/s 
    Stream #0.0(eng): Video: h264 (Baseline), yuv420p, 720x480, 2801 kb/s, PAR 65536:65536 DAR 3:2, 16.01 fps, 90k tbr, 90k tbn, 180k tbc 
    Metadata: 
     creation_time : 2013-06-04 00:50:41 

Należy pamiętać, że czas trwania jest zgodny z oczekiwaniami, około 5 sekund. Film odtwarzany jest również z normalną prędkością.

Używam setCaptureRate (30f), ponieważ 30 klatek na sekundę jest wartością mojego CamcorderProfile videoFrameRate. Na moim Galaxy Nexus S2 (4.2.1) pomijanie setCaptureRate() jest w porządku, ale kiedy testowałem na Galaxy Nexus S3 (4.1.1), pomijanie setCaptureRate() skutkuje zawsze pomocnym błędem "start failed -22" kiedy zadzwoniłem pod numer mMediaRecorder.start().

Więc, czego mi brakuje? Pomyślałem, że współczynnik przechwytywania i szybkość klatek wideo są niezależne, ale jest jasne, że tak nie jest. Czy istnieje sposób, aby określić programowo, co muszę ustawić szybkość przechwytywania na w celu ustalenia, że ​​moje wideo odtwarza z prędkością 1x?

+0

Dlaczego 'QUALITY_TIME_LAPSE_480P', a nie' QUALITY_480P'? Przerwy w czasie nie są z natury 1 prędkością odtwarzania. –

+0

Czy chciałeś również wywołać 'MediaRecorder.setVideoFrameRate'? –

+0

@RomanNurik Dzięki za komentarz! Nie chcę nagrywać dźwięku, a jedynym sposobem na zrobienie tego wydaje się być użycie filmu poklatkowego. Odp: setVideoFrameRate, zostaje wywołana, gdy zadzwonię do setProfile(): https://github.com/android/platform_frameworks_base/blob/master/media/java/android/media/MediaRecorder.java#L329 W rzeczywistości, patrząc na źródło jest to, co naprowadziło mnie do konieczności wywołania setCaptureRate() w pierwszej kolejności. https://github.com/android/platform_frameworks_base/blob/master/media/java/android/media/MediaRecorder.java#L337 W przeciwnym razie dostałem -22. – spitzanator

Odpowiedz

1

(Niniejszy dokument jest streszczeniem uchwały z uwagi na oryginalne pytanie)

Problem może być tak, że bezpośrednio za pomocą wpływów QUALITY_TIME_LAPSE_480P profilu odtwarzaniem ceny, ponieważ upływ czasu nie są niejawnie 1x szybkość odtwarzania.

Ponadto, jeżeli przyczyna używasz tego profilu jest zapobieganie audio z nagrywana podczas korzystania QUALITY_480P (ponieważ upływ czasu nie nagrać audio), może chcesz zamiast zadzwonić CamcorderProfile.get(QUALITY_480P) i ustawienie parametrów obrazu na MediaRecorder ręcznie w oparciu o profil, bez konieczności dzwonienia bezpośrednio pod numer MediaRecorder.setProfile. A MediaRecorder, który nie ma żadnego zestawu parametrów audio, nie powinien teoretycznie rejestrować żadnego dźwięku.

0

Zgodnie z dokumentacją, setCaptureRate(double fps) służy do ustawiania nagrywania poklatkowego, z dźwiękiem zignorowanym. Jest to najbardziej przydatne, jeśli chcesz uzyskać mniej klatek na sekundę niż może to zapewnić system. Pytasz więcej fps niż system może zapewnić, oto cytat z developer.android.com/reference:

Zauważ, że rejestrator nie może zagwarantować, że klatki zostaną przechwycone w danym tempie ze względu na ograniczenia/enkodera kamer. Jednak stara się, aby jak najbliżej było .

Twój kod nie zadzwoni, to setVideoFrameRate(int rate). Wierzę, że za pomocą tej funkcji twoje nagranie zostanie naprawione.

+0

Niestety, to nie jest poprawne. Spójrz na źródło MediaRecorder: https://android.googlesource.com/platform/frameworks/base/+/refs/heads/master/media/java/android/media/MediaRecorder.java setProfile (CamcorderProfile profile) nie zadzwoń do setVideoFrameRate (profile.videoFrameRate); Komentarz tam jest, co sprawiło, że najpierw wypróbowałem setCaptureRate(), aby działało na Galaxy Nexus S3. – spitzanator

0

Masz rację. Udzielę Ci prawidłowej odpowiedzi.i napotkałeś na tę samą sytuację.start nie powiodło się-22 należy do szybkości klatek rate.hence, którą podajesz, nie znajduje się w zasięgu urządzenia. Najpierw użyj funkcji getSupportedPreviewFpsRange(), aby określić zakres fps urządzeń, a następnie odpowiednio ustawić. Możesz użyć funkcji PREVIEW_FPS_MAX_INDEX i PREVIEW_FPS_MIN_INDEX, aby uzyskać maksymalne i minimalne fFps.

użycie Poniższy kod to daje wynik pomnożony przez 1000 czyli jeśli liczba klatek na sekundę wynosi 5, zwróci 5000.

Camera.Parameters camParameter = camera.getParameters(); 
    List<int[]> frame = camParameter.getSupportedPreviewFpsRange(); 
     Iterator<int[]> supportedPreviewFpsIterator = frame.iterator(); 
     while (supportedPreviewFpsIterator.hasNext()) { 
      int[] tmpRate = supportedPreviewFpsIterator.next(); 
      StringBuffer sb = new StringBuffer(); 
      sb.append("supportedPreviewRate: "); 
      for (int i = tmpRate.length, j = 0; j < i; j++) { 
       sb.append(tmpRate[j] + ", "); 
      } 
      Log.d(VTAG, sb.toString()); 
     } 
    } 

więcej sprawdzanie: http://developer.android.com/reference/android/hardware/Camera.Parameters.html#getSupportedPreviewFpsRange()

EDIT: w Android dokument programisty.Wspomniano, że setCaptureRate() Ustawia szybkość przechwytywania klatek wideo. Można tego użyć do ustawienia innej szybkości przechwytywania klatek wideo niż szybkość odtwarzania nagranego wideo. Ta metoda ustawia również tryb nagrywania na upływ czasu. Ponieważ ustawia on również tryb nagrywania na time lapse, więc sprawdź wideo po usunięciu setprofile QUALITY_TIME_LAPSE_480P na dowolny inny obsługiwany normalny profil, taki jak QUALITY_480P, lub dokonaj czystego niestandardowego ustawienia MediaRecorder, ustawiając rozmiar wideo i inne. Może ci to pomóc.

+0

Dzięki za odpowiedź! Rzeczywiście musisz sprawdzić obsługiwane klatek na sekundę, ale zweryfikowaliśmy, że 30 klatek na sekundę znajduje się w dopuszczalnych granicach na Galaxy Nexus S3, więc nie jest to problemem. – spitzanator