Remote control session recorder now pipes directly into MP4 file. XAML fix for Avalonia project.

This commit is contained in:
Jared Goodwin 2019-05-15 17:22:53 -07:00
parent d27374e667
commit 0f1e3811cc
18 changed files with 93 additions and 80 deletions

View File

@ -1,6 +1,6 @@
<Application xmlns="https://github.com/avaloniaui"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:local="clr-namespace:Remotely_Desktop.Unix"
xmlns:local="clr-namespace:Remotely_Desktop.Unix;assembly=Remotely_Desktop"
x:Class="Remotely_Desktop.Unix.App">
<Application.DataTemplates>
<local:ViewLocator/>

View File

@ -4,7 +4,7 @@
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
mc:Ignorable="d" d:DesignWidth="800" d:DesignHeight="450"
x:Class="Remotely_Desktop.Unix.Controls.HostNamePrompt"
xmlns:ViewModels="clr-namespace:Remotely_Desktop.Unix.ViewModels"
xmlns:ViewModels="clr-namespace:Remotely_Desktop.Unix.ViewModels;assembly=Remotely_Desktop"
Title="Remotely Host Name" Height="150" Width="350" WindowStartupLocation="CenterOwner">
<Window.DataContext>
<ViewModels:HostNamePromptViewModel/>

View File

@ -3,7 +3,7 @@
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
mc:Ignorable="d" d:DesignWidth="800" d:DesignHeight="450"
xmlns:vm="clr-namespace:Remotely_Desktop.Unix.ViewModels;assembly=Remotely_Desktop.Unix"
xmlns:vm="clr-namespace:Remotely_Desktop.Unix.ViewModels;assembly=Remotely_Desktop"
x:Class="Remotely_Desktop.Unix.Controls.MessageBox"
Title="{Binding Caption}" SizeToContent="WidthAndHeight" MinWidth="200" MinHeight="100" WindowStartupLocation="CenterOwner">
<Window.DataContext>

View File

@ -17,24 +17,24 @@
<AvaloniaResource Include="Assets\*" />
<AvaloniaResource Remove="Controls\HostNamePrompt.xaml" />
<AvaloniaResource Remove="Controls\MessageBox.xaml" />
</ItemGroup>
<ItemGroup>
<None Remove="Controls\HostNamePrompt.xaml" />
<None Remove="Controls\MessageBox.xaml" />
</ItemGroup>
<ItemGroup>
<EmbeddedResource Include="Controls\HostNamePrompt.xaml">
<Generator>MSBuild:Compile</Generator>
</EmbeddedResource>
<EmbeddedResource Include="Controls\MessageBox.xaml">
<Generator>MSBuild:Compile</Generator>
</EmbeddedResource>
</ItemGroup>
<ItemGroup>
<PackageReference Include="Avalonia" Version="0.8.0" />
<PackageReference Include="Avalonia.Desktop" Version="0.8.0" />
<PackageReference Include="Avalonia.ReactiveUI" Version="0.8.0" />
</ItemGroup>
<ItemGroup>
<EmbeddedResource Include="Controls\HostNamePrompt.xaml">
<Generator>MSBuild:Compile</Generator>
</EmbeddedResource>
</ItemGroup>
<ItemGroup>
<EmbeddedResource Include="Controls\MessageBox.xaml">
<Generator>MSBuild:Compile</Generator>
</EmbeddedResource>
</ItemGroup>
<ItemGroup>
<ProjectReference Include="..\Remotely_ScreenCast.Core\Remotely_ScreenCast.Core.csproj" />
<ProjectReference Include="..\Remotely_ScreenCast.Linux\Remotely_ScreenCast.Linux.csproj" />

View File

@ -155,6 +155,11 @@ namespace Remotely_Desktop.Unix.ViewModels
{
Conductor.SetMessageHandlers(new X11Input());
}
if (OSUtils.IsWindows)
{
return;
}
await Conductor.CasterSocket.SendDeviceInfo(Conductor.ServiceID, Environment.MachineName);
await Conductor.CasterSocket.GetSessionID();

View File

