使用与生成的视频文件不同的预览大小录制视频

Posted

技术标签:

【中文标题】使用与生成的视频文件不同的预览大小录制视频【英文标题】:Record video with a different preview size than the resulting video file 【发布时间】:2012-12-17 10:34:14 【问题描述】:

我正在尝试允许用户录制与他们在录制时可以看到的实际屏幕预览大小不同的视频。 this documentation concerning the getSupportedVideoSizes function 似乎可以做到这一点:

如果返回的列表不为 null,则返回的列表将包含 at 返回列表中的至少一种尺寸和其中一种尺寸必须是 传递给摄像机应用程序的 MediaRecorder.setVideoSize() 如果 摄像机用作视频源。 在这种情况下, 预览可能与录制视频的分辨率不同 在视频录制期间。

这表明某些手机会从此 fn 返回 null(根据我的经验 Galaxy SIII 会),但对于那些不这样做的人,可以提供与实际视频不同分辨率的预览。这种理解正确吗?有些手机允许这种行为,有些则不允许吗?

尝试解决方案:

在lengthy process of setting up for video recording中使用的official description of the setPreviewDisplay函数中提到:

如果调用此方法时使用 null 表面或根本不调用,媒体 记录器不会改变相机的预览表面。

这似乎是我想要的,但不幸的是,如果我这样做,整个视频录制过程就会完全混乱。我假设这个函数在录制视频的过程中不能传递 null 或根本不调用。也许在其他情况下这是可以的。不幸的是,这似乎对我没有帮助。

我接下来的唯一步骤是查看TextureViews 并使用预览纹理而不是典型的 SurfaceView 实现,以便使用 openGL 将纹理拉伸到与实际分辨率不同的我想要的大小(并裁剪任何超出屏幕的部分),然后使用 Surface 的 Surface(SurfaceTexture surfaceTexture) 构造函数为 setPreviewDisplay 函数构造一个 Surface。我想避免使用TextureView,因为在 ICS 下不兼容,而且这增加了很大的复杂性。

这似乎是一个微妙的过程,但我希望有人能在这方面提供一些建议。

谢谢。

【问题讨论】:

你能解释一下“完全搞砸”是什么意思吗? 如果我没记错的话,这意味着预览表面变黑了,没有任何记录。 【参考方案1】:

a.假设用户将x,y的大小设置为视频大小

b.现在使用 getSupportedVideoSizes 函数获取整个列表并查看 x,y 是否属于其中之一并设置 MediaRecorder.setVideoSize()。如果 x,y 不属于 getSupportedVideoSizes 列表,则设置默认配置文件用于视频记录。

这是关于视频大小

现在是预览大小,没有太多的解决方法选项。 获取一个保存 SurfaceView 的 RelativeLayout。

<android.view.SurfaceView xmlns:android="http://schemas.android.com/apk/res/android"
 android:id="@+id/preview"
 android:layout_
 android:layout_
 />

preview 是 SurfaceView 的名称。 在这里,我给出了一个将其重新调整为宽度和高度一半的示例。

resetCamera();  //reset the camera   

ViewGroup.LayoutParams params = preview.getLayoutParams();
RelativeLayout myRelLayout = (RelativeLayout) findViewById(R.id.myRelLayout);
params.width = (int) (myRelLayout.getWidth()/2);
params.height = (int)(myRelLayout.getHeight()/2);
preview.setLayoutParams(params);

initCamera(); //initiate the camera(open camera, set parameter, setPreviewDisplay,startPreview)

请查看预览的分辨率,然后根据视频大小相应缩小高度或宽度。

希望对你有帮助。

【讨论】:

【参考方案2】:

正如你提到的,这只有在 getSupportedVideoSizes() 返回非空列表时才有可能。

但是如果你确实看到了一个非空列表,那么这个简单的方法应该可以工作:

    用setPreviewSize设置所需的预览分辨率;您选择的尺寸必须是getSupportedPreviewSizes 给出的尺寸之一。

    分别使用setPreviewDisplay 或setPreviewTexture 将预览显示设置为SurfaceView 或SurfaceTexture。

    开始预览。

    创建媒体记录器,并使用setVideoSize 直接使用getSupportedVideoSizes 中的一种尺寸设置其视频大小,或使用预定义的Camcorder profiles 之一来配置所有媒体记录器设置给定质量/尺寸。

    将摄像头对象传递给 MediaRecorder 的 setCamera 调用,配置媒体记录器的其余部分,然后开始录制。

在具有非空 getSupportedVideoSizes 列表的设备上,这应该会导致预览保持在 setPreviewSize 调用设置的分辨率,并以设置的视频大小/摄像机配置文件分辨率进行录制。在不支持视频大小的设备上,MediaRecorder 将重置预览大小以匹配录制大小。您应该能够通过设置非常低的预览分辨率和高录制分辨率(例如,160x120 用于预览,720p 用于录制)来测试这一点。如果 MediaRecorder 在录制开始时将预览分辨率切换为 720p,应该很明显,因为预览质量会大幅提升。

注意预览大小不直接与显示SurfaceView的尺寸挂钩;相机预览的输出将被缩放以适应 SurfaceView,因此如果您的 SurfaceView 的尺寸由于您的布局和设备而为 100x100 像素,则无论您使用的预览分辨率如何,都将缩放为 100x100 以进行显示。所以你仍然需要确保保持 SurfaceView 的纵横比正确,这样预览才不会失真。

为了节能,您不应使用远高于 SurfaceView 中实际像素数的预览分辨率,因为在将预览拟合到 SurfaceView 时会丢失额外的分辨率。这当然只有在 getSupportedVideoSizes() 返回非空值时才有可能进行录制。

【讨论】:

我会尽快尝试这个,但我目前正在进行大量代码大修,不想搞砸太多东西。这看起来很有希望(尽管如果 getSupportedVideoSizes 像通常看起来那样为空,则令人沮丧。【参考方案3】:

首先,我将尝试回答您的具体问题。

    可以提供与实际视频不同分辨率的预览。这种理解正确吗?

是的,预览大小通常与录制大小不同。预览尺寸通常与您的显示尺寸无关。因此,如果手机显示 CIF (352 x 288),但能够录制 D1 (720 x 480),则预览大小和录制大小会有所不同。我觉得其他专家在这一点上已经给出了充分的回答。

    有些手机允许这种行为,有些则不允许吗?

大多数最新款手机都支持此功能,可能只有少数低端手机。

除了setPreviewDisplay,我们还要考虑这一点:

一个例外是,如果在调用 startPreview() 之前未设置预览表面(或设置为 null),则可以使用非 null 参数调用该方法一次以设置预览表面。 (这允许相机设置和表面创建并行进行,从而节省时间。)预览表面可能不会在预览运行时更改。

您能否分享一下使用NULL 表面调用setPreviewDisplay 时遇到的问题?

【讨论】:

以上是关于使用与生成的视频文件不同的预览大小录制视频的主要内容,如果未能解决你的问题,请参考以下文章

确保相机预览大小/纵横比与生成的视频相匹配

Android 使用CameraX实现预览/拍照/录制视频/图片分析/对焦/缩放/切换摄像头等操作

DELMIA教程:仿真视频录制功能介绍与使用方法

在 iOS 中录制视频时播放音频文件

Android相机 - 录制视频时预览放大

Screen2EXE录屏|录制视频