录屏
This commit is contained in:
231
Assets/Script/Recorder/XrealMixedRecorder.cs
Normal file
231
Assets/Script/Recorder/XrealMixedRecorder.cs
Normal file
@@ -0,0 +1,231 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.IO;
|
||||
using System.Linq;
|
||||
using Cysharp.Threading.Tasks;
|
||||
using RenderStreaming;
|
||||
using Stary.Evo;
|
||||
using UnityEngine;
|
||||
using Unity.XR.XREAL;
|
||||
using CameraType = Unity.XR.XREAL.CameraType;
|
||||
#if UNITY_ANDROID && !UNITY_EDITOR
|
||||
using GalleryDataProvider = NativeGalleryDataProvider;
|
||||
#else
|
||||
using GalleryDataProvider = Unity.XR.XREAL.MockGalleryDataProvider;
|
||||
#endif
|
||||
|
||||
public class XrealMixedRecorder : IVideoRecorder, IController
|
||||
{
|
||||
public enum ResolutionLevel
|
||||
{
|
||||
High,
|
||||
Middle,
|
||||
Low
|
||||
}
|
||||
|
||||
public ResolutionLevel resolutionLevel = ResolutionLevel.High;
|
||||
public BlendMode blendMode = BlendMode.Blend;
|
||||
public AudioState audioState = AudioState.ApplicationAndMicAudio;
|
||||
public CaptureSide captureside = CaptureSide.Single;
|
||||
public bool useGreenBackGround = false;
|
||||
|
||||
private XREALVideoCapture _videoCapture;
|
||||
|
||||
public bool IsRecording => _videoCapture != null && _videoCapture.IsRecording;
|
||||
public Action OnStartedRecordingVideo { get; set; }
|
||||
public Action<string> OnStoppedRecordingVideoAction { get; set; }
|
||||
|
||||
private GalleryDataProvider _galleryDataTool;
|
||||
|
||||
|
||||
/// <summary> Save the video to Application.persistentDataPath. </summary>
|
||||
/// <value> The full pathname of the video save file. </value>
|
||||
private string VideoSaveExtension => Path.Combine(Application.persistentDataPath, "Recording");
|
||||
|
||||
private string VideoSavePath
|
||||
{
|
||||
get
|
||||
{
|
||||
var timeStamp = Time.time.ToString().Replace(".", "").Replace(":", "");
|
||||
var filename =
|
||||
$"{this.GetSystem<IGlobalConfigSystem>().GetConnectionId()}{timeStamp}.mp4";
|
||||
return Path.Combine(Application.persistentDataPath, VideoSaveExtension, filename);
|
||||
}
|
||||
}
|
||||
|
||||
private string _videoSavePath;
|
||||
|
||||
public void StartRecording()
|
||||
{
|
||||
_videoSavePath = VideoSavePath;
|
||||
if (_videoCapture == null)
|
||||
CreateVideoCapture(StartVideoCapture);
|
||||
else if (_videoCapture.IsRecording)
|
||||
StopVideoCapture();
|
||||
else
|
||||
StartVideoCapture();
|
||||
}
|
||||
|
||||
public void StopRecording()
|
||||
{
|
||||
if (_videoCapture == null || !_videoCapture.IsRecording)
|
||||
{
|
||||
Debug.LogError("当前没有正在进行的 XREAL 录制");
|
||||
return;
|
||||
}
|
||||
|
||||
StopVideoCapture();
|
||||
}
|
||||
|
||||
/// <summary> Stops video capture. </summary>
|
||||
public void StopVideoCapture()
|
||||
{
|
||||
if (_videoCapture == null || !_videoCapture.IsRecording)
|
||||
{
|
||||
Debug.LogWarning("Can not stop video capture!");
|
||||
return;
|
||||
}
|
||||
|
||||
Debug.Log("Stop Video Capture!");
|
||||
_videoCapture.StopRecordingAsync(OnStoppedRecordingVideo);
|
||||
}
|
||||
|
||||
/// <summary> Executes the 'stopped recording video' action. </summary>
|
||||
/// <param name="result"> The result.</param>
|
||||
private void OnStoppedRecordingVideo(XREALVideoCapture.VideoCaptureResult result)
|
||||
{
|
||||
if (!result.success)
|
||||
{
|
||||
Debug.Log("Stopped Recording Video Faild!");
|
||||
return;
|
||||
}
|
||||
|
||||
Debug.Log("Stopped Recording Video!");
|
||||
_videoCapture.StopVideoModeAsync(OnStoppedVideoCaptureMode);
|
||||
}
|
||||
|
||||
/// <summary> Executes the 'stopped video capture mode' action. </summary>
|
||||
/// <param name="result"> The result.</param>
|
||||
private async void OnStoppedVideoCaptureMode(XREALVideoCapture.VideoCaptureResult result)
|
||||
{
|
||||
Debug.Log("Stopped Video Capture Mode!");
|
||||
|
||||
var encoder = _videoCapture.GetContext().GetEncoder() as VideoEncoder;
|
||||
var path = encoder.EncodeConfig.outPutPath;
|
||||
var filename = string.Format("Xreal_Shot_Video_{0}.mp4",
|
||||
DateTimeOffset.UtcNow.ToUnixTimeMilliseconds().ToString());
|
||||
|
||||
await DelayInsertVideoToGallery(path, filename, "Record");
|
||||
OnStoppedRecordingVideoAction?.Invoke(path);
|
||||
// Release video capture resource.
|
||||
_videoCapture.Dispose();
|
||||
_videoCapture = null;
|
||||
}
|
||||
|
||||
/// <summary> 延迟将视频插入相册,确保视频文件已完全写入 </summary>
|
||||
/// <param name="originFilePath"> 视频文件路径 </param>
|
||||
/// <param name="displayName"> 显示名称 </param>
|
||||
/// <param name="folderName"> 文件夹名称 </param>
|
||||
private async UniTask DelayInsertVideoToGallery(string originFilePath, string displayName, string folderName)
|
||||
{
|
||||
await UniTask.DelayFrame(100);
|
||||
InsertVideoToGallery(originFilePath, displayName, folderName);
|
||||
}
|
||||
|
||||
/// <summary> 将视频插入到系统相册中 </summary>
|
||||
/// <param name="originFilePath"> 视频文件的原始路径 </param>
|
||||
/// <param name="displayName"> 视频在相册中显示的名称 </param>
|
||||
/// <param name="folderName"> 相册文件夹名称 </param>
|
||||
public void InsertVideoToGallery(string originFilePath, string displayName, string folderName)
|
||||
{
|
||||
Debug.LogFormat("InsertVideoToGallery: {0}, {1} => {2}", displayName, originFilePath, folderName);
|
||||
if (_galleryDataTool == null) _galleryDataTool = new GalleryDataProvider();
|
||||
|
||||
_galleryDataTool.InsertVideo(originFilePath, displayName, folderName);
|
||||
}
|
||||
|
||||
private void CreateVideoCapture(Action callback)
|
||||
{
|
||||
XREALVideoCaptureUtility.CreateAsync(false, delegate(XREALVideoCapture videoCapture)
|
||||
{
|
||||
Debug.Log("Created VideoCapture Instance!");
|
||||
if (videoCapture != null)
|
||||
{
|
||||
_videoCapture = videoCapture;
|
||||
callback?.Invoke();
|
||||
}
|
||||
else
|
||||
{
|
||||
Debug.LogError("Failed to create VideoCapture Instance!");
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
public void StartVideoCapture()
|
||||
{
|
||||
if (_videoCapture.IsRecording)
|
||||
{
|
||||
Debug.LogWarning("Can not start video capture!");
|
||||
return;
|
||||
}
|
||||
|
||||
var cameraParameters = new CameraParameters();
|
||||
var cameraResolution = GetResolutionByLevel(resolutionLevel);
|
||||
cameraParameters.cameraType = CameraType.RGB;
|
||||
cameraParameters.hologramOpacity = 0.0f;
|
||||
cameraParameters.frameRate = NativeConstants.RECORD_FPS_DEFAULT;
|
||||
cameraParameters.cameraResolutionWidth = cameraResolution.width;
|
||||
cameraParameters.cameraResolutionHeight = cameraResolution.height;
|
||||
cameraParameters.pixelFormat = CapturePixelFormat.PNG;
|
||||
cameraParameters.blendMode = blendMode;
|
||||
// Set audio state, audio record needs the permission of "android.permission.RECORD_AUDIO",
|
||||
// Add it to your "AndroidManifest.xml" file in "Assets/Plugin".
|
||||
cameraParameters.audioState = audioState;
|
||||
cameraParameters.captureSide = captureside;
|
||||
cameraParameters.backgroundColor = useGreenBackGround ? Color.green : Color.black;
|
||||
|
||||
_videoCapture.StartVideoModeAsync(cameraParameters, OnStartedVideoCaptureMode, true);
|
||||
}
|
||||
|
||||
|
||||
private Resolution GetResolutionByLevel(ResolutionLevel level)
|
||||
{
|
||||
var resolutions =
|
||||
XREALVideoCaptureUtility.SupportedResolutions.OrderByDescending((res) => res.width * res.height);
|
||||
var resolution = new Resolution();
|
||||
switch (level)
|
||||
{
|
||||
case ResolutionLevel.High:
|
||||
resolution = resolutions.ElementAt(0);
|
||||
break;
|
||||
case ResolutionLevel.Middle:
|
||||
resolution = resolutions.ElementAt(1);
|
||||
break;
|
||||
case ResolutionLevel.Low:
|
||||
resolution = resolutions.ElementAt(2);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
return resolution;
|
||||
}
|
||||
|
||||
private void OnStartedVideoCaptureMode(XREALVideoCapture.VideoCaptureResult result)
|
||||
{
|
||||
if (!result.success)
|
||||
{
|
||||
Debug.Log("Started Video Capture Mode faild!");
|
||||
return;
|
||||
}
|
||||
|
||||
Debug.Log("Started Video Capture Mode!");
|
||||
|
||||
_videoCapture.StartRecordingAsync(_videoSavePath, (a) => OnStartedRecordingVideo?.Invoke());
|
||||
}
|
||||
|
||||
public IArchitecture GetArchitecture()
|
||||
{
|
||||
return MainArchitecture.Interface;
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user