@ -1,6 +1,6 @@
<Window xmlns="https://github.com/avaloniaui"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:vm="clr-namespace:Remotely_Desktop.Unix.ViewModels;assembly=Remotely_Desktop.Unix"
xmlns:vm="clr-namespace:Remotely_Desktop.Unix.ViewModels;assembly=Remotely_Desktop"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
mc:Ignorable="d" d:DesignWidth="800" d:DesignHeight="450"

View File

@ -25,6 +25,10 @@
<assemblyIdentity name="System.Numerics.Vectors" publicKeyToken="b03f5f7f11d50a3a" culture="neutral" />
<bindingRedirect oldVersion="0.0.0.0-4.1.4.0" newVersion="4.1.4.0" />
</dependentAssembly>
<dependentAssembly>
<assemblyIdentity name="System.Memory" publicKeyToken="cc7b13ffcd2ddd51" culture="neutral" />
<bindingRedirect oldVersion="0.0.0.0-4.0.1.1" newVersion="4.0.1.1" />
</dependentAssembly>
</assemblyBinding>
</runtime>
</configuration>

View File

@ -1,6 +1,6 @@
<?xml version="1.0" encoding="utf-8"?>
<Project ToolsVersion="15.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<Import Project="..\packages\PropertyChanged.Fody.3.0.0\build\PropertyChanged.Fody.props" Condition="Exists('..\packages\PropertyChanged.Fody.3.0.0\build\PropertyChanged.Fody.props')" />
<Import Project="..\packages\PropertyChanged.Fody.3.0.1\build\PropertyChanged.Fody.props" Condition="Exists('..\packages\PropertyChanged.Fody.3.0.1\build\PropertyChanged.Fody.props')" />
<Import Project="..\packages\Costura.Fody.4.0.0\build\Costura.Fody.props" Condition="Exists('..\packages\Costura.Fody.4.0.0\build\Costura.Fody.props')" />
<Import Project="$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props" Condition="Exists('$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props')" />
<PropertyGroup>
@ -51,8 +51,8 @@
<Reference Include="Newtonsoft.Json, Version=12.0.0.0, Culture=neutral, PublicKeyToken=30ad4fe6b2a6aeed, processorArchitecture=MSIL">
<HintPath>..\packages\Newtonsoft.Json.12.0.2\lib\net45\Newtonsoft.Json.dll</HintPath>
</Reference>
<Reference Include="PropertyChanged, Version=3.0.0.0, Culture=neutral, PublicKeyToken=ee3ee20bcf148ddd, processorArchitecture=MSIL">
<HintPath>..\packages\PropertyChanged.Fody.3.0.0\lib\net452\PropertyChanged.dll</HintPath>
<Reference Include="PropertyChanged, Version=3.0.1.0, Culture=neutral, PublicKeyToken=ee3ee20bcf148ddd, processorArchitecture=MSIL">
<HintPath>..\packages\PropertyChanged.Fody.3.0.1\lib\net452\PropertyChanged.dll</HintPath>
</Reference>
<Reference Include="System" />
<Reference Include="System.Configuration" />
@ -148,13 +148,13 @@
</ProjectReference>
</ItemGroup>
<Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />
<Import Project="..\packages\Fody.5.0.3\build\Fody.targets" Condition="Exists('..\packages\Fody.5.0.3\build\Fody.targets')" />
<Target Name="EnsureNuGetPackageBuildImports" BeforeTargets="PrepareForBuild">
<PropertyGroup>
<ErrorText>This project references NuGet package(s) that are missing on this computer. Use NuGet Package Restore to download them. For more information, see http://go.microsoft.com/fwlink/?LinkID=322105. The missing file is {0}.</ErrorText>
</PropertyGroup>
<Error Condition="!Exists('..\packages\Fody.5.0.3\build\Fody.targets')" Text="$([System.String]::Format('$(ErrorText)', '..\packages\Fody.5.0.3\build\Fody.targets'))" />
<Error Condition="!Exists('..\packages\Costura.Fody.4.0.0\build\Costura.Fody.props')" Text="$([System.String]::Format('$(ErrorText)', '..\packages\Costura.Fody.4.0.0\build\Costura.Fody.props'))" />
<Error Condition="!Exists('..\packages\PropertyChanged.Fody.3.0.0\build\PropertyChanged.Fody.props')" Text="$([System.String]::Format('$(ErrorText)', '..\packages\PropertyChanged.Fody.3.0.0\build\PropertyChanged.Fody.props'))" />
<Error Condition="!Exists('..\packages\Fody.5.0.6\build\Fody.targets')" Text="$([System.String]::Format('$(ErrorText)', '..\packages\Fody.5.0.6\build\Fody.targets'))" />
<Error Condition="!Exists('..\packages\PropertyChanged.Fody.3.0.1\build\PropertyChanged.Fody.props')" Text="$([System.String]::Format('$(ErrorText)', '..\packages\PropertyChanged.Fody.3.0.1\build\PropertyChanged.Fody.props'))" />
</Target>
<Import Project="..\packages\Fody.5.0.6\build\Fody.targets" Condition="Exists('..\packages\Fody.5.0.6\build\Fody.targets')" />
</Project>

