录屏
This commit is contained in:
@@ -3588,7 +3588,7 @@ MonoBehaviour:
|
|||||||
onValueChanged:
|
onValueChanged:
|
||||||
m_PersistentCalls:
|
m_PersistentCalls:
|
||||||
m_Calls: []
|
m_Calls: []
|
||||||
m_IsOn: 1
|
m_IsOn: 0
|
||||||
--- !u!1 &3813444533319316158
|
--- !u!1 &3813444533319316158
|
||||||
GameObject:
|
GameObject:
|
||||||
m_ObjectHideFlags: 0
|
m_ObjectHideFlags: 0
|
||||||
|
|||||||
@@ -40,6 +40,9 @@ namespace Script
|
|||||||
private AudioStreamSender _audioStreamSender;
|
private AudioStreamSender _audioStreamSender;
|
||||||
private VideoStreamSender _videoStreamSender;
|
private VideoStreamSender _videoStreamSender;
|
||||||
|
|
||||||
|
|
||||||
|
private IVideoRecorder _recorder;
|
||||||
|
|
||||||
public void Initialize(GameObject panelGo, MainPanel mainPanel)
|
public void Initialize(GameObject panelGo, MainPanel mainPanel)
|
||||||
{
|
{
|
||||||
PanelGo = panelGo;
|
PanelGo = panelGo;
|
||||||
@@ -54,8 +57,18 @@ namespace Script
|
|||||||
_hangUpTog = PanelGo.transform.Find("menuBar/hangUp").GetComponent<Button>();
|
_hangUpTog = PanelGo.transform.Find("menuBar/hangUp").GetComponent<Button>();
|
||||||
_audioStreamSender = GameObject.Find("RenderStreaming").GetComponent<AudioStreamSender>();
|
_audioStreamSender = GameObject.Find("RenderStreaming").GetComponent<AudioStreamSender>();
|
||||||
_videoStreamSender = GameObject.Find("RenderStreaming").GetComponent<VideoStreamSender>();
|
_videoStreamSender = GameObject.Find("RenderStreaming").GetComponent<VideoStreamSender>();
|
||||||
|
#if UNITY_EDITOR
|
||||||
|
_recorder = new EditorGameViewRecorder();
|
||||||
|
#elif UNITY_ANDROID
|
||||||
|
_recorder = new XrealMixedRecorder();
|
||||||
|
#else
|
||||||
|
Debug.LogWarning("当前平台没有可用录制器");
|
||||||
|
#endif
|
||||||
|
_recorder.OnStartedRecordingVideo = OnStartedRecordingVideo;
|
||||||
|
_recorder.OnStoppedRecordingVideoAction = OnStoppedRecordingVideoAction;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
public void OnEnter()
|
public void OnEnter()
|
||||||
{
|
{
|
||||||
LoadUsers();
|
LoadUsers();
|
||||||
@@ -119,8 +132,38 @@ namespace Script
|
|||||||
|
|
||||||
private void OnRecordTogValueChanged(bool value)
|
private void OnRecordTogValueChanged(bool value)
|
||||||
{
|
{
|
||||||
|
if (value)
|
||||||
|
_recorder.StartRecording();
|
||||||
|
else
|
||||||
|
_recorder.StopRecording();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private void OnStartedRecordingVideo()
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
private void OnStoppedRecordingVideoAction(string path)
|
||||||
|
{
|
||||||
|
var participants = new List<MainPanel.UsersItem>();
|
||||||
|
MainPanel.UsersItem host = null;
|
||||||
|
foreach (var value in _meetingList.Values)
|
||||||
|
if (value.item.role == "host")
|
||||||
|
{
|
||||||
|
host = value.item;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
participants.Add(value.item);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
WebRequestSystem.Upload(path, this.GetSystem<IGlobalConfigSystem>().IP,
|
||||||
|
this.GetSystem<IGlobalConfigSystem>().GetConnectionId(),
|
||||||
|
this.GetSystem<IGlobalConfigSystem>().GetUserId(), host, participants);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
private void OnHangUpTogValueChanged()
|
private void OnHangUpTogValueChanged()
|
||||||
{
|
{
|
||||||
this.GetSystem<IRenderStreamingSystem>().HangUp();
|
this.GetSystem<IRenderStreamingSystem>().HangUp();
|
||||||
|
|||||||
8
Assets/Script/Recorder.meta
Normal file
8
Assets/Script/Recorder.meta
Normal file
@@ -0,0 +1,8 @@
|
|||||||
|
fileFormatVersion: 2
|
||||||
|
guid: 0d0e1b8f02d02434c9f0d3e805a6ba04
|
||||||
|
folderAsset: yes
|
||||||
|
DefaultImporter:
|
||||||
|
externalObjects: {}
|
||||||
|
userData:
|
||||||
|
assetBundleName:
|
||||||
|
assetBundleVariant:
|
||||||
99
Assets/Script/Recorder/EditorGameViewRecorder.cs
Normal file
99
Assets/Script/Recorder/EditorGameViewRecorder.cs
Normal file
@@ -0,0 +1,99 @@
|
|||||||
|
#if UNITY_EDITOR
|
||||||
|
using System;
|
||||||
|
using System.IO;
|
||||||
|
using RenderStreaming;
|
||||||
|
using Stary.Evo;
|
||||||
|
using UnityEngine;
|
||||||
|
using UnityEditor.Recorder;
|
||||||
|
using UnityEditor.Recorder.Input;
|
||||||
|
|
||||||
|
public class EditorGameViewRecorder : IVideoRecorder, IController
|
||||||
|
{
|
||||||
|
private RecorderController recorderController;
|
||||||
|
|
||||||
|
public bool IsRecording => recorderController != null && recorderController.IsRecording();
|
||||||
|
|
||||||
|
/// <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 = DateTime.Now.ToString("yyyy-MM-ddTHH-mm-ss");
|
||||||
|
var filename =
|
||||||
|
$"meeting-recording-{this.GetSystem<IGlobalConfigSystem>().GetConnectionId()}-{timeStamp}";
|
||||||
|
return Path.Combine(Application.persistentDataPath, VideoSaveExtension, filename);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private string _videoSavePath;
|
||||||
|
public Action OnStartedRecordingVideo { get; set; }
|
||||||
|
public Action<string> OnStoppedRecordingVideoAction { get; set; }
|
||||||
|
|
||||||
|
public void StartRecording()
|
||||||
|
{
|
||||||
|
if (IsRecording)
|
||||||
|
return;
|
||||||
|
_videoSavePath = VideoSavePath;
|
||||||
|
|
||||||
|
var controllerSettings = ScriptableObject.CreateInstance<RecorderControllerSettings>();
|
||||||
|
recorderController = new RecorderController(controllerSettings);
|
||||||
|
|
||||||
|
var movieSettings = ScriptableObject.CreateInstance<MovieRecorderSettings>();
|
||||||
|
movieSettings.name = "Game View MP4 Recorder";
|
||||||
|
movieSettings.Enabled = true;
|
||||||
|
movieSettings.OutputFormat = MovieRecorderSettings.VideoRecorderOutputFormat.MP4;
|
||||||
|
movieSettings.OutputFile = _videoSavePath;
|
||||||
|
movieSettings.CaptureAudio = false;
|
||||||
|
|
||||||
|
movieSettings.ImageInputSettings = new GameViewInputSettings
|
||||||
|
{
|
||||||
|
OutputWidth = 1920,
|
||||||
|
OutputHeight = 1080
|
||||||
|
};
|
||||||
|
|
||||||
|
controllerSettings.AddRecorderSettings(movieSettings);
|
||||||
|
controllerSettings.SetRecordModeToManual();
|
||||||
|
controllerSettings.FrameRate = 30.0f;
|
||||||
|
controllerSettings.CapFrameRate = true;
|
||||||
|
|
||||||
|
recorderController.PrepareRecording();
|
||||||
|
|
||||||
|
var started = recorderController.StartRecording();
|
||||||
|
if (!started)
|
||||||
|
{
|
||||||
|
Debug.LogError("Editor Recorder 启动失败,请确认已进入 Play Mode,并安装 com.unity.recorder");
|
||||||
|
recorderController = null;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
Debug.Log($"Editor 开始录制: {_videoSavePath}");
|
||||||
|
OnStartedRecordingVideo?.Invoke();
|
||||||
|
}
|
||||||
|
|
||||||
|
public void StopRecording()
|
||||||
|
{
|
||||||
|
if (!IsRecording)
|
||||||
|
{
|
||||||
|
Debug.LogError("当前没有正在进行的 Editor 录制");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
recorderController.StopRecording();
|
||||||
|
|
||||||
|
if (!File.Exists(_videoSavePath))
|
||||||
|
OnStoppedRecordingVideoAction?.Invoke(_videoSavePath + ".mp4");
|
||||||
|
else
|
||||||
|
Debug.LogError($"Editor MP4 文件不存在,可能还在写入或输出路径变化: {_videoSavePath}");
|
||||||
|
|
||||||
|
recorderController = null;
|
||||||
|
}
|
||||||
|
|
||||||
|
public IArchitecture GetArchitecture()
|
||||||
|
{
|
||||||
|
return MainArchitecture.Interface;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
#endif
|
||||||
3
Assets/Script/Recorder/EditorGameViewRecorder.cs.meta
Normal file
3
Assets/Script/Recorder/EditorGameViewRecorder.cs.meta
Normal file
@@ -0,0 +1,3 @@
|
|||||||
|
fileFormatVersion: 2
|
||||||
|
guid: 2f7a8ef900894205803013925c8fbe95
|
||||||
|
timeCreated: 1779783425
|
||||||
10
Assets/Script/Recorder/IVideoRecorder.cs
Normal file
10
Assets/Script/Recorder/IVideoRecorder.cs
Normal file
@@ -0,0 +1,10 @@
|
|||||||
|
using System;
|
||||||
|
|
||||||
|
public interface IVideoRecorder
|
||||||
|
{
|
||||||
|
bool IsRecording { get; }
|
||||||
|
Action OnStartedRecordingVideo { get; set; }
|
||||||
|
Action<string> OnStoppedRecordingVideoAction { get; set; }
|
||||||
|
void StartRecording();
|
||||||
|
void StopRecording();
|
||||||
|
}
|
||||||
11
Assets/Script/Recorder/IVideoRecorder.cs.meta
Normal file
11
Assets/Script/Recorder/IVideoRecorder.cs.meta
Normal file
@@ -0,0 +1,11 @@
|
|||||||
|
fileFormatVersion: 2
|
||||||
|
guid: 7807c2de252777049950ce1055c8f3a2
|
||||||
|
MonoImporter:
|
||||||
|
externalObjects: {}
|
||||||
|
serializedVersion: 2
|
||||||
|
defaultReferences: []
|
||||||
|
executionOrder: 0
|
||||||
|
icon: {instanceID: 0}
|
||||||
|
userData:
|
||||||
|
assetBundleName:
|
||||||
|
assetBundleVariant:
|
||||||
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;
|
||||||
|
}
|
||||||
|
}
|
||||||
3
Assets/Script/Recorder/XrealMixedRecorder.cs.meta
Normal file
3
Assets/Script/Recorder/XrealMixedRecorder.cs.meta
Normal file
@@ -0,0 +1,3 @@
|
|||||||
|
fileFormatVersion: 2
|
||||||
|
guid: 7a4221a28a1840a3aae5572edfa217be
|
||||||
|
timeCreated: 1779783401
|
||||||
@@ -5,6 +5,7 @@ using System.Text;
|
|||||||
using System.Threading.Tasks;
|
using System.Threading.Tasks;
|
||||||
using Cysharp.Threading.Tasks;
|
using Cysharp.Threading.Tasks;
|
||||||
using Newtonsoft.Json;
|
using Newtonsoft.Json;
|
||||||
|
using Script;
|
||||||
using UnityEngine;
|
using UnityEngine;
|
||||||
using UnityEngine.Networking;
|
using UnityEngine.Networking;
|
||||||
|
|
||||||
@@ -511,5 +512,37 @@ namespace Stary.Evo
|
|||||||
};
|
};
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public static async UniTask Upload(string filePath, string serverBaseUrl, string meetingId, string userId,
|
||||||
|
MainPanel.UsersItem host,
|
||||||
|
List<MainPanel.UsersItem> participants)
|
||||||
|
{
|
||||||
|
var bytes = File.ReadAllBytes(filePath);
|
||||||
|
var fileName = Path.GetFileName(filePath);
|
||||||
|
|
||||||
|
var ext = Path.GetExtension(fileName).ToLowerInvariant();
|
||||||
|
var mimeType = ext == ".webm" ? "video/webm" : "video/mp4";
|
||||||
|
|
||||||
|
|
||||||
|
var form = new List<IMultipartFormSection>
|
||||||
|
{
|
||||||
|
new MultipartFormDataSection("meetingId", meetingId),
|
||||||
|
new MultipartFormDataSection("userId", userId),
|
||||||
|
new MultipartFormDataSection("filename", fileName),
|
||||||
|
new MultipartFormFileSection("recording", bytes, fileName, mimeType),
|
||||||
|
new MultipartFormDataSection("host", JsonConvert.SerializeObject(host)),
|
||||||
|
new MultipartFormDataSection("participants", JsonConvert.SerializeObject(participants))
|
||||||
|
};
|
||||||
|
|
||||||
|
using var request = UnityWebRequest.Post($"{serverBaseUrl}/api/recordings", form);
|
||||||
|
request.timeout = 300;
|
||||||
|
request.certificateHandler = new SelfSignedCertHandler(certificateData);
|
||||||
|
await request.SendWebRequest();
|
||||||
|
|
||||||
|
if (request.result != UnityWebRequest.Result.Success)
|
||||||
|
Debug.LogError($"上传失败: {request.error}, body={request.downloadHandler.text}");
|
||||||
|
else
|
||||||
|
Debug.Log($"上传成功: {request.downloadHandler.text}");
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -5,6 +5,7 @@
|
|||||||
"com.unity.ide.rider": "3.0.40",
|
"com.unity.ide.rider": "3.0.40",
|
||||||
"com.unity.inputsystem": "1.19.0",
|
"com.unity.inputsystem": "1.19.0",
|
||||||
"com.unity.nuget.newtonsoft-json": "3.2.2",
|
"com.unity.nuget.newtonsoft-json": "3.2.2",
|
||||||
|
"com.unity.recorder": "4.0.3",
|
||||||
"com.unity.render-pipelines.universal": "17.3.0",
|
"com.unity.render-pipelines.universal": "17.3.0",
|
||||||
"com.unity.test-framework": "1.1.33",
|
"com.unity.test-framework": "1.1.33",
|
||||||
"com.unity.ugui": "2.0.0",
|
"com.unity.ugui": "2.0.0",
|
||||||
|
|||||||
@@ -91,6 +91,15 @@
|
|||||||
"dependencies": {},
|
"dependencies": {},
|
||||||
"url": "https://packages.unity.com"
|
"url": "https://packages.unity.com"
|
||||||
},
|
},
|
||||||
|
"com.unity.recorder": {
|
||||||
|
"version": "4.0.3",
|
||||||
|
"depth": 0,
|
||||||
|
"source": "registry",
|
||||||
|
"dependencies": {
|
||||||
|
"com.unity.timeline": "1.0.0"
|
||||||
|
},
|
||||||
|
"url": "https://packages.unity.com"
|
||||||
|
},
|
||||||
"com.unity.render-pipelines.core": {
|
"com.unity.render-pipelines.core": {
|
||||||
"version": "14.0.12",
|
"version": "14.0.12",
|
||||||
"depth": 1,
|
"depth": 1,
|
||||||
@@ -167,6 +176,18 @@
|
|||||||
},
|
},
|
||||||
"url": "https://packages.unity.com"
|
"url": "https://packages.unity.com"
|
||||||
},
|
},
|
||||||
|
"com.unity.timeline": {
|
||||||
|
"version": "1.7.7",
|
||||||
|
"depth": 1,
|
||||||
|
"source": "registry",
|
||||||
|
"dependencies": {
|
||||||
|
"com.unity.modules.audio": "1.0.0",
|
||||||
|
"com.unity.modules.director": "1.0.0",
|
||||||
|
"com.unity.modules.animation": "1.0.0",
|
||||||
|
"com.unity.modules.particlesystem": "1.0.0"
|
||||||
|
},
|
||||||
|
"url": "https://packages.unity.com"
|
||||||
|
},
|
||||||
"com.unity.ugui": {
|
"com.unity.ugui": {
|
||||||
"version": "2.0.0",
|
"version": "2.0.0",
|
||||||
"depth": 0,
|
"depth": 0,
|
||||||
|
|||||||
Reference in New Issue
Block a user