Используйте ChatGPT для записи Camera2, чтобы делать снимки во время записи видео, не прерывая запись.

Запись вопроса

Вставьте сюда описание изображения
Вставьте сюда описание изображения
Вставьте сюда описание изображения
Вставьте сюда описание изображения

отладочный код

Как вы можете видеть из ответов на вопросы, основной код в основном был предоставлен. Здесь мы можем дополнить XML-код на основе опыта или продолжить запросить подробный код (конечно, мы также можем напрямую опубликовать код ошибки, чтобы задать вопросы).
Вставьте сюда описание изображения

Скорректированный код

xml

<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="match_parent">
    <TextureView
        android:id="@+id/textureview"
        android:layout_width="fill_parent"
        android:layout_height="fill_parent"/>

    <LinearLayout
        android:layout_width="match_parent"
        android:layout_height="wrap_content">
        <Button
            android:id="@+id/start"
            android:layout_width="0dp"
            android:layout_height="wrap_content"
            android:layout_weight="1"
            android:onClick="startRtmp"
            android:text="开始推流"/>
        <Button
            android:id="@+id/stop"
            android:layout_width="0dp"
            android:layout_height="wrap_content"
            android:layout_weight="1"
            android:onClick="stopRtmp"
            android:text="关闭推流"/>
        <Button
            android:id="@+id/take_photo"
            android:layout_width="0dp"
            android:layout_height="wrap_content"
            android:layout_weight="1"
            android:onClick="takePhoto"
            android:text="拍照"/>
    </LinearLayout>
</RelativeLayout>

Код активности

package runde.mark.demo;

import android.Manifest;
import android.content.Context;
import android.content.pm.PackageManager;
import android.graphics.ImageFormat;
import android.graphics.SurfaceTexture;
import android.hardware.camera2.CameraAccessException;
import android.hardware.camera2.CameraCaptureSession;
import android.hardware.camera2.CameraCharacteristics;
import android.hardware.camera2.CameraDevice;
import android.hardware.camera2.CameraManager;
import android.hardware.camera2.CaptureRequest;
import android.hardware.camera2.params.StreamConfigurationMap;
import android.media.Image;
import android.media.ImageReader;
import android.media.MediaCodec;
import android.media.MediaRecorder;
import android.os.Build;
import android.os.Bundle;
import android.os.Handler;
import android.os.HandlerThread;
import android.util.Log;
import android.util.Size;
import android.view.Surface;
import android.view.TextureView;
import android.view.View;
import android.widget.Button;

import androidx.annotation.NonNull;
import androidx.annotation.RequiresApi;
import androidx.appcompat.app.AppCompatActivity;
import androidx.core.app.ActivityCompat;

import java.io.File;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.nio.ByteBuffer;
import java.util.Arrays;

/**
 * Created by 玉念聿辉.
 * User: 吴明辉
 * Date: 2023/5/4
 * Time: 10:02
 */
public class MainActivity extends AppCompatActivity {

    private static final String TAG = "MainActivity";

    private Size videoSize;
    private Size previewSize;

    private CameraDevice cameraDevice;
    private CameraCaptureSession cameraCaptureSession;
    private CaptureRequest.Builder captureRequestBuilder;
    private MediaRecorder mediaRecorder;
    private TextureView textureView;
    private Surface previewSurface;
    private Surface recordSurface;
    private ImageReader imageReader;

    private Handler mHandler;
    private boolean isTakePhoto = false;


