Recording Video with a Specific Resolution in Android

Understanding Video Recording

Video recording in Android involves capturing frames at a certain rate (frames per second) and storing them in a video file format. The resolution determines the size of each frame, influencing the overall quality and file size.

Setting Video Resolution

Android provides flexible control over video recording parameters, including resolution. Here’s how to record a video with 480×480 pixels:

Using CameraX

CameraX is a modern and simplified API for camera operations in Android.

“`java
import androidx.camera.core.CameraSelector;
import androidx.camera.core.ImageCapture;
import androidx.camera.core.ImageCaptureException;
import androidx.camera.core.Preview;
import androidx.camera.lifecycle.ProcessCameraProvider;
import androidx.core.content.ContextCompat;

import android.Manifest;
import android.content.pm.PackageManager;
import android.graphics.Rect;
import android.media.MediaRecorder;
import android.os.Bundle;
import android.util.Log;
import android.view.View;
import android.widget.Button;
import android.widget.Toast;

import androidx.appcompat.app.AppCompatActivity;
import androidx.core.app.ActivityCompat;

import java.io.File;
import java.io.IOException;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.Locale;

public class MainActivity extends AppCompatActivity {

private static final String TAG = “MainActivity”;
private static final int REQUEST_CODE_PERMISSIONS = 10;
private static final String[] REQUIRED_PERMISSIONS = new String[]{Manifest.permission.CAMERA, Manifest.permission.RECORD_AUDIO};

private CameraSelector cameraSelector;
private CameraX.ProcessCameraProvider cameraProvider;
private Preview preview;
private ImageCapture imageCapture;
private MediaRecorder mediaRecorder;
private File videoFile;
private Button startButton;
private Button stopButton;

@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);

startButton = findViewById(R.id.startButton);
stopButton = findViewById(R.id.stopButton);

startButton.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
startRecording();
}
});

stopButton.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
stopRecording();
}
});

if (allPermissionsGranted()) {
startCamera();
} else {
ActivityCompat.requestPermissions(this, REQUIRED_PERMISSIONS, REQUEST_CODE_PERMISSIONS);
}
}

private void startCamera() {
cameraSelector = new CameraSelector.Builder()
.requireLensFacing(CameraSelector.LENS_FACING_BACK)
.build();

preview = new Preview.Builder()
.build();

imageCapture = new ImageCapture.Builder()
.setTargetResolution(new Size(480, 480)) // Set the desired resolution
.build();

ProcessCameraProvider.getInstance(this).addListener(() -> {
try {
cameraProvider = ProcessCameraProvider.getInstance(this).get();
cameraProvider.unbindAll();
cameraProvider.bindToLifecycle(this, cameraSelector, preview, imageCapture);
} catch (Exception e) {
Log.e(TAG, “Use case binding failed”, e);
}
}, ContextCompat.getMainExecutor(this));
}

private void startRecording() {
mediaRecorder = new MediaRecorder();
videoFile = createFileForRecording();

try {
mediaRecorder.setAudioSource(MediaRecorder.AudioSource.MIC);
mediaRecorder.setVideoSource(MediaRecorder.VideoSource.SURFACE);
mediaRecorder.setOutputFormat(MediaRecorder.OutputFormat.MPEG_4);
mediaRecorder.setOutputFile(videoFile.getAbsolutePath());
mediaRecorder.setVideoEncodingBitRate(1000000);
mediaRecorder.setVideoFrameRate(30);
mediaRecorder.setVideoSize(480, 480); // Set the desired resolution
mediaRecorder.setAudioEncoder(MediaRecorder.AudioEncoder.AAC);
mediaRecorder.setVideoEncoder(MediaRecorder.VideoEncoder.H264);
mediaRecorder.prepare();
mediaRecorder.start();
Toast.makeText(this, “Recording started”, Toast.LENGTH_SHORT).show();
} catch (IOException e) {
Log.e(TAG, “Failed to start recording”, e);
Toast.makeText(this, “Failed to start recording”, Toast.LENGTH_SHORT).show();
}
}

private void stopRecording() {
if (mediaRecorder != null) {
try {
mediaRecorder.stop();
mediaRecorder.release();
Toast.makeText(this, “Recording stopped”, Toast.LENGTH_SHORT).show();
} catch (Exception e) {
Log.e(TAG, “Failed to stop recording”, e);
Toast.makeText(this, “Failed to stop recording”, Toast.LENGTH_SHORT).show();
}
}
}

private File createFileForRecording() {
String timestamp = new SimpleDateFormat(“yyyyMMdd_HHmmss”, Locale.getDefault()).format(new Date());
File storageDir = getExternalFilesDir(Environment.DIRECTORY_MOVIES);
return new File(storageDir, “VID_” + timestamp + “.mp4”);
}

private boolean allPermissionsGranted() {
for (String permission : REQUIRED_PERMISSIONS) {
if (ContextCompat.checkSelfPermission(this, permission) != PackageManager.PERMISSION_GRANTED) {
return false;
}
}
return true;
}

@Override
public void onRequestPermissionsResult(int requestCode, @NonNull String[] permissions, @NonNull int[] grantResults) {
super.onRequestPermissionsResult(requestCode, permissions, grantResults);
if (requestCode == REQUEST_CODE_PERMISSIONS) {
if (allPermissionsGranted()) {
startCamera();
} else {
Toast.makeText(this, “Permissions not granted by the user.”, Toast.LENGTH_SHORT).show();
finish();
}
}
}
}
“`

