5

我有一个 MediaRecorder 录制视频,我对setCaptureRate()的效果感到非常困惑。

具体来说,我准备我的 MediaRecorder 如下:

mMediaRecorder = new MediaRecorder();
mCamera.stopPreview();
mCamera.unlock();
mMediaRecorder.setCamera(mCamera);
mMediaRecorder.setVideoSource(MediaRecorder.VideoSource.CAMERA);
mMediaRecorder.setProfile(CamcorderProfile.QUALITY_TIME_LAPSE_480P);
mMediaRecorder.setCaptureRate(30f);
mMediaRecorder.setOrientationHint(270);
mMediaRecorder.setOutputFile(...);
mMediaRecorder.setPreviewDisplay(...);
mMediaRecorder.prepare();

我记录了五秒钟(使用 CountDownTimer,但这无关紧要),这是生成的文件:

$ ffmpeg -i ~/CaptureRate30fps.mp4 
...
Seems stream 0 codec frame rate differs from container frame rate: 180000.00 (180000/1) -> 30.00 (30/1)
Input #0, mov,mp4,m4a,3gp,3g2,mj2, from '/home/mspitz/CaptureRate30fps.mp4':
  Metadata:
    major_brand     : isom
    minor_version   : 0
    compatible_brands: isom3gp4
    creation_time   : 2013-06-04 00:52:00
  Duration: 00:00:02.59, start: 0.000000, bitrate: 5238 kb/s
    Stream #0.0(eng): Video: h264 (Baseline), yuv420p, 720x480, 5235 kb/s, PAR 65536:65536 DAR 3:2, 30 fps, 30 tbr, 90k tbn, 180k tbc
    Metadata:
      creation_time   : 2013-06-04 00:52:00

请注意,持续时间约为 3 秒。视频的播放速度也快了很多,仿佛将 5 秒的视频塞进了 3 秒。

现在,如果我通过完全按照上面的方式准备 mediaRecorder 进行录制,但减去 setCaptureRate(30f) 行,我会得到一个像这样的文件:

$ ffmpeg -i ~/NoSetCaptureRate.mp4 
...
Seems stream 0 codec frame rate differs from container frame rate: 180000.00 (180000/1) -> 90000.00 (180000/2)
Input #0, mov,mp4,m4a,3gp,3g2,mj2, from '/home/mspitz/NoSetCaptureRate.mp4':
  Metadata:
    major_brand     : isom
    minor_version   : 0
    compatible_brands: isom3gp4
    creation_time   : 2013-06-04 00:50:41
  Duration: 00:00:04.87, start: 0.000000, bitrate: 2803 kb/s
    Stream #0.0(eng): Video: h264 (Baseline), yuv420p, 720x480, 2801 kb/s, PAR 65536:65536 DAR 3:2, 16.01 fps, 90k tbr, 90k tbn, 180k tbc
    Metadata:
      creation_time   : 2013-06-04 00:50:41

请注意,持续时间与预期的一样,约为 5 秒。视频也以正常速度播放。

我使用 setCaptureRate(30f) 因为每秒 30 帧是我的 CamcorderProfile 的videoFrameRate的值。在我的 Galaxy Nexus S2 (4.2.1) 上,省略 setCaptureRate() 很好,但是当我在 Galaxy Nexus S3 (4.1.1) 上测试时,省略 setCaptureRate() 会导致非常有用的“启动失败 -22”错误当我打电话时mMediaRecorder.start()

那么,我错过了什么?我认为捕获率和视频帧率是独立的,但很明显它们不是。有没有办法以编程方式确定我需要设置什么捕获速率才能确定我的视频以 1 倍速度播放?

4

3 回答 3

2

(这是对原始问题的评论的决议摘要)

问题可能是直接使用QUALITY_TIME_LAPSE_480P配置文件会影响播放速率,因为时间流逝隐含地不是 1x 播放速率。

此外,如果您使用该配置文件的原因是防止在使用QUALITY_480P时录制音频(因为时间流逝不录制音频),您可能希望根据配置文件手动调用CamcorderProfile.get(QUALITY_480P)并设置视频参数,而不直接MediaRecorder打电话MediaRecorder.setProfile。没有设置任何音频参数的AMediaRecorder理论上不应该录制任何音频。

于 2013-06-12T03:41:49.970 回答
0

你是对的。我会给你正确的答案。我也遇到过同样的情况。启动失败-22 属于帧速率。因此你给出的捕获率不在设备范围内。首先使用 getSupportedPreviewFpsRange() 确定设备 fps 范围,然后进行相应设置。您可以使用 PREVIEW_FPS_MAX_INDEX 和 PREVIEW_FPS_MIN_INDEX 获得最大和最小 fFps。

使用下面的代码,它会给出乘以 1000 的结果,即如果帧速率为 5,它将返回 5000。

Camera.Parameters camParameter = camera.getParameters();
    List<int[]> frame = camParameter.getSupportedPreviewFpsRange();
        Iterator<int[]> supportedPreviewFpsIterator = frame.iterator();
        while (supportedPreviewFpsIterator.hasNext()) {
            int[] tmpRate = supportedPreviewFpsIterator.next();
            StringBuffer sb = new StringBuffer();
            sb.append("supportedPreviewRate: ");
            for (int i = tmpRate.length, j = 0; j < i; j++) {
                sb.append(tmpRate[j] + ", ");
            }
            Log.d(VTAG, sb.toString());
        }
    }

更多检查在这里:http: //developer.android.com/reference/android/hardware/Camera.Parameters.html#getSupportedPreviewFpsRange()

编辑: 在 android 开发者文档中。提到 setCaptureRate() 设置视频帧捕获率。这可用于设置与录制视频的播放速率不同的视频帧捕获速率。此方法还将录制模式设置为延时。由于它还将录制模式设置为延时,因此在将 setprofile QUALITY_TIME_LAPSE_480P 删除为任何其他受支持的正常配置文件(如 QUALITY_480P)后检查视频,或通过设置视频大小等进行纯自定义 mediaRecorder 设置。它可能会对您有所帮助。

于 2013-06-10T13:03:42.203 回答
0

根据文档,setCaptureRate(double fps)用于设置延时录制,忽略音频。如果您想要的 fps 比系统实际提供的少,这是最有用的。您要求的 fps 比系统所能提供的多,这里是developer.android.com/reference的引述:

请注意,由于相机/编码器的限制,录像机不能保证以给定的速率捕获帧。然而,它试图尽可能接近。

您的代码没有调用的是setVideoFrameRate(int rate). 我相信使用此功能,您的录音将得到修复。

于 2013-06-04T08:45:39.580 回答