Unity NatCorder
前言
一、NatCorder
Unity全平台录屏工具,工具的具体内容在其他博客里都能找到,但找了很多博客内容都差不多,用的时候还要自己去看一下源码,官方的demo在笔记本上都会录制摄像头看到的画面,很不任性,
二、使用步骤
1.引入库
我使用的是NatCorder1.5.1,unity2019版本.在官方三个demo场景Replaycam里面修改来的.最后的效果.添加了一个开始时录屏和结束录屏的按钮,一个录制时长的Text.
2.Ui
如果用到录制摄像头的功能,可以吧里面的预制UI隐藏掉或者删掉,同时添加一个开始和结束录屏的Button和显示录屏时长的Text,
录制视屏的脚本都在ReplayCam上面挂着,最后通过调用它上面的ReplayCam脚本里面的方法,录制.
3.ReplayCam官方脚本
官方脚本,大体上没动过,添加了一些自己理解的注释,和一个
internal Action replayAction;的委托方法,等会要在其他地方赋值,测试时发现录制完成后还要等点时长,可能是转码保存,如果不得他调用完录制完成方法就退出,视屏无法正常播放.
/*
* NatCorder
* Copyright (c) 2019 Yusuf Olokoba
*/
namespace NatCorder.Examples
{
#if UNITY_EDITOR
using UnityEditor;
#endif
using UnityEngine;
using UnityEngine.UI;
using System.Collections;
using Clocks;
using Inputs;
using System;
public class ReplayCam : MonoBehaviour
{
/**
* ReplayCam Example
* -----------------
* This example records the screen using a `CameraRecorder`.
* When we want mic audio, we play the mic to an AudioSource and record the audio source using an `AudioRecorder`
* -----------------
* Note that UI canvases in Overlay mode cannot be recorded, so we use a different mode (this is a Unity issue)
*/
[Header("Recording")]
public int videoWidth = 1280;
public int videoHeight = 720;
[Header("Microphone")]
public bool recordMicrophone;
public AudioSource microphoneSource;
private MP4Recorder videoRecorder;
private IClock recordingClock;
private CameraInput cameraInput;
private AudioInput audioInput;
/// <summary>
/// 接収录制完成是的委托方法
/// </summary>
internal Action replayAction;
public void StartRecording()
{
SetWidthAndHight();
// Start recording
recordingClock = new RealtimeClock();
videoRecorder = new MP4Recorder(
videoWidth,
videoHeight,
30,
recordMicrophone ? AudioSettings.outputSampleRate : 0,
recordMicrophone ? (int)AudioSettings.speakerMode : 0,
OnReplay
);
// Camera.main 设置录制那个摄像机的画面
cameraInput = new CameraInput(videoRecorder, recordingClock, Camera.main);
if (recordMicrophone)
{
StartMicrophone();
audioInput = new AudioInput(videoRecorder, recordingClock, microphoneSource, true);
}
}
private void StartMicrophone()
{
#if !UNITY_WEBGL || UNITY_EDITOR // No `Microphone` API on WebGL :(
// Create a microphone clip
microphoneSource.clip = Microphone.Start(null, true, 60, 48000);
while (Microphone.GetPosition(null) <= 0) ;
// Play through audio source
microphoneSource.timeSamples = Microphone.GetPosition(null);
microphoneSource.loop = true;
microphoneSource.Play();
#endif
}
public void StopRecording()
{
// Stop the recording inputs
if (recordMicrophone)
{
StopMicrophone();
audioInput.Dispose();
}
cameraInput.Dispose();
// Stop recording
videoRecorder.Dispose();
}
private void StopMicrophone()
{
#if !UNITY_WEBGL || UNITY_EDITOR
Microphone.End(null);
microphoneSource.Stop();
#endif
}
/// <summary>
/// 视频录制完成时调用,在下面上个平台上播放录制的视屏
/// </summary>
/// <param name="path"></param>
private void OnReplay(string path)
{
replayAction();
Debug.Log("Saved recording to: " + path);
// Playback the video
#if UNITY_EDITOR
EditorUtility.OpenWithDefaultApp(path);
#elif UNITY_IOS
Handheld.PlayFullScreenMovie("file://" + path);
#elif UNITY_ANDROID
Handheld.PlayFullScreenMovie(path);
#endif
}
/// <summary>
/// 设置录制大小
/// </summary>
private void SetWidthAndHight()
{
videoWidth = UnityEngine.Screen.width;
videoHeight = UnityEngine.Screen.height;
}
}
}
4.UiCanvas
挂载在上图Canvas上,主要是通过这个脚本来调用ReplayCam脚本上的方法.完成录屏和一些界面提示,
using NatCorder.Examples;
using UnityEngine;
using UnityEngine.UI;
public class UiCanvas : MonoBehaviour
{
private Text uiText;
private Text btnText;
public ReplayCam cam;
private int timeNum;
private RecordType recordType;
void Awake()
{
uiText = transform.Find("Text").GetComponent<Text>();
btnText = transform.Find("Button/Text").GetComponent<Text>();
}
// Start is called before the first frame update
void Start()
{
transform.Find("Button").GetComponent<Button>().onClick.AddListener(Btn);
cam.replayAction += replayAction;
}
private void OnEnable()
{
recordType = RecordType.Null;
SetRecordType();
}
private void Btn()
{
SetRecordType();
}
void SetRecordType()
{
switch (recordType)
{
case RecordType.Null:
recordType = RecordType.StartRecord;
break;
case RecordType.StartRecord:
StartRectord();
recordType = RecordType.StopRecord;
break;
case RecordType.StopRecord:
StopRectord();
recordType = RecordType.StartRecord;
break;
default:
break;
}
btnText.text = recordType == RecordType.StopRecord ? "停止录屏" : "开始录屏";
}
// Update is called once per frame
void Update()
{
}
/// <summary>
/// 开始录屏,调用ReplayCam.StartRecording()方法
/// </summary>
public void StartRectord()
{
timeNum = 0;
cam.StartRecording();
//定时的方法
TimerManager.instance.DoLoop(1000, SetTimeText);
}
/// <summary>
/// 结束录屏,调用ReplayCam.StopRectord()方法
/// </summary>
public void StopRectord()
{
cam.StopRecording();
TimerManager.instance.RemoveHandler(SetTimeText);
uiText.text = "正在转译编码,缓存视屏";
}
/// <summary>
/// 设置当前录屏时长
/// </summary>
public void SetTimeText()
{
timeNum++;
uiText.text = "录屏时长:" + timeNum.ToString() + "秒";
}
/// <summary>
/// sdk录屏,保存完成后调用这个方法
/// </summary>
private void replayAction()
{
uiText.text = "视屏保存完成,时长:" + timeNum.ToString() + "秒";
}
}
public enum RecordType
{
Null,
StartRecord,
StopRecord
}
5.缓存路径
缓存路径的代码在MP4Recorder脚本那上面,我在Pc上开发,所以修改了子Pc端缓存的路径,在这个方法里也开始设置缓存视屏的名字.
[Doc(@"MP4RecorderCtor")]
public MP4Recorder (int videoWidth, int videoHeight, int videoFramerate, int audioSampleRate, int audioChannelCount, Action<string> recordingCallback, int videoBitrate = (int)(960 * 540 * 11.4f), int videoKeyframeInterval = 3) {
videoWidth = videoWidth >> 1 << 1;
videoHeight = videoHeight >> 1 << 1;
var readbackFormat = TextureFormat.RGBA32;
var recordingDirectory = Application.persistentDataPath;
var recordingFilename = string.Format("recording_{0}.mp4", DateTime.Now.ToString("yyyy_MM_dd_HH_mm_ss_fff"));
switch (Application.platform) {
case RuntimePlatform.OSXEditor:
recordingDirectory = Directory.GetCurrentDirectory();
goto case RuntimePlatform.OSXPlayer;
case RuntimePlatform.OSXPlayer:
readbackFormat = TextureFormat.ARGB32;
goto case RuntimePlatform.IPhonePlayer;
case RuntimePlatform.WebGLPlayer:
case RuntimePlatform.WindowsEditor:
recordingDirectory = Directory.GetCurrentDirectory();
goto case RuntimePlatform.IPhonePlayer;
case RuntimePlatform.WindowsPlayer:
//在Win中视屏缓存路径在包体Exe程序所在目录
recordingDirectory = Directory.GetCurrentDirectory();
goto case RuntimePlatform.IPhonePlayer;
case RuntimePlatform.IPhonePlayer: {
var recordingPath = Path.Combine(recordingDirectory, recordingFilename);
Debug.Log("下载路径:"+ recordingPath);
var nativeRecorder = MediaRecorderBridge.CreateMP4Recorder(videoWidth, videoHeight, videoFramerate, videoBitrate, videoKeyframeInterval, audioSampleRate, audioChannelCount);
this.internalRecorder = new MediaRecorderiOS(nativeRecorder, videoWidth, videoHeight, readbackFormat, recordingPath, recordingCallback);
break;
}
case RuntimePlatform.Android: {
var recordingPath = Path.Combine(recordingDirectory, recordingFilename);
var nativeRecorder = new AndroidJavaObject(@"com.yusufolokoba.natcorder.MP4Recorder", videoWidth, videoHeight, videoFramerate, videoBitrate, videoKeyframeInterval, audioSampleRate, audioChannelCount);
this.internalRecorder = new MediaRecorderAndroid(nativeRecorder, videoWidth, videoHeight, recordingPath, recordingCallback);
break;
}
default:
Debug.LogError("NatCorder Error: MP4Recorder is not supported on this platform");
this.internalRecorder = null; // Self-destruct >:D
break;
}
}
总结
记录NatCorder在Pc端录制视屏的简单demo.
基于natcorder1.5.1版本写的,
找我拿也行,下载也行,下面的下在连接是1.7版本的
csdn下在地址
Gitee地址