2011-03-17 11 views
6

Necesito obtener un fotograma de un archivo de video (puede estar en sdcard, cache dir o app dir). Tengo el paquete android.media en mi aplicación y en mi interior tengo la clase MediaMetadataRetriever. Para obtener el primer fotograma en un mapa de bits, uso código:android capture video frame

public static Bitmap getVideoFrame(Context context, Uri videoUri) { 
    MediaMetadataRetriever retriever = new MediaMetadataRetriever(); 
    try { 
     retriever.setMode(MediaMetadataRetriever.MODE_CAPTURE_FRAME_ONLY); 
     retriever.setDataSource(context, videoUri); 
     return retriever.captureFrame(); 
    } catch (IllegalArgumentException ex) { 
     throw new RuntimeException(); 
    } catch (RuntimeException ex) { 
     throw new RuntimeException(); 
    } finally { 
     retriever.release(); 
    } 
} 

Pero esto no está funcionando. Lanza una excepción (java.lang.RuntimeException: setDataSource failed: status = 0x80000000) cuando establezco el origen de datos. ¿Sabes cómo hacer que este código funcione? ¿O tiene alguna solución similar (simple) sin usar ffmpeg u otras bibliotecas externas? videoUri es un uri válido (el reproductor multimedia puede reproducir video desde ese URI)

+0

puede proporcionar una muestra para su pregunta, he intentado mucho para este tipo de muestra, finalmente tuve que preguntarle. – ManishSB

Respuesta

11

Los siguientes obras para mí:

public static Bitmap getVideoFrame(FileDescriptor FD) { 
     MediaMetadataRetriever retriever = new MediaMetadataRetriever(); 
     try { 
      retriever.setDataSource(FD); 
      return retriever.getFrameAtTime(); 
     } catch (IllegalArgumentException ex) { 
      ex.printStackTrace(); 
     } catch (RuntimeException ex) { 
      ex.printStackTrace(); 
     } finally { 
      try { 
       retriever.release(); 
      } catch (RuntimeException ex) { 
      } 
     } 
     return null; 
    } 

también funciona si se utiliza una ruta en lugar de un descriptor de fichero.

+0

qué valor debe pasar como argumento FileDescripter. Lo que realmente piensa es que, en mi aplicación, solo hay url de video y desea obtener la lista de fotogramas de ese archivo de video ... –

+0

Para obtener un objeto FileDescriptor, haga - openFileInput (myVideoFileName) .getFD(). Para hacer esto, el video debe estar en su directorio privado de aplicaciones. También puede cambiar al mapa de bits estático público getVideoFrame (String FD) y pasar la ruta de sus videos. –

+0

En un segundo, un video tiene de 25 a 30 fotogramas. Es capaz de obtener todos los marcos. Debido a esta técnica tengo 3-4 marcos repetidos cada vez. Y faltan algunos cuadros. –

0

Tengo el mismo error en mi aplicación. Vi en este sitio que

esta es una forma no oficial de hacerlo y que sólo funcionará en la magdalena (y tal vez más adelante versión). El equipo de Android no garantiza que libmedia_jni.so, que usa el archivo java , se incluya o tenga la misma interfaz en versiones futuras.

http://osdir.com/ml/AndroidDevelopers/2009-06/msg02442.html

He actualizado mi teléfono de pan de jengibre y que ya no funciona.

0

Uri's no son muy específicos. A veces se refieren a algo en un paquete. A menudo necesitan ser traducidos a una forma de ruta absoluta. La otra instancia en la que utilizó el Uri, probablemente fue lo suficientemente inteligente como para comprobar qué tipo de Uri era. Este caso que has mostrado parece no estar muy duro.

-2

Entonces, ¿hay una manera específica para obtener el marco de vídeo como

File sdcard = Environment.getExternalStorageDirectory(); 
File file = new File(sdcard, "myvideo.mp4"); 
+0

¿Estás preguntando o respondiendo? –

+0

estaba dando errores ... ahora está funcionando ... supongo que hay algún problema con mi editor de eclipse. Gracias de todos modos –

+0

