Get single bitmap frame from mp4?

canalrun

Well-Known Member
Licensed User
Longtime User
Hello,
I am using Erel's VideoRecordApp to record a short video and save it to a file. I would like to extract a single frame from the video to show as a thumbnail.

I found a similar post from two years ago – the reply was "probably not possible without decoding the entire video".

In searching the Internet I found the Android function MediaMetadataRetriever at: MediaMetadataRetriever | Android Developers

The functions getFrameAtTime() and setDataSource(String path) look like possibilities.

I also found a related question on Stack Overflow which uses this function: Extract bitmap from video in android - Stack Overflow.

Would it be possible, maybe using the Reflector or by creating a small library, to use these functions? Would they accomplish what I am thinking? – Extract a frame from a video that could be used as a thumbnail.

Is there a better way to do this?

Thanks,
Barry.
 

canalrun

Well-Known Member
Licensed User
Longtime User
You can use Reflection to call these methods. It should be quite simple and should do what you need. I can help you with the reflection code if you need.

Erel was correct – it was pretty simple.

I have attached a demo app below which is basically just a modification to Erel's VideoRecorderApp example.

I added Reflector code in the RecordComplete subroutine to create a "thumbnail" from the first frame of the recorded video. I then show the "thumbnail" in an ImageView. The "thumbnail" is pretty big and I modified the width and height disproportionally.

In the getFrameAtTime method call the first parameter, 0, is the time offset for the desired frame. The second parameter, 3, is the value of the option parameter, OPTION_CLOSEST, to retrieve a frame that is located closest to or at the given time.

This is the code I modified:
B4X:
Sub videoRecorder_RecordComplete (Success As Boolean)
    Log(Success)
    If Success Then
'        vv.LoadVideo(File.DirRootExternal, "1.mp4")
'        vv.Play

      Dim rfl As Reflector
     Dim obj As Object
     Dim b As Bitmap
     
     obj = rfl.CreateObject("android.media.MediaMetadataRetriever")
     rfl.Target = obj
      rfl.RunMethod2("setDataSource", vidfile, "java.lang.String")
      b = rfl.RunMethod3("getFrameAtTime", 0, "java.lang.long", 3, "java.lang.int")
     
     Dim i, j, h, w As Int
     Dim iv As ImageView
     
     i = b.Height * 0.3
     j = b.Width * 0.5
     h = Activity.Height
     w = Activity.Width
     
     iv.Initialize("")
     Activity.AddView(iv, (w - j) / 2, (h - i) / 3, j, i)
     iv.Bitmap = b
    End If
End Sub

Barry.
 

Attachments

  • vrapp.zip
    6.3 KB · Views: 687
Upvote 0

peacemaker

Expert
Licensed User
Longtime User
Just info:
getFrameAtTime is in microseconds, if to try to get the screenshot of the camera preview - the minimal value better to use = 2500000 (2.5 seconds after camera is started)
 
Upvote 0
Top