
本文将介绍如何使用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离线录制视频的全部内容,如果你有任何反馈,请随时在本页面下方留言。