View File

@ -1,7 +1,7 @@
<?xml version="1.0" encoding="utf-8"?>
<packages>
<package id="Costura.Fody" version="4.0.0" targetFramework="net472" />
<package id="Fody" version="5.0.3" targetFramework="net472" developmentDependency="true" />
<package id="Fody" version="5.0.6" targetFramework="net472" developmentDependency="true" />
<package id="Newtonsoft.Json" version="12.0.2" targetFramework="net472" />
<package id="PropertyChanged.Fody" version="3.0.0" targetFramework="net472" />
<package id="PropertyChanged.Fody" version="3.0.1" targetFramework="net472" />
</packages>

View File

@ -15,7 +15,7 @@
<ItemGroup>
<PackageReference Include="Microsoft.AspNetCore.SignalR.Client" Version="1.1.0" />
<PackageReference Include="Microsoft.AspNetCore.SignalR.Client.Core" Version="1.1.0" />
<PackageReference Include="Microsoft.AspNetCore.SignalR.Protocols.MessagePack" Version="1.1.0" />
<PackageReference Include="Microsoft.AspNetCore.SignalR.Protocols.MessagePack" Version="1.1.5" />
<PackageReference Include="System.Drawing.Common" Version="4.5.1" />
</ItemGroup>

View File

@ -25,6 +25,10 @@
<assemblyIdentity name="System.Threading.Tasks.Extensions" publicKeyToken="cc7b13ffcd2ddd51" culture="neutral" />
<bindingRedirect oldVersion="0.0.0.0-4.2.0.0" newVersion="4.2.0.0" />
</dependentAssembly>
<dependentAssembly>
<assemblyIdentity name="System.Memory" publicKeyToken="cc7b13ffcd2ddd51" culture="neutral" />
<bindingRedirect oldVersion="0.0.0.0-4.0.1.1" newVersion="4.0.1.1" />
</dependentAssembly>
</assemblyBinding>
</runtime>
</configuration>

View File

