4

我正在将照片/视频捕获集成到我的应用中,并且遇到了视频捕获问题。无论何时录像开始,屏幕闪烁,我会暂停一段时间,然后开始录像。但是,使用手机的相机应用程序,根本没有闪烁/暂停。开始录制视频时屏幕闪烁并调整大小

而且,我的相机预览显示会在调用recorder.start()后立即调整大小。我不明白这是为什么。它会使预览失真(一切看起来都会变得更加宽广)。

我的问题:如何防止开始录像时的闪烁/暂停?如何防止recorder.start()调整我的预览显示?

每当启用“视频模式”时,立即调用initRecording()。一旦用户按下按钮,startRecording()被调用。最后,当再次按下按钮时,调用stopRecording()。不太重要的是,当切换回“图片模式”时,destroyRecorder()被调用。

@Override 
public void onResume() { 

    super.onResume(); 

    Camera camera = null; 
    try { 
     camera = Camera.open(); 
    } 
    catch (Exception e) { 
     // Camera isn't available 
     Toast.makeText(getActivity(), "Camera is not available at this time.", Toast.LENGTH_SHORT).show(); 
     getActivity().finish(); 
     return; 
    } 

    if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.GINGERBREAD) { 
     setCameraDisplayOrientation(camera); 
    } 
    else { 
     camera.setDisplayOrientation(90); 
    } 

    setCamera(camera); 
    setCameraZoomDisplay(camera); 

    if (getSurfaceHolder() != null) { 
     startPreview(); 

     if (getMode() == MODE_VIDEO) { 
      initRecording(); 
     } 
    } 
} 

private void setCameraDisplayOrientation(Camera camera) { 

    CameraInfo info = new CameraInfo(); 
    Camera.getCameraInfo(0, info); 

    int rotation = getActivity().getWindowManager().getDefaultDisplay().getRotation(); 
    int degrees = 0; 
    switch (rotation) { 
     case Surface.ROTATION_0: 
      degrees = 0; 
      break; 
     case Surface.ROTATION_90: 
      degrees = 90; 
      break; 
     case Surface.ROTATION_180: 
      degrees = 180; 
      break; 
     case Surface.ROTATION_270: 
      degrees = 270; 
      break; 
    } 

    int result = (info.orientation - degrees + 360) % 360; 
    camera.setDisplayOrientation(result); 
} 

private void initRecording() { 

    MediaRecorder recorder = new MediaRecorder(); 
    setRecorder(recorder); 

    Camera camera = getCamera(); 
    camera.unlock(); 
    recorder.setCamera(camera); 

    recorder.setAudioSource(MediaRecorder.AudioSource.MIC); 
    recorder.setVideoSource(MediaRecorder.VideoSource.CAMERA); 

    CamcorderProfile cp = CamcorderProfile.get(CamcorderProfile.QUALITY_HIGH); 
    recorder.setProfile(cp); 

    String extension; 
    switch (cp.fileFormat) { 
     case MediaRecorder.OutputFormat.MPEG_4: 
      extension = "mp4"; 
      break; 
     case MediaRecorder.OutputFormat.THREE_GPP: 
      extension = "3gp"; 
      break; 
     default: 
      extension = "tmp"; 
    } 

    setVideoMimeType(MimeTypeMap.getSingleton().getMimeTypeFromExtension(extension)); 

    File toFile = new File(getActivity().getCacheDir(), "tempvideo.tmp"); 
    if (toFile.exists()) { 
     toFile.delete(); 
    } 
    setTempFile(toFile); 

    recorder.setOutputFile(toFile.getPath()); 
    recorder.setPreviewDisplay(getSurfaceHolder().getSurface()); 

    try { 
     recorder.prepare(); 
     setRecorderInitialized(true); 
    } 
    catch (IllegalStateException e) { 
     e.printStackTrace(); 
    } 
    catch (IOException e) { 
     e.printStackTrace(); 
    } 
} 

private boolean startRecording() { 

    try { 
     getRecorder().start(); 
     setRecording(true); 

     ImageView actionImageView = getActionImageView(); 
     actionImageView.setImageResource(R.drawable.record_red); 
    } 
    catch (Exception e) { 
     getCamera().lock(); 
    } 

    return true; 
} 

private void stopRecording() { 

    MediaRecorder recorder = getRecorder(); 
    if (recorder != null && isRecording()) { 
     recorder.stop(); 
     setRecording(false); 
     setRecorderInitialized(false); 

     try { 
      insertVideo(); 
     } 
     catch (IOException e) { 
      e.printStackTrace(); 
     } 

     initRecording(); 

     ImageView actionImageView = getActionImageView(); 
     actionImageView.setImageResource(R.drawable.record_green); 
    } 
} 

