Bootstrap

在Android开发中实现静默拍视频

在 Android 中自动拍摄视频通常可以通过 MediaRecorderCameraX 实现。以下是使用 CameraX 的方式来实现自动拍摄视频的详细代码,因为 CameraX 相对简单且适合大多数设备。

实现步骤

  1. 配置 CameraX 和 VideoCapture。
  2. 开始并自动停止录制视频。
  3. 保存视频文件。

准备工作

build.gradle 中添加依赖:

dependencies {
    def camerax_version = "1.2.0"
    implementation "androidx.camera:camera-core:$camerax_version"
    implementation "androidx.camera:camera-camera2:$camerax_version"
    implementation "androidx.camera:camera-lifecycle:$camerax_version"
    implementation "androidx.camera:camera-video:$camerax_version"
}

自动录制视频的 Java 代码

import android.Manifest;
import android.content.pm.PackageManager;
import android.os.Bundle;
import android.util.Log;
import android.widget.Toast;

import androidx.annotation.NonNull;
import androidx.annotation.OptIn;
import androidx.appcompat.app.AppCompatActivity;
import androidx.camera.core.CameraSelector;
import androidx.camera.lifecycle.ProcessCameraProvider;
import androidx.camera.video.FileOutputOptions;
import androidx.camera.video.PendingRecording;
import androidx.camera.video.Quality;
import androidx.camera.video.Recorder;
import androidx.camera.video.VideoCapture;
import androidx.camera.video.VideoRecordEvent;
import androidx.camera.video.VideoRecording;
import androidx.core.app.ActivityCompat;
import androidx.core.content.ContextCompat;

import com.google.common.util.concurrent.ListenableFuture;

import java.io.File;
import java.util.concurrent.ExecutionException;

public class VideoCaptureActivity extends AppCompatActivity {
    private static final int REQUEST_CODE_PERMISSIONS = 10;
    private static final String[] REQUIRED_PERMISSIONS = {Manifest.permission.CAMERA, Manifest.permission.RECORD_AUDIO};

    private VideoCapture<Recorder> videoCapture;
    private VideoRecording videoRecording;

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

        // 检查权限
        if (allPermissionsGranted()) {
            startCamera();  // 启动相机
        } else {
            ActivityCompat.requestPermissions(this, REQUIRED_PERMISSIONS, REQUEST_CODE_PERMISSIONS);
        }
    }

    // 检查权限是否被授予
    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();
            }
        }
    }

    // 启动CameraX
    private void startCamera() {
        ListenableFuture<ProcessCameraProvider> cameraProviderFuture = ProcessCameraProvider.getInstance(this);
        cameraProviderFuture.addListener(() -> {
            try {
                ProcessCameraProvider cameraProvider = cameraProviderFuture.get();
                bindVideoCapture(cameraProvider);
            } catch (ExecutionException | InterruptedException e) {
                Log.e("VideoCaptureActivity", "Error starting camera", e);
            }
        }, ContextCompat.getMainExecutor(this));
    }

    // 绑定视频捕获功能
    @OptIn(markerClass = androidx.camera.video.ExperimentalVideo.class)
    private void bindVideoCapture(@NonNull ProcessCameraProvider cameraProvider) {
        // 配置 Recorder 和 VideoCapture
        Recorder recorder = new Recorder.Builder()
                .setQualitySelector(QualitySelector.from(Quality.HD))
                .build();
        videoCapture = VideoCapture.withOutput(recorder);

        CameraSelector cameraSelector = CameraSelector.DEFAULT_BACK_CAMERA;

        try {
            // 取消之前的绑定并重新绑定
            cameraProvider.unbindAll();
            cameraProvider.bindToLifecycle(this, cameraSelector, videoCapture);
            startRecording();  // 自动开始录制视频
        } catch (Exception e) {
            Log.e("VideoCaptureActivity", "Error binding video capture", e);
        }
    }

    // 开始录制视频
    private void startRecording() {
        File outputDir = getExternalFilesDir(null);  // 获取文件保存路径
        File videoFile = new File(outputDir, "video_capture_" + System.currentTimeMillis() + ".mp4");

        // 设置文件输出选项
        FileOutputOptions fileOutputOptions = new FileOutputOptions.Builder(videoFile).build();
        
        // 创建录制会话
        PendingRecording pendingRecording = videoCapture.getOutput().prepareRecording(this, fileOutputOptions);

        if (ActivityCompat.checkSelfPermission(this, Manifest.permission.RECORD_AUDIO) == PackageManager.PERMISSION_GRANTED) {
            pendingRecording.withAudioEnabled();  // 启用音频录制
        }

        // 开始录制
        videoRecording = pendingRecording.start(ContextCompat.getMainExecutor(this), videoRecordEvent -> {
            if (videoRecordEvent instanceof VideoRecordEvent.Start) {
                Log.d("VideoCaptureActivity", "Recording started");
            } else if (videoRecordEvent instanceof VideoRecordEvent.Finalize) {
                // 录制完成后处理
                VideoRecordEvent.Finalize finalizeEvent = (VideoRecordEvent.Finalize) videoRecordEvent;
                if (!finalizeEvent.hasError()) {
                    Log.d("VideoCaptureActivity", "Video saved successfully: " + videoFile.getAbsolutePath());
                    Toast.makeText(this, "Video saved: " + videoFile.getAbsolutePath(), Toast.LENGTH_SHORT).show();
                } else {
                    Log.e("VideoCaptureActivity", "Error saving video: " + finalizeEvent.getError());
                }
            }
        });

        // 可选:指定录制时间限制,例如 10 秒后自动停止
        findViewById(R.id.stopRecordingButton).postDelayed(this::stopRecording, 10000); // 10 秒后停止录制
    }

    // 停止录制视频
    private void stopRecording() {
        if (videoRecording != null) {
            videoRecording.stop();
            videoRecording = null;
            Log.d("VideoCaptureActivity", "Recording stopped");
        }
    }
}

代码说明

  • 权限检查:代码会检查是否授予了摄像头和音频录制权限。
  • 绑定 CameraX:通过 CameraXVideoCapture 功能进行视频录制,使用 Recorder 来配置视频质量。
  • 自动开始和停止录制:代码中 startRecording() 方法会自动开始录制,并设置了一个 postDelayed() 方法,在 10 秒后自动停止录制。可以根据需要更改时间。
  • 文件保存:视频文件保存在 getExternalFilesDir() 目录下,文件名包含时间戳以避免重复。

注意事项

  1. 权限:确保在实际运行时已授予相机和麦克风权限。
  2. 保存路径:视频保存路径为 getExternalFilesDir(),这是一个沙盒目录,不需要额外的文件读写权限。

这样,您就可以通过 CameraX 在 Android 应用中实现自动拍摄视频。

;