@ -41,8 +41,8 @@
<Reference Include="Costura, Version=4.0.0.0, Culture=neutral, PublicKeyToken=9919ef960d84173d, processorArchitecture=MSIL">
<HintPath>..\packages\Costura.Fody.4.0.0\lib\net40\Costura.dll</HintPath>
</Reference>
<Reference Include="MessagePack, Version=1.7.3.4, Culture=neutral, PublicKeyToken=b4a0369545f0a1be, processorArchitecture=MSIL">
<HintPath>..\packages\MessagePack.1.7.3.4\lib\net47\MessagePack.dll</HintPath>
<Reference Include="MessagePack, Version=1.7.3.7, Culture=neutral, PublicKeyToken=b4a0369545f0a1be, processorArchitecture=MSIL">
<HintPath>..\packages\MessagePack.1.7.3.7\lib\net47\MessagePack.dll</HintPath>
</Reference>
<Reference Include="Microsoft.AspNetCore.Connections.Abstractions, Version=2.2.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60, processorArchitecture=MSIL">
<HintPath>..\packages\Microsoft.AspNetCore.Connections.Abstractions.2.2.0\lib\netstandard2.0\Microsoft.AspNetCore.Connections.Abstractions.dll</HintPath>
@ -68,8 +68,8 @@
<Reference Include="Microsoft.AspNetCore.SignalR.Protocols.Json, Version=1.1.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60, processorArchitecture=MSIL">
<HintPath>..\packages\Microsoft.AspNetCore.SignalR.Protocols.Json.1.1.0\lib\netstandard2.0\Microsoft.AspNetCore.SignalR.Protocols.Json.dll</HintPath>
</Reference>
<Reference Include="Microsoft.AspNetCore.SignalR.Protocols.MessagePack, Version=1.1.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60, processorArchitecture=MSIL">
<HintPath>..\packages\Microsoft.AspNetCore.SignalR.Protocols.MessagePack.1.1.0\lib\netstandard2.0\Microsoft.AspNetCore.SignalR.Protocols.MessagePack.dll</HintPath>
<Reference Include="Microsoft.AspNetCore.SignalR.Protocols.MessagePack, Version=1.1.5.0, Culture=neutral, PublicKeyToken=adb9793829ddae60, processorArchitecture=MSIL">
<HintPath>..\packages\Microsoft.AspNetCore.SignalR.Protocols.MessagePack.1.1.5\lib\netstandard2.0\Microsoft.AspNetCore.SignalR.Protocols.MessagePack.dll</HintPath>
</Reference>
<Reference Include="Microsoft.Extensions.Configuration, Version=2.2.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60, processorArchitecture=MSIL">
<HintPath>..\packages\Microsoft.Extensions.Configuration.2.2.0\lib\netstandard2.0\Microsoft.Extensions.Configuration.dll</HintPath>
@ -126,8 +126,8 @@
<Reference Include="System.IO.Pipelines, Version=4.0.0.1, Culture=neutral, PublicKeyToken=cc7b13ffcd2ddd51, processorArchitecture=MSIL">
<HintPath>..\packages\System.IO.Pipelines.4.5.3\lib\netstandard2.0\System.IO.Pipelines.dll</HintPath>
</Reference>
<Reference Include="System.Memory, Version=4.0.1.0, Culture=neutral, PublicKeyToken=cc7b13ffcd2ddd51, processorArchitecture=MSIL">
<HintPath>..\packages\System.Memory.4.5.2\lib\netstandard2.0\System.Memory.dll</HintPath>
<Reference Include="System.Memory, Version=4.0.1.1, Culture=neutral, PublicKeyToken=cc7b13ffcd2ddd51, processorArchitecture=MSIL">
<HintPath>..\packages\System.Memory.4.5.3\lib\netstandard2.0\System.Memory.dll</HintPath>
</Reference>
<Reference Include="System.Numerics" />
<Reference Include="System.Numerics.Vectors, Version=4.1.4.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a, processorArchitecture=MSIL">
@ -186,12 +186,12 @@
copy /y "$(TargetPath)" "$(SolutionDir)Remotely_Agent\bin\Debug\netcoreapp2.2\ScreenCast\"
)</PostBuildEvent>
</PropertyGroup>
<Import Project="..\packages\Fody.5.0.3\build\Fody.targets" Condition="Exists('..\packages\Fody.5.0.3\build\Fody.targets')" />
<Target Name="EnsureNuGetPackageBuildImports" BeforeTargets="PrepareForBuild">
<PropertyGroup>
<ErrorText>This project references NuGet package(s) that are missing on this computer. Use NuGet Package Restore to download them. For more information, see http://go.microsoft.com/fwlink/?LinkID=322105. The missing file is {0}.</ErrorText>
</PropertyGroup>
<Error Condition="!Exists('..\packages\Fody.5.0.3\build\Fody.targets')" Text="$([System.String]::Format('$(ErrorText)', '..\packages\Fody.5.0.3\build\Fody.targets'))" />
<Error Condition="!Exists('..\packages\Costura.Fody.4.0.0\build\Costura.Fody.props')" Text="$([System.String]::Format('$(ErrorText)', '..\packages\Costura.Fody.4.0.0\build\Costura.Fody.props'))" />
<Error Condition="!Exists('..\packages\Fody.5.0.6\build\Fody.targets')" Text="$([System.String]::Format('$(ErrorText)', '..\packages\Fody.5.0.6\build\Fody.targets'))" />
</Target>
<Import Project="..\packages\Fody.5.0.6\build\Fody.targets" Condition="Exists('..\packages\Fody.5.0.6\build\Fody.targets')" />
</Project>