Mi comentario fue para pedirle que "Este código de 2 líneas es su respuesta o una pregunta con su problema?" –

6

Prueba de esto, lo he usado y su trabajo

public static Bitmap getVideoFrame(Context context, Uri uri) { 
    MediaMetadataRetriever retriever = new MediaMetadataRetriever(); 
    try { 
     retriever.setDataSource(uri.toString(),new HashMap<String, String>()); 
     return retriever.getFrameAtTime(); 
    } catch (IllegalArgumentException ex) { 
     ex.printStackTrace(); 
    } catch (RuntimeException ex) { 
     ex.printStackTrace(); 
    } finally { 
     try { 
      retriever.release(); 
     } catch (RuntimeException ex) { 
     } 
    } 
    return null; 
} 

En lugar de la URI se pueden pasar directamente tu url

+0

se requiere api 14. cómo usar en api debajo de él. – Suraj

+0

simplemente utiliza este FFmpegMediaMetadataRetriever https://github.com/wseemann/FFmpegMediaMetadataRetriever – arul

0

que estaba recibiendo el mismo error utilizando los ThumbnailUtils clase http://developer.android.com/reference/android/media/ThumbnailUtils.html
Utiliza MediaMetadataRetriever bajo el capó y la mayoría de las veces se puede enviar una ruta de archivo utilizando este método sin ningún problema:

public static Bitmap createVideoThumbnail (String filePath, int kind) 

Sin embargo, en Android 4.0.4, seguí recibiendo el mismo error que estaba viendo @gabi. El uso de un descriptor de archivo en su lugar resolvió el problema y aún funciona para dispositivos que no sean 4.0.4. De hecho, terminé subclasando ThumbnailUtils. Aquí está mi método de subclase:

public static Bitmap createVideoThumbnail(FileDescriptor fDescriptor, int kind) 
{ 
    Bitmap bitmap = null; 
    MediaMetadataRetriever retriever = new MediaMetadataRetriever(); 
    try { 
     retriever.setDataSource(fDescriptor); 
     bitmap = retriever.getFrameAtTime(-1); 
    } 
    catch (IllegalArgumentException ex) { 
     // Assume this is a corrupt video file 
     Log.e(LOG_TAG, "Failed to create video thumbnail for file description: " + fDescriptor.toString()); 
    } 
    catch (RuntimeException ex) { 
     // Assume this is a corrupt video file. 
     Log.e(LOG_TAG, "Failed to create video thumbnail for file description: " + fDescriptor.toString()); 
    } finally { 
     try { 
      retriever.release(); 
     } catch (RuntimeException ex) { 
      // Ignore failures while cleaning up. 
     } 
    } 

    if (bitmap == null) return null; 

    if (kind == Images.Thumbnails.MINI_KIND) { 
     // Scale down the bitmap if it's too large. 
     int width = bitmap.getWidth(); 
     int height = bitmap.getHeight(); 
     int max = Math.max(width, height); 
     if (max > 512) { 
      float scale = 512f/max; 
      int w = Math.round(scale * width); 
      int h = Math.round(scale * height); 
      bitmap = Bitmap.createScaledBitmap(bitmap, w, h, true); 
     } 
    } else if (kind == Images.Thumbnails.MICRO_KIND) { 
     bitmap = extractThumbnail(bitmap, 
       TARGET_SIZE_MICRO_THUMBNAIL, 
       TARGET_SIZE_MICRO_THUMBNAIL, 
       OPTIONS_RECYCLE_INPUT); 
    } 
    return bitmap; 
} 
0

La excepción se produce también cuando el File no existe.Entonces, antes de llamar al setDataSource(), es mejor que compruebe si new File(url).exists().

0

Utilicé este código y eso está funcionando para mí. puedes probar este.

if (Build.VERSION.SDK_INT >= 14) { 
       ffmpegMetaDataRetriever.setDataSource(
         videoFile.getAbsolutePath(), 
         new HashMap<String, String>()); 
      } else { 
       ffmpegMetaDataRetriever.setDataSource(videoFile 
         .getAbsolutePath()); 
      }