我正在尝试使用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的视频,所以我在这里肯定错过了一些东西。相机管理器总共识别了两个相机设备。当我使用来自 CameraCharacteristics 的 getOutPutFormats() 时,它为两个相机显示相同的有效分辨率集,并且与上述错误消息的范围相同。
以下是我用来初始化媒体记录器并启动捕获会话的代码:
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 onOpen 回调:
@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());
}
}
我尝试弄乱通话顺序和输出格式/编码器,但没有运气。我确信我拥有所有必需的权限。提前感谢您的时间!
此设备很可能在 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预览,这对于最近推出的设备来说是非常不寻常的。
您可以验证已弃用的相机 API 中支持的预览大小集是否与您在错误中获得的列表匹配;如果不是,则在生成列表时可能存在操作系统错误,因此很高兴知道。
但通常,您不能请求相机的 CameraCharacteristics StreamConfiguraitonMap 中未枚举的大小,无论框侧面的功能列表显示什么。 有时,OEM 相机应用具有魔术钩子,可以启用普通应用无法访问的功能;通常是因为该功能仅在一些非常非常特定的情况下有效,普通应用程序不知道如何复制。