View File

@ -1,8 +1,8 @@
<?xml version="1.0" encoding="utf-8"?>
<packages>
<package id="Costura.Fody" version="4.0.0" targetFramework="net472" />
<package id="Fody" version="5.0.3" targetFramework="net472" developmentDependency="true" />
<package id="MessagePack" version="1.7.3.4" targetFramework="net472" />
<package id="Fody" version="5.0.6" targetFramework="net472" developmentDependency="true" />
<package id="MessagePack" version="1.7.3.7" targetFramework="net472" />
<package id="Microsoft.AspNetCore.Connections.Abstractions" version="2.2.0" targetFramework="net472" />
<package id="Microsoft.AspNetCore.Http.Connections.Client" version="1.1.0" targetFramework="net472" />
<package id="Microsoft.AspNetCore.Http.Connections.Common" version="1.1.0" targetFramework="net472" />
@ -11,7 +11,7 @@
<package id="Microsoft.AspNetCore.SignalR.Client.Core" version="1.1.0" targetFramework="net472" />
<package id="Microsoft.AspNetCore.SignalR.Common" version="1.1.0" targetFramework="net472" />
<package id="Microsoft.AspNetCore.SignalR.Protocols.Json" version="1.1.0" targetFramework="net472" />
<package id="Microsoft.AspNetCore.SignalR.Protocols.MessagePack" version="1.1.0" targetFramework="net472" />
<package id="Microsoft.AspNetCore.SignalR.Protocols.MessagePack" version="1.1.5" targetFramework="net472" />
<package id="Microsoft.Extensions.Configuration" version="2.2.0" targetFramework="net472" />
<package id="Microsoft.Extensions.Configuration.Abstractions" version="2.2.0" targetFramework="net472" />
<package id="Microsoft.Extensions.Configuration.Binder" version="2.2.4" targetFramework="net472" />
@ -29,7 +29,7 @@
<package id="System.ComponentModel.Annotations" version="4.5.0" targetFramework="net472" />
<package id="System.Drawing.Common" version="4.5.1" targetFramework="net472" />
<package id="System.IO.Pipelines" version="4.5.3" targetFramework="net472" />
<package id="System.Memory" version="4.5.2" targetFramework="net472" />
<package id="System.Memory" version="4.5.3" targetFramework="net472" />
<package id="System.Numerics.Vectors" version="4.5.0" targetFramework="net472" />
<package id="System.Runtime.CompilerServices.Unsafe" version="4.5.2" targetFramework="net472" />
<package id="System.Threading.Channels" version="4.5.0" targetFramework="net472" />

View File

@ -1 +1 @@
2019.05.09.2205
2019.05.15.1708

View File

@ -0,0 +1,15 @@
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Drawing;
using System.Linq;
using System.Threading.Tasks;
namespace Remotely_Server.Models
{
public class RecordingSessionState
{
public Bitmap CumulativeFrame { get; set; }
public Process FfmpegProcess { get; set; }
}
}

View File

@ -56,7 +56,7 @@
<ItemGroup>
<PackageReference Include="Microsoft.AspNetCore.App" />
<PackageReference Include="Microsoft.AspNetCore.SignalR.Protocols.MessagePack" Version="1.1.0" />
<PackageReference Include="Microsoft.AspNetCore.SignalR.Protocols.MessagePack" Version="1.1.5" />
<PackageReference Include="Microsoft.CodeAnalysis.Common" Version="3.0.0" />
<PackageReference Include="Microsoft.EntityFrameworkCore.Sqlite" Version="2.2.4" />
<PackageReference Include="Microsoft.Extensions.Logging.EventLog" Version="2.2.0" />

View File

@ -134,7 +134,7 @@ namespace Remotely_Server.Services
if (AppConfig.RecordRemoteControlSessions)
{
RCSessionRecorder.EncodeFrames(Context.ConnectionId);
RCSessionRecorder.StopProcessing(Context.ConnectionId);
}
}

View File