private void destroyRecorder() { 

    MediaRecorder recorder = getRecorder(); 
    recorder.release(); 
    setRecorder(null); 
    getCamera().lock(); 
} 
+0

你有没有想过是什么导致闪烁和调整大小?我正在处理与我正在进行的项目相同的问题。 – MattDavis

+0

@MattDavis抱歉,遗憾的是没有。 –

回答

7

原因时MediaRecorder.start()被调用略有放大是由于相机调整其大小,预览匹配的正在录制的视频分辨率。通过设置预览和视频解析可以解决此问题。我想我也找到了一种方法来阻止闪烁,尽管我发现在使用Camera和MediaRecorder时,一些滞后或闪烁可能来自任何地方,这可能是有点难以追查。 The Android documentation for setting up a camera/video recorder是开始确保主要部分设置正确的好地方,但我发现有必要深入研究一些api类文档以进行调试并使体验真正流畅。

Camera.Parameters班是保持流畅录像体验的关键。一旦你有一个Camera对象,你可以使用Camera.getParameters()来获取当前参数来修改它们。然后可以使用Camera.setParameters(Camera.Parameters)来触发已经做出的任何更改。

为防止视频调整大小,我们需要确保参数的预览大小与要录制的视频分辨率一致。要获得支持的视频/预览尺寸列表,我们可以在我们当前的参数对象上使用Camera.Parameters.getSupportedPreviewSizes(),它将返回一个Camera.Size对象列表。这些对象中的每一个都具有宽度和高度属性,可通过Camera.Size.widthCamera.Size.height直接访问(无getter方法)。 getSupportedPreviewSizes()方法是guaranteed to return at least one result,,好像结果是从最高分辨率到最低分。

(对于API级别> 11还有一个getSupportedVideoSizes()方法,但它似乎只有在设备的某些视频尺寸与预览尺寸不同时才会显示,否则返回null。这个方法,所以我会坚持使用PreviewSizes,因为它可以保证返回一个大小适合视频和预览,但它是要知道前进的东西。)

一旦我们有Camera.Size对应于视频分辨率,我们可以使用Camera.Parameters.setPreviewSize(width, height).设置此大小此外,为了帮助闪烁,我使用了Camera.Parameters.setFocusMode(Camera.Parameters.FOCUS_MODE_CONTINUOUS_VIDEO).采取了一个这些步骤,使用Camera.setParameters()来通知摄像机您的更改。我已经成功地在获取相机后设置这些参数,因为在用户与此Activity进行交互时设置参数导致了一些滞后。如果您使用相同的活动进行视频和图片捕获,您也可以在此处设置图片参数,Camera对象将使用适合每个模式的参数进行处理。

几乎完成!现在预览已经完成,剩下的就是确保MediaRecorder使用与预览相同的分辨率。在准备媒体记录器时,在拨打MediaRecorder.setProfile()(或设置编码器,API级别< 8)和MediaRecorder.setOutputFile()之间,请拨打MediaRecorder.setVideoSize(width, height),使用与预览相同的值。现在,使用MediaRecorder.start()从预览到记录的转换应该是无缝的,因为它们都使用相同的分辨率。

我这里还有一些简单的代码片段,所以你可以看到在行动的一切:

获取和设置PARAMS:

Camera.Parameters params = camera.getParameters(); 

params.setFocusMode(Camera.Parameters.FOCUS_MODE_CONTINUOUS_VIDEO); 

//myVideoSize is an instance of Camera.Size 
List<Camera.Size> previewSizes = params.getSupportedPreviewSizes(); 
myVideoSize = previewSizes.get(0); 
params.setPreviewSize(myVideoSize.width, myVideoSize.height); 

camera.setParameters(params); 

然后设置在媒体记录尺寸:

//After setting the profile.... 
mediaRecorder.setProfile(CamcorderProfile.get(CamcorderProfile.QUALITY_HIGH)); 

//Use myVideoSize from above 
mediaRecorder.setVideoSize(myVideoSize.width, myVideoSize.height); 

//Before setting the output file 
mediaRecorder.setOutputFile(myFile); 
+1

伟大的职位,感谢您解释整个过程。我遵循这些步骤,但我仍然得到预览和闪烁的大小调整。我将相机预览尺寸和“MediaRecorder”的视频尺寸设置为相同的值(640x480)。 – Cat

+0

当我使用这条线。 mediaRecorder.setVideoSize(myVideoSize.width,myVideoSize.height);视频不在android中录制。 – Shankar