我想提取项目原始文件夹中的所有视频帧(mp4)。
val videoUri = Uri.parse("android.resource://" + packageName + "/" + R.raw.video_h)
captureVideoFrames(this@OutsideCamActivity, videoUri)
我可以使用下面给出的函数获取帧,但是速度很慢并且丢失帧。
private fun captureAndDisplayFrames(videoUri: Uri) {
lifecycleScope.launch(Dispatchers.IO) {
val retriever = MediaMetadataRetriever()
try {
retriever.setDataSource(this@OutsideCamActivity, videoUri)
// Get the video duration
val videoDuration =
retriever.extractMetadata(MediaMetadataRetriever.METADATA_KEY_DURATION)?.toLong() ?: 0L
var currentPosition = 0L
// Capture frames at regular intervals
while (currentPosition < videoDuration) {
// Extract frame at the current position
val frame: Bitmap? = retriever.getFrameAtTime(currentPosition * 1000, MediaMetadataRetriever.OPTION_CLOSEST_SYNC)
// Check if the frame was successfully retrieved
if (frame != null) {
// Update the ImageView on the main thread
withContext(Dispatchers.Main) {
imgOutH.setImageBitmap(frame)
}
} else {
Log.e("FrameExtraction", "No frame found at time: $currentPosition")
}
// Increment position (e.g., by 1 second or as per your requirement)
currentPosition += 1000 // Move to the next second
}
} catch (e: IllegalArgumentException) {
Log.e("FrameExtraction", "Invalid video source: ${e.message}")
} catch (e: IllegalStateException) {
Log.e("FrameExtraction", "Retriever not configured properly: ${e.message}")
} catch (e: Exception) {
Log.e("FrameExtraction", "Error retrieving frame: ${e.message}")
} finally {
retriever.release() // Always release the retriever resource
}
}
}
我所做的是捕获帧并设置在 ImageView 中。
我的要求不是在 ImageView 中设置,而是对图像进行一些处理,该图像也可以正常工作。捕获所有帧时出现问题。
MediaMetadataRetriever.OPTION_CLOSEST_SYNC
只为您提供 I 帧。但部分帧(通常是大多数)将会丢失。
您可以使用
MediaMetadataRetriever.OPTION_CLOSEST
来获取所有帧,但这很慢。
更有效的方法是将 MediaCodec 与 MediaExtractor 一起使用。