@ -4,6 +4,7 @@ using Remotely_Server.Models;
using System;
using System.Collections.Concurrent;
using System.Collections.Generic;
using System.Diagnostics;
using System.Drawing;
using System.Drawing.Imaging;
using System.IO;
@ -16,7 +17,7 @@ namespace Remotely_Server.Services
{
private static bool IsProcessing { get; set; }
private static ConcurrentQueue<RemoteControlFrame> FrameQueue { get; } = new ConcurrentQueue<RemoteControlFrame>();
private static ConcurrentDictionary<string, Bitmap> CumulativeFrames { get; } = new ConcurrentDictionary<string, Bitmap>();
private static ConcurrentDictionary<string, RecordingSessionState> SessionStates { get; } = new ConcurrentDictionary<string, RecordingSessionState>();
private static object LockObject { get; } = new object();
private IHostingEnvironment HostingEnv { get; }
@ -52,18 +53,28 @@ namespace Remotely_Server.Services
{
if (FrameQueue.TryDequeue(out var frame))
{
if (!CumulativeFrames.ContainsKey(frame.ViewerID))
{
CumulativeFrames[frame.ViewerID] = new Bitmap(frame.Width, frame.Height);
}
var saveDir = Directory.CreateDirectory(GetSaveFolder(frame));
var saveFile = Path.Combine(
saveDir.FullName,
$"frame-{(Directory.GetFiles(saveDir.FullName).Length + 1).ToString()}.jpg");
var saveFile = Path.Combine(saveDir.FullName, $"Recording.mp4");
var bitmap = CumulativeFrames[frame.ViewerID] as Bitmap;
if (!SessionStates.ContainsKey(frame.ViewerID))
{
SessionStates[frame.ViewerID] = new RecordingSessionState()
{
CumulativeFrame = new Bitmap(frame.Width, frame.Height)
};
var ffmpegProc = new Process();
SessionStates[frame.ViewerID].FfmpegProcess = ffmpegProc;
ffmpegProc.StartInfo.FileName = "ffmpeg.exe";
ffmpegProc.StartInfo.Arguments = $"-y -f image2pipe -i pipe:.jpg -r 5 \"{saveFile}\"";
ffmpegProc.StartInfo.UseShellExecute = false;
ffmpegProc.StartInfo.RedirectStandardInput = true;
ffmpegProc.Start();
}
var bitmap = SessionStates[frame.ViewerID].CumulativeFrame;
using (var graphics = Graphics.FromImage(bitmap))
{
using (var ms = new MemoryStream(frame.FrameBytes))
@ -74,14 +85,10 @@ namespace Remotely_Server.Services
}
}
}
bitmap.Save(saveFile, ImageFormat.Jpeg);
bitmap.Save(SessionStates[frame.ViewerID].FfmpegProcess.StandardInput.BaseStream, ImageFormat.Jpeg);
}
}
}
catch (Exception ex)
{
DataService.WriteEvent(ex);
}
finally
{
IsProcessing = false;
@ -102,34 +109,12 @@ namespace Remotely_Server.Services
frame.StartTime.ToString("HH.mm.ss.fff"));
}
internal void EncodeFrames(string viewerID)
internal void StopProcessing(string viewerID)
{
var recordingDirs = Directory.GetDirectories(Path.Combine(
HostingEnv.ContentRootPath,
"Recordings",
DateTime.Now.Year.ToString().PadLeft(4, '0'),
DateTime.Now.Month.ToString().PadLeft(2, '0')),
viewerID,
SearchOption.AllDirectories);
foreach (var dir in recordingDirs)
{
foreach (var subDir in Directory.GetDirectories(dir))
{
try
{
System.Diagnostics.Process.Start("ffmpeg", $"-y -i \"{Path.Combine(subDir, "frame-%d.jpg")}\" \"{Path.Combine(subDir, "Recording.mp4")}\"").WaitForExit();
foreach (var file in Directory.GetFiles(subDir, "*.jpg"))
{
File.Delete(file);
}
}
catch (Exception ex)
{
DataService.WriteEvent(ex);
}
}
}
SessionStates[viewerID].FfmpegProcess.StandardInput.Flush();
SessionStates[viewerID].FfmpegProcess.StandardInput.Close();
SessionStates[viewerID].FfmpegProcess.Close();
SessionStates.TryRemove(viewerID, out _);
}
}
}