namespace TimelapseApi; using System.Diagnostics; using System.Threading; public class VideoFileCreator : IAsyncDisposable, IDisposable { Process? p; Stream? iStrm; string output; double fps_src; double fps_dest; bool open; public bool OpenResult {get;private set;} public VideoFileCreator(string path,double fps_src=10,double fps_dest=30,bool autoOpen=true) { this.fps_src=fps_src; this.fps_dest =fps_dest; output = path; this.open=false; if(autoOpen) { Open(); } } public bool Open() { if(open) { return OpenResult; } p=new Process(); p.StartInfo=new ProcessStartInfo("ffmpeg",$"-f image2pipe -framerate {fps_src} -i - -c:v libx264 -vf format=yuv420p -r {fps_dest} -movflags +faststart \"{output}\"") {UseShellExecute=false,RedirectStandardInput=true,CreateNoWindow=true,WindowStyle=ProcessWindowStyle.Hidden}; var r=p.Start(); if(r) { iStrm = p.StandardInput.BaseStream; } open=true; return r; } public void Add(byte[] data) { if(iStrm != null) { iStrm.Write(data,0,data.Length); } } public async Task AddAsync(byte[] data) { if(iStrm != null) { await iStrm.WriteAsync(data,0,data.Length); } } public void Add(string file) { if(iStrm != null) { byte[] data=File.ReadAllBytes(file); iStrm.Write(data,0,data.Length); } } public async Task AddAsync(string file) { if(iStrm != null) { byte[] data=await File.ReadAllBytesAsync(file); await iStrm.WriteAsync(data,0,data.Length); } } public async ValueTask DisposeAsync() { if(iStrm!= null) { await iStrm.DisposeAsync(); } if(p != null) { await p.WaitForExitAsync(); p.Dispose(); } } public void Dispose() { if(iStrm!= null) { iStrm.Dispose(); } if(p != null) { p.WaitForExit(); p.Dispose(); } } }