    @RequiresApi(api = Build.VERSION_CODES.M)
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.camera);
        Button start = findViewById(R.id.start);
        start.setText("开始录制");
        Button stop = findViewById(R.id.stop);
        stop.setText("关闭录制");

        HandlerThread mThreadHandler = new HandlerThread("CAMERA2");
        mThreadHandler.start();
        mHandler = new Handler(mThreadHandler.getLooper());

        // 初始化 MediaRecorder
        startRecordingVideo();

        // 创建 ImageReader,并设置监听器
        imageReader = ImageReader.newInstance(1920, 1080, ImageFormat.JPEG, 1);
        imageReader.setOnImageAvailableListener(imageReader -> {
            // 获取最新的图片
            Image image = imageReader.acquireLatestImage();

            // 将图片保存为文件
            if (isTakePhoto) {
                FileOutputStream output = null;
                try {
                    // 创建保存图片的文件
                    File pictureFile = new File(getExternalFilesDir(null), System.currentTimeMillis() + ".jpg");
                    Log.e(TAG, "onImageAvailable  图片地址: " + pictureFile.getAbsolutePath());
                    output = new FileOutputStream(pictureFile);
                    ByteBuffer buffer = image.getPlanes()[0].getBuffer();
                    byte[] bytes = new byte[buffer.remaining()];
                    buffer.get(bytes);
                    output.write(bytes);
                } catch (FileNotFoundException e) {
                    e.printStackTrace();
                } catch (IOException e) {
                    e.printStackTrace();
                } finally {
                    if (output != null) {
                        try {
                            output.close();
                        } catch (IOException e) {
                            e.printStackTrace();
                        }
                    }
                    isTakePhoto = false;
                }
            }
            if (image != null) {
                image.close();
            }
        }, mHandler);

        // 设置监听器,并打开相机并启动预览
        textureView = findViewById(R.id.textureview);
        textureView.setSurfaceTextureListener(new TextureView.SurfaceTextureListener() {
            @Override
            public void onSurfaceTextureAvailable(@NonNull SurfaceTexture surfaceTexture, int i, int i1) {
                // 打开相机并启动预览
                if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
                    openCamera();
                }
            }

            @Override
            public void onSurfaceTextureSizeChanged(@NonNull SurfaceTexture surfaceTexture, int i, int i1) {

            }

            @Override
            public boolean onSurfaceTextureDestroyed(@NonNull SurfaceTexture surfaceTexture) {
                return false;
            }

            @Override
            public void onSurfaceTextureUpdated(@NonNull SurfaceTexture surfaceTexture) {

            }
        });

    }

    // 打开相机
    @RequiresApi(api = Build.VERSION_CODES.LOLLIPOP)
    private void openCamera() {
        CameraManager cameraManager = (CameraManager) getSystemService(Context.CAMERA_SERVICE);
        try {
            // 获取可用的摄像头列表
            String[] cameraIds = cameraManager.getCameraIdList();

            // 选择后置摄像头作为默认摄像头
            String cameraId = null;
            for (String id : cameraIds) {
                CameraCharacteristics cameraCharacteristics = cameraManager.getCameraCharacteristics(id);
                if (cameraCharacteristics.get(CameraCharacteristics.LENS_FACING)
                        == CameraCharacteristics.LENS_FACING_BACK) {
                    cameraId = id;
                    break;
                }
            }

            // 获取相机支持的预览尺寸和视频尺寸
            CameraCharacteristics cameraCharacteristics = cameraManager.getCameraCharacteristics(cameraId);
            StreamConfigurationMap streamConfigurationMap = cameraCharacteristics.get(CameraCharacteristics.SCALER_STREAM_CONFIGURATION_MAP);
            previewSize = streamConfigurationMap.getOutputSizes(SurfaceTexture.class)[0];
            videoSize = chooseVideoSize(streamConfigurationMap.getOutputSizes(MediaRecorder.class));

            // 打开相机并启动预览
            if (ActivityCompat.checkSelfPermission(this, Manifest.permission.CAMERA) != PackageManager.PERMISSION_GRANTED) {
                return;
            }
            cameraManager.openCamera(cameraId, new CameraDevice.StateCallback() {
                @RequiresApi(api = Build.VERSION_CODES.M)
                @Override
                public void onOpened(CameraDevice cameraDevice) {
                    MainActivity.this.cameraDevice = cameraDevice;

                    try {
                        // 创建预览请求,以及对应的 Surface
                        captureRequestBuilder = cameraDevice.createCaptureRequest(CameraDevice.TEMPLATE_RECORD);
                        SurfaceTexture surfaceTexture = textureView.getSurfaceTexture();
                        surfaceTexture.setDefaultBufferSize(previewSize.getWidth(), previewSize.getHeight());
                        previewSurface = new Surface(surfaceTexture);
                        captureRequestBuilder.addTarget(previewSurface);

                        // 创建录制请求,以及对应的 Surface
                        captureRequestBuilder.addTarget(recordSurface);

                        // 添加拍照 Surface
                        captureRequestBuilder.addTarget(imageReader.getSurface());

                        // 创建 CameraCaptureSession
                        cameraDevice.createCaptureSession(Arrays.asList(previewSurface, recordSurface, imageReader.getSurface()),
                                new CameraCaptureSession.StateCallback() {
                                    @Override
                                    public void onConfigured(CameraCaptureSession cameraCaptureSession) {
                                        MainActivity.this.cameraCaptureSession = cameraCaptureSession;

                                        try {
                                            captureRequestBuilder.set(CaptureRequest.CONTROL_AF_MODE,
                                                    CaptureRequest.CONTROL_AF_MODE_CONTINUOUS_PICTURE);
                                            cameraCaptureSession.setRepeatingRequest(captureRequestBuilder.build(),
                                                    null, mHandler);
                                        } catch (CameraAccessException e) {
                                            Log.e(TAG, "Failed to start preview", e);
                                        }
                                    }

                                    @Override
                                    public void onConfigureFailed(CameraCaptureSession cameraCaptureSession) {
                                        Log.e(TAG, "Failed to create capture session");
                                    }
                                }, mHandler);
                    } catch (CameraAccessException e) {
                        Log.e(TAG, "Failed to create capture request", e);
                    }
                }

                @Override
                public void onDisconnected(CameraDevice cameraDevice) {
                    cameraDevice.close();
                    MainActivity.this.cameraDevice = null;
                }

                @Override
                public void onError(CameraDevice cameraDevice, int error) {
                    cameraDevice.close();
                    MainActivity.this.cameraDevice = null;
                }
            }, mHandler);
        } catch (CameraAccessException e) {
            Log.e(TAG, "Failed to get camera id list", e);
        }
    }

    // 选择视频尺寸
    @RequiresApi(api = Build.VERSION_CODES.LOLLIPOP)
    private Size chooseVideoSize(Size[] sizes) {
        for (Size size : sizes) {
            if (size.getWidth() ==
                    size.getHeight() * 16 / 9 &&
                    size.getWidth() <= 1920) {
                return size;
            }
        }
        return sizes[0];
    }

    @RequiresApi(api = Build.VERSION_CODES.LOLLIPOP)
    private void updateView() {
        try {
            captureRequestBuilder = cameraDevice.createCaptureRequest(CameraDevice.TEMPLATE_RECORD);
            captureRequestBuilder.addTarget(previewSurface);

            // 创建录制请求,以及对应的 Surface
            captureRequestBuilder.addTarget(recordSurface);

            // 添加拍照 Surface
            captureRequestBuilder.addTarget(imageReader.getSurface());
            captureRequestBuilder.set(CaptureRequest.CONTROL_AF_MODE, CaptureRequest.CONTROL_AF_MODE_CONTINUOUS_PICTURE);
            cameraCaptureSession.setRepeatingRequest(captureRequestBuilder.build(), null, mHandler);
            Log.e(TAG, "updateView");
        } catch (CameraAccessException e) {
            Log.e(TAG, "Failed to start preview", e);
        }
    }


    // 启动录制视频
    private void startRecordingVideo() {
        try {
            // 配置 MediaRecorder
            if (mediaRecorder == null) {
                mediaRecorder = new MediaRecorder();
                if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
                    recordSurface = MediaCodec.createPersistentInputSurface();
                }
            } else {
                mediaRecorder.reset();
            }
            if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
                mediaRecorder.setInputSurface(recordSurface);
            }
            mediaRecorder.setAudioSource(MediaRecorder.AudioSource.DEFAULT);
            mediaRecorder.setVideoSource(MediaRecorder.VideoSource.SURFACE);
            mediaRecorder.setOutputFormat(MediaRecorder.OutputFormat.MPEG_2_TS);
            mediaRecorder.setOutputFile(getOutputFile());
            mediaRecorder.setVideoEncodingBitRate(5 * 1024 * 1024);
            mediaRecorder.setVideoFrameRate(30);
            mediaRecorder.setVideoSize(1920, 1080);
            mediaRecorder.setVideoEncoder(MediaRecorder.VideoEncoder.H264);
            mediaRecorder.setAudioEncoder(MediaRecorder.AudioEncoder.AAC);
            mediaRecorder.prepare();
            mediaRecorder.start();

            //再次录制时刷新预览
            if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP && cameraCaptureSession != null) {
                updateView();
            }
        } catch (IOException e) {
            Log.e(TAG, "Failed to start recording video", e);
        }
    }

    // 停止录制视频
    private void stopRecordingVideo() {
        if (mediaRecorder != null) {
            mediaRecorder.stop();
            mediaRecorder.reset();
        }
    }

    // 获取输出文件路径
    private String getOutputFile() {
        File file = new File(this.getExternalFilesDir(null), System.currentTimeMillis() + ".ts");
        Log.e(TAG, "getOutputFile  视频路径: " + file.getAbsolutePath());
        return file.getAbsolutePath();
    }

    @RequiresApi(api = Build.VERSION_CODES.LOLLIPOP)
    public void startRtmp(View view) {
        Log.e(TAG, "startRtmp: 开始录制");
        startRecordingVideo();
    }

    @RequiresApi(api = Build.VERSION_CODES.LOLLIPOP)
    public void stopRtmp(View view) {
        Log.e(TAG, "stopRtmp: 关闭录制");
        stopRecordingVideo();
    }

    public void takePhoto(View view) {
        Log.e(TAG, "takePhoto: 拍照");
        isTakePhoto = true;
    }
}

Не забудьте добавить разрешения

    <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
    <uses-permission android:name="android.permission.READ_INTERNAL_STORAGE" />
    <uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" />
    <uses-permission android:name="android.permission.RECORD_AUDIO" />
    <uses-permission android:name="android.permission.CAMERA" />

текущий результат

Вставьте сюда описание изображения

Supongo que te gusta

Origin blog.csdn.net/qq_35350654/article/details/130485177
Recomendado
Clasificación