Using MediaRecorder

MediaRecorder is a traditional API for audio and video recording.

“`java
import android.Manifest;
import android.content.pm.PackageManager;
import android.hardware.Camera;
import android.media.CamcorderProfile;
import android.media.MediaRecorder;
import android.os.Bundle;
import android.os.Environment;
import android.util.Log;
import android.view.SurfaceHolder;
import android.view.SurfaceView;
import android.widget.Button;
import android.widget.Toast;

import androidx.appcompat.app.AppCompatActivity;
import androidx.core.app.ActivityCompat;
import androidx.core.content.ContextCompat;

import java.io.File;
import java.io.IOException;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.Locale;

public class MainActivity extends AppCompatActivity implements SurfaceHolder.Callback {

private static final String TAG = “MainActivity”;
private static final int REQUEST_CODE_PERMISSIONS = 10;
private static final String[] REQUIRED_PERMISSIONS = new String[]{Manifest.permission.CAMERA, Manifest.permission.RECORD_AUDIO};

private SurfaceView surfaceView;
private SurfaceHolder surfaceHolder;
private MediaRecorder mediaRecorder;
private Camera camera;
private Button startButton;
private Button stopButton;

@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);

startButton = findViewById(R.id.startButton);
stopButton = findViewById(R.id.stopButton);
surfaceView = findViewById(R.id.surfaceView);

surfaceHolder = surfaceView.getHolder();
surfaceHolder.addCallback(this);
surfaceHolder.setType(SurfaceHolder.SURFACE_TYPE_PUSH_BUFFERS);

startButton.setOnClickListener(view -> {
if (mediaRecorder != null) {
startRecording();
} else {
Toast.makeText(MainActivity.this, “Please start camera first.”, Toast.LENGTH_SHORT).show();
}
});

stopButton.setOnClickListener(view -> stopRecording());

if (allPermissionsGranted()) {
startCamera();
} else {
ActivityCompat.requestPermissions(this, REQUIRED_PERMISSIONS, REQUEST_CODE_PERMISSIONS);
}
}

private void startCamera() {
camera = Camera.open(Camera.CameraInfo.CAMERA_FACING_BACK);
try {
camera.setPreviewDisplay(surfaceHolder);
camera.startPreview();
} catch (IOException e) {
Log.e(TAG, “Failed to start camera preview”, e);
}
}

private void startRecording() {
try {
mediaRecorder = new MediaRecorder();
mediaRecorder.setAudioSource(MediaRecorder.AudioSource.MIC);
mediaRecorder.setVideoSource(MediaRecorder.VideoSource.CAMERA);
mediaRecorder.setOutputFormat(MediaRecorder.OutputFormat.MPEG_4);
mediaRecorder.setOutputFile(createFileForRecording().getAbsolutePath());

// Set the video resolution to 480×480
mediaRecorder.setVideoSize(480, 480);

// Other recording settings can be configured here

mediaRecorder.setVideoEncoder(MediaRecorder.VideoEncoder.H264);
mediaRecorder.setAudioEncoder(MediaRecorder.AudioEncoder.AAC);

mediaRecorder.setPreviewDisplay(surfaceHolder.getSurface());
mediaRecorder.prepare();
mediaRecorder.start();
Toast.makeText(this, “Recording started”, Toast.LENGTH_SHORT).show();
} catch (IOException e) {
Log.e(TAG, “Failed to start recording”, e);
Toast.makeText(this, “Failed to start recording”, Toast.LENGTH_SHORT).show();
}
}

private void stopRecording() {
if (mediaRecorder != null) {
try {
mediaRecorder.stop();
mediaRecorder.reset();
mediaRecorder.release();
mediaRecorder = null;
Toast.makeText(this, “Recording stopped”, Toast.LENGTH_SHORT).show();
} catch (Exception e) {
Log.e(TAG, “Failed to stop recording”, e);
Toast.makeText(this, “Failed to stop recording”, Toast.LENGTH_SHORT).show();
}
}
if (camera != null) {
camera.stopPreview();
camera.release();
camera = null;
}
}

private File createFileForRecording() {
String timestamp = new SimpleDateFormat(“yyyyMMdd_HHmmss”, Locale.getDefault()).format(new Date());
File storageDir = getExternalFilesDir(Environment.DIRECTORY_MOVIES);
return new File(storageDir, “VID_” + timestamp + “.mp4”);
}

private boolean allPermissionsGranted() {
for (String permission : REQUIRED_PERMISSIONS) {
if (ContextCompat.checkSelfPermission(this, permission) != PackageManager.PERMISSION_GRANTED) {
return false;
}
}
return true;
}

@Override
public void onRequestPermissionsResult(int requestCode, String[] permissions, int[] grantResults) {
super.onRequestPermissionsResult(requestCode, permissions, grantResults);
if (requestCode == REQUEST_CODE_PERMISSIONS) {
if (allPermissionsGranted()) {
startCamera();
} else {
Toast.makeText(this, “Permissions not granted by the user.”, Toast.LENGTH_SHORT).show();
finish();
}
}
}

@Override
public void surfaceCreated(SurfaceHolder holder) {
// Nothing to do here
}

@Override
public void surfaceChanged(SurfaceHolder holder, int format, int width, int height) {
// Nothing to do here
}

@Override
public void surfaceDestroyed(SurfaceHolder holder) {
// Nothing to do here
}
}
“`

Choosing the Right API

| API | Pros | Cons |
|——————|———————————————|——————————————————-|
| CameraX | Modern, streamlined, easy to use | Requires Android API Level 21+ |
| MediaRecorder | Versatile, fine-grained control | Older API, more complex, prone to errors |

Important Considerations

* **Permissions:** You need to request camera and audio recording permissions from the user.
* **Output Format:** Choose an appropriate video format like MP4 for wide compatibility.
* **Frame Rate:** Adjust the frame rate (fps) based on your requirements.
* **Bitrate:** The bitrate affects the video quality and file size.
* **Device Support:** Verify that the target devices support the specified resolution.
* **Error Handling:** Implement robust error handling to catch exceptions during recording.

This article provides a foundation for recording videos with a specific resolution in Android. Experiment with different settings and APIs to achieve your desired results. Remember to prioritize user experience, optimize performance, and ensure a seamless recording process.

Leave a Reply

Your email address will not be published. Required fields are marked *