我正在尝试使用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并启动捕获会话的代码:
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());
}
}
我已经尝试搞乱调用顺序和输出格式/编码器而没有运气。我确信我拥有所有必需的权限。提前感谢您的时间!
答案 0 :(得分:1)
此设备最有可能支持LEGACY级别的camera2;检查INFO_SUPPORTED_HARDWARE_LEVEL的输出是什么。
LEGACY设备在传统的android.hardware.Camera API之上有效地运行camera2(比这更复杂,但大致如此);结果,他们通过camera2的能力受到限制。
最大录音分辨率是一个重要问题; android.hardware.Camera通过LEGACY映射层无法直接使用的魔术路径录制视频(没有涉及Surface)。因此,camera2 LEGACY只能以android.hardware.Camera支持的最大预览分辨率进行录制,而不是以最高录制分辨率进行录制。
听起来这款设备不支持1:1 1080p预览,这对于最近推出的设备来说非常不寻常。
您可以验证已弃用的Camera API中支持的预览尺寸集是否与您在错误中获得的列表相匹配;如果它没有,那么在生成列表时可能存在操作系统错误,因此很容易知道。
但总的来说,无论盒子侧面的功能列表是什么,您都无法请求相机的CameraCharacteristics StreamConfiguraitonMap中未列出的大小。有时,OEM相机应用程序具有神奇的钩子,以启用普通应用程序无法实现的功能;通常因为该功能仅适用于一些非常特定的情况,普通应用程序不知道如何复制。