本文介绍如何在集成Unity的iOS原生项目中截取和录制屏幕

完整代码请查看Record_Screen_In_Unity

由于Unity不熟练,不知道怎么直接在Unity里录制屏幕。查询网上的方法,基本都是采用Unity的插件录制,不过基本都是收费插件,所以我们采用曲线救国,自己制作录制脚本。

思路是首先在Unity里获取当前屏幕截图,传给native,原生使用GPUImage进行视频的合成

1. 准备工作

新建一个Unity和原生混合的工程(参考之前的文章),在主场景中放置一个白色的球,方便我们录制时验证

2. Unity端

  • 获取AR摄像头采集的原始数据

使用ARCameraManagerTryGetLatestImage方法获取XRCameraImage对象,再用XRCameraImageConversionParams把数据转成需要的格式

cameraManager.TryGetLatestImage(out XRCameraImage image)

renderTexture = new Texture2D(image.width, image.height, TextureFormat.BGRA32, false);
conversionParams = new XRCameraImageConversionParams(image, TextureFormat.BGRA32, CameraImageTransformation.None);
intPtr = new IntPtr(renderTexture.GetRawTextureData<byte>().GetUnsafePtr());

var rawTextureData = renderTexture.GetRawTextureData<byte>();
try
{
    image.Convert(conversionParams, intPtr, rawTextureData.Length);
}
finally
{
    image.Dispose();
}

renderTexture.Apply();

NativeAPI.SendVideoData(renderTexture.GetRawTextureData(), rawTextureData.Length);
  • 获取屏幕渲染结果

使用Texture2DReadPixels获取屏幕渲染结果

renderTexture.ReadPixels(new Rect(0, 0, Screen.width, Screen.height), 0, 0);
renderTexture.Apply();

byte[] rawData = renderTexture.GetRawTextureData();
NativeAPI.SendVideoData(rawData, rawData.Length);

3. Native端

使用GPUImageRawDataInput作为输入,GPUImageMovieWriter作为输出
摄像头数据是旋转的,添加GPUImageTransformFilter旋转回来
如果不是录制全屏,添加GPUImageCropFilter截取屏幕的某一部分

注意: 初始化GPUImageMovieWriter注意宽高需要是16的倍数,否则会有黑边

4. 音频录制

通过OnAudioFilterRead(float[] data, int channels)采集unity的声音传给Native端,在Native端将音频数据转为CMSampleBuffer塞入GPUImage

Unity设置的音频采样率要和Native端统一

AudioSettings.outputSampleRate = 44100;

注意: OnAudioFilterRead方法只有在添加了AudioSource组件后才会回调,并且AudioSource的playOnAwake需要为false

完整代码请查看Record_Screen_In_Unity