如何在某些Android设备上解决前置摄像头视频录制的神器问题?

时间:2014-03-13 20:39:40

标签: android android-camera android-mediarecorder

我正在尝试以编程方式记录Android设备前置摄像头的视频。虽然我拥有的大多数测试设备,包括Nexus 4,Nexus 7和三星Galaxy S4,都能正确录制视频,有些则没有。

例如,这是三星Galaxy S3录制的视频片段的屏幕截图:

artifacts

有奇怪的文物和颜色,视频似乎没有居中(它指向一个人的脸,你可以看到在镜头中几乎看不到)。

这是我的代码:

//
// starting code
//

CAMERA = Camera.open(Camera.CameraInfo.CAMERA_FACING_FRONT);
Camera.Parameters cameraParameters = CAMERA.getParameters();
if (cameraParameters.isZoomSupported()) {
    cameraParameters.setZoom(0);
}
CAMERA.setParameters(cameraParameters);
CAMERA.setDisplayOrientation(90);

CAMERA.setPreviewDisplay(CAMERA_SURFACE_VIEW.getHolder());
CAMERA.startPreview();
CAMERA.unlock();

CAMERA_MEDIA_RECORDER = new MediaRecorder();
CAMERA_MEDIA_RECORDER.setCamera(CAMERA);
try {
    CAMERA_MEDIA_RECORDER.setOrientationHint(270);
} catch (Exception e) {
    // this is to fix "setParameter failed" b/c of unsupported orientation hint
    CAMERA_MEDIA_RECORDER.setOrientationHint(90);
}
CAMERA_MEDIA_RECORDER.setAudioSource(MediaRecorder.AudioSource.CAMCORDER);
CAMERA_MEDIA_RECORDER.setVideoSource(MediaRecorder.VideoSource.CAMERA);

ArrayList<Integer> profileIds = new ArrayList<Integer>();

if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.HONEYCOMB) {
    profileIds.add(CamcorderProfile.QUALITY_480P);
    profileIds.add(CamcorderProfile.QUALITY_720P);
}

profileIds.add(CamcorderProfile.QUALITY_HIGH);
profileIds.add(CamcorderProfile.QUALITY_LOW);

CamcorderProfile camcorderProfile = null;

for (int profileId : profileIds) {
    try {
        camcorderProfile = CamcorderProfile.get(Camera.CameraInfo.CAMERA_FACING_FRONT, profileId);
        break; // found our most desired profile, done
    } catch (IllegalArgumentException e) {
        // profile not found on device... It's okay, the next one might exist.
        continue;
    } catch (RuntimeException e) {
        continue;
    }
}

if (camcorderProfile == null) {
    return false;
}

CAMERA_MEDIA_RECORDER.setProfile(camcorderProfile);
CAMERA_MEDIA_RECORDER.setAudioEncodingBitRate(96000);

int audioSamplingRate = 44100;

for (int rate : new int[] {44100, 32000, 22050, 16000, 11025, 8000}) {
    if (AudioRecord.getMinBufferSize(rate, AudioFormat.CHANNEL_IN_DEFAULT, AudioFormat.ENCODING_PCM_16BIT) > 0) {
        audioSamplingRate = rate;
        break;
    }
}

CAMERA_MEDIA_RECORDER.setAudioSamplingRate(audioSamplingRate);
CAMERA_MEDIA_RECORDER.setVideoEncodingBitRate(700000);

String extension = ".3gpp";

if (camcorderProfile.fileFormat == MediaRecorder.OutputFormat.MPEG_4) {
    extension = ".mp4";
}

File file = new File(Internal.getStoragePath(Internal.CURRENT_ACTIVITY) + "/webcam" + extension);
file.createNewFile();

CAMERA_MEDIA_RECORDER.setOutputFile(file.toString());
CAMERA_MEDIA_RECORDER.setPreviewDisplay(CAMERA_SURFACE_VIEW.getHolder().getSurface());

CAMERA_MEDIA_RECORDER.prepare();
CAMERA_MEDIA_RECORDER.start();

//
// stopping code
//

try {
    CAMERA_MEDIA_RECORDER.stop();
} catch (IllegalStateException e) {
    // do nothing
} catch (RuntimeException e) {
    // do nothing
}

CAMERA_MEDIA_RECORDER.reset();
CAMERA_MEDIA_RECORDER.release();

CAMERA.lock();
CAMERA.stopPreview();
CAMERA.release();

CAMERA_MEDIA_RECORDER = null;
CAMERA = null;
CAMERA_SURFACE_VIEW = null;

编辑:我应该指出,surfaceView是1 x 1 px并且在屏幕边界之外。我不希望显示预览。

如何确保所有带前置摄像头的设备上的录像效果都很好?

2 个答案:

答案 0 :(得分:1)

&#34;接受&#34;答案只是一种解决方法,并没有解决问题,因为当你发布预览并开始录制时,缩放或方面会发生变化,因为mediarecorder会将预览曲面调整到它实际需要的位置,因此镜头的框架将会当你达到不合需要的记录时改变。正确的做法是将预览大小设置为与录制大小的宽高比​​一致,以便mediarecorder获得预期的表面。

检查Android相机应用程序,它不会停止预览,然后开始录制(你可以通过保持闪光灯开启来检查这一点,如果你开始录制闪光灯没有关闭然后再打开,这将是会发生什么,如果你在录制之前释放表面 - 你可以在你自己的应用程序中测试它。

最好的方法是查看Google如何使用内置的Android相机应用程序。查看util.java类中的getOptimalPreviewSize()方法。

https://android.googlesource.com/platform/packages/apps/Camera.git/+/master/src/com/android/camera/Util.java

答案 1 :(得分:0)

我终于能够使用三星Galaxy S3设备并进行一些测试了。问题是由以下几行引起的:

CAMERA.setPreviewDisplay(CAMERA_SURFACE_VIEW.getHolder());
CAMERA.startPreview();

我在StackOverflow上找到的以下答案让我得到了解决方案:https://stackoverflow.com/a/14319270/379245

如果在SurfaceViewCamera之间共享MediaRecorder预览,则显然会导致问题,例如我遇到的问题。从Camera对象中删除预览显示的设置最终解决了问题。