ue3dUnity使用NatCorder离线录制视频

Unity使用NatCorder离线录制视频

分类:
ue3d - Unity使用NatCorder离线录制视频

本文将介绍如何使用Unity资产NatCorder离线录制视频。

NatCorder是什么?

NatCorder是一种资产,用于在Unity中创建mp4等视频文件,如果你未安装,请先可从站内下载

基本的用法总结在站内文章中,有需要的可以参考一下:使用NatCorder创建视频文件

仅离线录制视频

上面的文章总结了如何离线只录制视频,代码片段如下所示

using System.Linq;
using NatSuite.Recorders;
using NatSuite.Recorders.Clocks;
using UnityEngine;
using System.Threading.Tasks;

public class Example : MonoBehaviour
{
    public async void Start()
    {
        const int width = 128;
        const int height = 128;
        const int frameRate = 30;
        
        var clock = new FixedIntervalClock(frameRate);
        var recorder = new MP4Recorder(width, height, frameRate);
        
        var colors = Enumerable.Range(0, width * height)
            .Select(_ => (Color32) Color.magenta)
            .ToArray();
        var frames = Enumerable.Range(0, 100)
            .Select(x =>
            {
                var texture = new Texture2D(width, height, TextureFormat.RGBA32, false, false);
                texture.SetPixels32(colors);
                return texture.GetPixels32();
            })
            .ToArray();

        var path = await Task.Run(() =>
        {
            foreach (var frame in frames)
            {
                recorder.CommitFrame(frame, clock.timestamp);
            }
            return recorder.FinishWriting();
        });
        Debug.Log(path);
    }
}

仅离线录制音频

接下来,将展示如何仅离线录制音频,下面以WAVRecorder录制音频的源码为例。

using System.Linq;
using NatSuite.Recorders;
using UnityEngine;

public class Example : MonoBehaviour
{
    [SerializeField] private AudioClip _clip;

    private WAVRecorder _recorder;
    
    private void Start()
    {
        // 使用 AudioClip 频率和通道数初始化 WAVRecorder
        _recorder = new WAVRecorder(_clip.frequency, _clip.channels);
        
        // 从 AudioClip 获取数据
        var samples = new float[_clip.samples * _clip.channels];
        _clip.GetData(samples, 0);
        
        // 将所有数据提交到记录器
        var samplesList = samples.ToList();
        while (true)
        {
            // 提交每个适当的数字
            var count = Mathf.Min(samplesList.Count, 10000);
            var d = samplesList.GetRange(0, count).ToArray();
            samplesList.RemoveRange(0, count);
            
            _recorder.CommitSamples(d);
            
            if (samplesList.Count == 0)
            {
                break;
            }
        }
    }

    private void OnDestroy()
    {
        Debug.Log(_recorder.FinishWriting().Result);
    }
}

使用WAVRecorder时,频率和通道已注册到WAVRecorder构造函数,因此所要做的就是适当地提交AudioClip数据。 由于内部规范,如果一次提交可能效果不佳,但将其分成两次左右可能效果更好。

离线录制视频和音频

最后总结一下如何离线同时录制视频和音频。

首先,作为准备,创建一个可以以帧为单位获取AudioClip数据的类,然后实际使用它进行录音。

创建一个可以以帧为单位获取AudioClip数据的类

首先,让创建一个可以以帧为单位获取AudioClip数据的类。

using System;
using UnityEngine;

public class AudioClipData
{
    private readonly AudioClip _clip;
    
    private float[] _samples;
    private float[] Samples => _samples ?? (_samples = FetchSamples(_clip));

    public AudioClipData(AudioClip clip)
    {
        _clip = clip;
    }

    /// <summary>
    /// 获取数据
    /// </summary>
    /// <param name="startFrame">开始获取的框架</param>
    /// <param name="frameCount">帧数</param>
    /// <param name="fps">FPS</param>
    /// <returns></returns>
    public float[] Get(int startFrame, int frameCount, int fps)
    {
        var samplesPerFrame = _clip.frequency / fps * _clip.channels;
        return Get(samplesPerFrame * startFrame, samplesPerFrame * frameCount);
    }
        
    private float[] Get(int startIndex, int length)
    {
        var result = new float[length];
        if (Samples.Length - startIndex < length)
        {
            length = Samples.Length - startIndex;
        }

        if (length >= 0)
        {
            Array.Copy(Samples, startIndex, result, 0, length);
        }

        return result;
    }

    private static float[] FetchSamples(AudioClip clip)
    {
        var samples = new float[clip.samples * clip.channels];
        clip.GetData(samples, 0);
        return samples;
    }
}

阅读这段代码需要先了解音频数据的结构,可以参考站内文章:通过直接编辑AudioClip学习声音数据的结构

具体是从FPS中获取AudioClip的频率和声道数,以及每帧的样本数,AudioClip.GetData()这样就可以通过指定frame来获取in中的数据。

离线记录

接下来使用这个类来实际进行离线录制。

using System.Linq;
using NatSuite.Recorders;
using NatSuite.Recorders.Clocks;
using UnityEngine;

public class Example : MonoBehaviour
{
    [SerializeField] private AudioClip _clip;
    private IMediaRecorder _recorder;
    
    public void Start()
    {
        const int width = 128;
        const int height = 128;
        const int frameRate = 30;
        var sampleRate = AudioSettings.outputSampleRate;
        var channelCount = (int)AudioSettings.speakerMode;
        
        // 使用 FrameRate 生成 FixedIntervalClock
        var clock = new FixedIntervalClock(frameRate);

        // 生成记录器
        // 这里的 sampleRate 和 channelCount 使用 AudioSettings 中的那些
        _recorder = new MP4Recorder(width, height, frameRate, sampleRate, channelCount);
        
        // 为每一帧准备一组纹理
        var colors = Enumerable.Range(0, width * height)
            .Select(_ => (Color32) Color.magenta)
            .ToArray();
        
        var frames = Enumerable.Range(0, 100)
            .Select(x =>
            {
                var texture = new Texture2D(width, height, TextureFormat.RGBA32, false, false);
                texture.SetPixels32(colors);
                // 此时调用 GetPixels32()
                return texture.GetPixels32();
            })
            .ToArray();

        var audioClipData = new AudioClipData(_clip);

        var currentFrame = 0;
        foreach (var frame in frames)
        {
            var timestamp = clock.timestamp;
            _recorder.CommitFrame(frame, timestamp);
            var data = audioClipData.Get(currentFrame, 1, frameRate);
            _recorder.CommitSamples(data, timestamp);
            currentFrame++;
        }
    }

    private void OnDestroy()
    {
        Debug.Log(_recorder.FinishWriting().Result);
    }
}

请注意,与WAVRecorder不同,除非使用AudioSettings,否则MP4Recorder的参数采样率不起作用,导致Unity崩溃。

以上是关于如何使用Unity资产NatCorder离线录制视频的全部内容,如果你有任何反馈,请随时在本页面下方留言。

相关信息

  • 类型:知识
  • 字数:548
  • 字符:7126
  • 适用软件:Unity
  • 说明:无
  • 编号:163897

热门内容

提示:3D天堂作为服务提供者,尊重网络版权及知识产权,对某些行为的发生不具备充分的监控能力,若无意间侵犯到您的权利,请 联系我们,我们会在收到信息后尽快给予处理。

本站文章版权归本站自创作者所有,未经允许不得转载!