How to capture frame by frame images from Android video recording in real time
One can get frames by using ImageReader for camera2 API. And preview callback for camera1 API.
Here is how to do it with camera2 API.
One can also explore this library for working example with both camera2 and camera1 API.
How to capture screenshot or video frame of VideoView in Android
I have found a solution to this problem. It appears that the VideoView does not allow this because of low-level hardware GPU reasons while using a SurfaceView.
The solution is to use a TextureView and use a MediaPlayer to play a video inside of it. The Activity will need to implement TextureView.SurfaceTextureListener. When taking a screenshot with this solution, the video freezes for a short while. Also, the TextureView does not display a default UI for the playback progress bar (play, pause, FF/RW, play time, etc). That is one drawback. If you have another solution please let me know :)
Here is the solution:
public class TextureViewActivity extends Activity
implements TextureView.SurfaceTextureListener,
OnBufferingUpdateListener,
OnCompletionListener,
OnPreparedListener,
OnVideoSizeChangedListener
{
private MediaPlayer mp;
private TextureView tv;
public static String MY_VIDEO = "https://www.blahblahblah.com/myVideo.mp4";
public static String TAG = "TextureViewActivity";
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_texture_view);
tv = (TextureView) findViewById(R.id.textureView1);
tv.setSurfaceTextureListener(this);
}
public void getBitmap(TextureView vv)
{
String mPath = Environment.getExternalStorageDirectory().toString()
+ "/Pictures/" + Utilities.getDayTimeString() + ".png";
Toast.makeText(getApplicationContext(), "Capturing Screenshot: " + mPath, Toast.LENGTH_SHORT).show();
Bitmap bm = vv.getBitmap();
if(bm == null)
Log.e(TAG,"bitmap is null");
OutputStream fout = null;
File imageFile = new File(mPath);
try {
fout = new FileOutputStream(imageFile);
bm.compress(Bitmap.CompressFormat.PNG, 90, fout);
fout.flush();
fout.close();
} catch (FileNotFoundException e) {
Log.e(TAG, "FileNotFoundException");
e.printStackTrace();
} catch (IOException e) {
Log.e(TAG, "IOException");
e.printStackTrace();
}
}
@Override
public boolean onCreateOptionsMenu(Menu menu) {
// Inflate the menu; this adds items to the action bar if it is present.
getMenuInflater().inflate(R.menu.media_player_video, menu);
return true;
}
@Override
public boolean onOptionsItemSelected(MenuItem item) {
// Handle action bar item clicks here. The action bar will
// automatically handle clicks on the Home/Up button, so long
// as you specify a parent activity in AndroidManifest.xml.
int id = item.getItemId();
if (id == R.id.action_settings) {
return true;
}
return super.onOptionsItemSelected(item);
}
@Override
public void onSurfaceTextureAvailable(SurfaceTexture surface, int width, int height)
{
Surface s = new Surface(surface);
try
{
mp = new MediaPlayer();
mp.setDataSource(MY_VIDEO);
mp.setSurface(s);
mp.prepare();
mp.setOnBufferingUpdateListener(this);
mp.setOnCompletionListener(this);
mp.setOnPreparedListener(this);
mp.setOnVideoSizeChangedListener(this);
mp.setAudioStreamType(AudioManager.STREAM_MUSIC);
mp.start();
Button b = (Button) findViewById(R.id.textureViewButton);
b.setOnClickListener(new OnClickListener(){
@Override
public void onClick(View v)
{
TextureViewActivity.this.getBitmap(tv);
}
});
}
catch (IllegalArgumentException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (SecurityException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (IllegalStateException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
Capture video frames with opencv in android
Here is how to do it:
public Mat onCameraFrame(CameraBridgeViewBase.CvCameraViewFrame inputFrame) {
//Do your processing here, for example:
Mat image = inputFrame.rgba();
Mat ret_mat=new Mat();
Core.add(image, new Scalar(40, 40, 40, 0), ret_mat); //change brightness of video frame
return ret_mat;
}
OpenCv functions operate with Mat object, which represents matrix of pixels of your image/frame. The code above makes each frame brighter by 40 units.
android capture video frame
The following works for me:
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;
}
Also works if you use a path instead of a filedescriptor.
Android - How to get a screen recording's frames in real time using MediaRecorder
You wouldn't do an ImageView for this. You'd use a SurfaceView. It's meant to be used for things like media playback. https://developer.android.com/reference/android/view/SurfaceView?hl=en
You can find a bunch of examples on how to use it on Google, such as https://gist.github.com/scottgwald/7743453
Related Topics
Why Getcontext() in Fragment Sometimes Returns Null
How to Print Stacktrace for an Exception Android
Android Ndk: Link Using a Pre-Compiled Static Library
Use Recyclerview Inside Scrollview with Flexible Recycler Item Height
Android Httpclient Hangs on Second Request to the Server (Connection Timed Out)
Android Save Images to SQLite or Sdcard or Memory
Mediaplayer Error (1, -1004) Aka Media_Error_Io Trying to Stream Music on Samsung S3
Developing a Custom Lock Screen
How to Make Proguard Ignore External Libraries
Firebaseinitprovider: Firebaseapp Initialization Unsuccessful
Using Tesseract for Handwriting Recognition
How to Create Xmpp Chat Client for Facebook
Android 1.5: Reading Sms Messages
Eclipse Android Project, How to Reference Library Within Workspace
Android - Preserve or Delete Files Created by the Application on Uninstall