我正在尝试使用 Vivo X20 (7.1.1) 和camera2 api 录制视频,而不使用预览和录制声音(严格仅录制高清视频)。
我目前陷入困境,因为我无法弄清楚如何成功调用 MediaRecorder.setVideoSize() 并录制高清视频。目前,当我运行应用程序时,日志显示错误:尺寸 (w=1920, h=1080) 和格式 0x1 的表面无效,尺寸不在有效集中:[1440x1080、1280x960、1280x720、960x540、800x480、720x480、 768x432、640x480、384x288、352x288、320x240、176x144]
手机自带的相机应用程序可以录制高达 4K 的视频,所以我肯定错过了一些东西。 CameraManager总共识别出两个摄像头设备。当我使用 CameraCharacteristics 中的 getOutPutFormats() 时,它显示两个相机的相同有效分辨率集,并且与上述错误消息的范围相同。
下面是我用来初始化 MediaRecorder 并启动捕获 session 的代码:
public void StartRecordingVideo() {
Initialize();
recordingVideo = true;
cameraManager = (CameraManager) this.getSystemService(Context.CAMERA_SERVICE);
try {
if (ActivityCompat.checkSelfPermission(this, Manifest.permission.CAMERA) == PackageManager.PERMISSION_GRANTED) {
String[] cameraIDs = cameraManager.getCameraIdList();
//LogAllCameraInfo();
if (cameraIDs != null)
{
for(int x = 0; x < cameraIDs.length; x++)
{
Log.d(LOG_ID, "ID: " + cameraIDs[x]);
}
}
cameraManager.openCamera(deviceCameraID, cameraStateCallback, handler);
Log.d(LOG_ID, "Successfully opened camera");
}
else
{
throw new IllegalAccessException();
}
}
catch (Exception e)
{
recordingVideo = false;
Log.e(LOG_ID, "Error during record video start: " + e.getMessage());
}
}
private void Initialize()
{
videoRecordThread = new HandlerThread("video_capture");
videoRecordThread.start();
handler = new Handler((videoRecordThread.getLooper()));
try
{
vidRecorder = new MediaRecorder();
vidRecorder.setVideoSource(MediaRecorder.VideoSource.SURFACE);
vidRecorder.setOutputFormat(MediaRecorder.OutputFormat.MPEG_4);
vidRecorder.setVideoFrameRate(30);
vidRecorder.setCaptureRate(30);
vidRecorder.setVideoEncoder(MediaRecorder.VideoEncoder.DEFAULT);
vidRecorder.setVideoEncodingBitRate(10000000);
vidRecorder.setVideoSize(1920, 1080);
String videoFilename = Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_DOWNLOADS)+ File.separator + System.currentTimeMillis() + ".mp4";
vidRecorder.setOutputFile(videoFilename);
Log.d(LOG_ID, "Starting video: " + videoFilename);
vidRecorder.prepare();
}
catch (Exception e)
{
Log.e(LOG_ID, "Error during Initialize: " + e.getMessage());
}
}
以及 onReady/onSurfacePrepared/Camera onOpened 回调:
@Override
public void onReady(CameraCaptureSession session) {
Log.d(LOG_ID, "onReady: ");
super.onReady(session);
try {
CaptureRequest.Builder builder = deviceCamera.createCaptureRequest(CameraDevice.TEMPLATE_RECORD);
builder.addTarget(vidRecorder.getSurface());
CaptureRequest request = builder.build();
session.setRepeatingRequest(request, null, handler);
vidRecorder.start();
} catch (CameraAccessException e) {
Log.d(LOG_ID, "Error on Ready: " + e.getMessage());
}
}
@Override
public void onSurfacePrepared(CameraCaptureSession session, Surface surface) {
Log.d(LOG_ID, "onSurfacePrepared: ");
super.onSurfacePrepared(session, surface);
}
@Override
public void onOpened(CameraDevice camera) {
Log.d(LOG_ID, "onOpened: ");
deviceCamera = camera;
try {
camera.createCaptureSession(Arrays.asList(vidRecorder.getSurface()), recordSessionStateCallback, handler);
} catch (CameraAccessException e) {
Log.d(LOG_ID, "onOpened: " + e.getMessage());
}
}
我尝试过打乱调用顺序和输出格式/编码器,但没有成功。我确信我拥有所有必需的权限。预先感谢您的宝贵时间!
最佳答案
该设备很可能支持旧版级别的camera2;检查 INFO_SUPPORTED_HARDWARE_LEVEL 的输出是。
旧版设备在旧版 android.hardware.Camera API 之上有效运行camera2(比这更复杂,但大致正确);因此,他们通过camera2的功能受到限制。
最大录制分辨率是一个重要问题; android.hardware.Camera 通过一条神奇路径记录视频,LEGACY 映射层无法直接使用该路径(不涉及 Surface)。因此,camera2 LEGACY 只能以 android.hardware.Camera 支持的最大预览分辨率进行录制,而不能以最大录制分辨率进行录制。
听起来该设备不支持 1:1 1080p 预览,这对于最近推出的设备来说非常不寻常。
您可以验证已弃用的相机 API 中支持的预览尺寸集是否与您在错误中获得的列表相匹配;如果没有,那么生成列表时可能存在操作系统错误,因此最好了解一下。
但一般来说,无论包装盒侧面的功能列表如何说明,您都无法请求相机的 CameraCharacteristics StreamConfiguraitonMap 中未枚举的尺寸。有时,OEM 相机应用程序具有神奇的钩子(Hook)来启用普通应用程序无法使用的功能;通常是因为该功能仅在某些非常非常特定的情况下起作用,而普通应用程序不知道如何复制这些情况。
关于android - 在没有预览的情况下录制时,尺寸不在有效设置中,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/48411125/