1- using FFMpegCore ;
2- using OnnxStack . Core . Config ;
1+ using OnnxStack . Core . Config ;
32using OnnxStack . Core . Image ;
43using System ;
54using System . Collections . Generic ;
65using System . Diagnostics ;
76using System . IO ;
87using System . Linq ;
98using System . Runtime . CompilerServices ;
9+ using System . Text . Json ;
1010using System . Threading ;
1111using System . Threading . Tasks ;
1212
@@ -73,7 +73,7 @@ private static async Task WriteVideoFramesAsync(IEnumerable<OnnxImage> onnxImage
7373 foreach ( var image in onnxImages )
7474 {
7575 // Write each frame to the input stream of FFMPEG
76- await videoWriter . StandardInput . BaseStream . WriteAsync ( image . GetImageBytes ( ) , cancellationToken ) ;
76+ await image . CopyToStreamAsync ( videoWriter . StandardInput . BaseStream , cancellationToken ) ;
7777 }
7878
7979 // Done close stream and wait for app to process
@@ -103,7 +103,7 @@ public static async Task WriteVideoStreamAsync(VideoInfo videoInfo, IAsyncEnumer
103103 await foreach ( var frame in videoStream )
104104 {
105105 // Write each frame to the input stream of FFMPEG
106- await frame . CopyToStreamAsync ( videoWriter . StandardInput . BaseStream ) ;
106+ await frame . CopyToStreamAsync ( videoWriter . StandardInput . BaseStream , cancellationToken ) ;
107107 }
108108
109109 // Done close stream and wait for app to process
@@ -118,12 +118,17 @@ public static async Task WriteVideoStreamAsync(VideoInfo videoInfo, IAsyncEnumer
118118 /// </summary>
119119 /// <param name="videoBytes">The video bytes.</param>
120120 /// <returns></returns>
121- public static async Task < VideoInfo > ReadVideoInfoAsync ( byte [ ] videoBytes )
121+ public static async Task < VideoInfo > ReadVideoInfoAsync ( byte [ ] videoBytes , CancellationToken cancellationToken = default )
122122 {
123- using ( var memoryStream = new MemoryStream ( videoBytes ) )
123+ string tempVideoPath = GetTempFilename ( ) ;
124+ try
125+ {
126+ await File . WriteAllBytesAsync ( tempVideoPath , videoBytes , cancellationToken ) ;
127+ return await ReadVideoInfoAsync ( tempVideoPath , cancellationToken ) ;
128+ }
129+ finally
124130 {
125- var result = await FFProbe . AnalyseAsync ( memoryStream ) . ConfigureAwait ( false ) ;
126- return new VideoInfo ( result . PrimaryVideoStream . Width , result . PrimaryVideoStream . Height , result . Duration , ( int ) result . PrimaryVideoStream . FrameRate ) ;
131+ DeleteTempFile ( tempVideoPath ) ;
127132 }
128133 }
129134
@@ -133,10 +138,29 @@ public static async Task<VideoInfo> ReadVideoInfoAsync(byte[] videoBytes)
133138 /// </summary>
134139 /// <param name="filename">The filename.</param>
135140 /// <returns></returns>
136- public static async Task < VideoInfo > ReadVideoInfoAsync ( string filename )
141+ public static async Task < VideoInfo > ReadVideoInfoAsync ( string filename , CancellationToken cancellationToken = default )
137142 {
138- var result = await FFProbe . AnalyseAsync ( filename ) . ConfigureAwait ( false ) ;
139- return new VideoInfo ( result . PrimaryVideoStream . Width , result . PrimaryVideoStream . Height , result . Duration , ( int ) result . PrimaryVideoStream . FrameRate ) ;
143+
144+ using ( var metadataReader = CreateMetadataReader ( filename ) )
145+ {
146+ // Start FFMPEG
147+ metadataReader . Start ( ) ;
148+
149+ var videoInfo = default ( VideoInfo ) ;
150+ using ( StreamReader reader = metadataReader . StandardOutput )
151+ {
152+ string result = await reader . ReadToEndAsync ( ) ;
153+ var videoMetadata = JsonSerializer . Deserialize < VideoMetadata > ( result ) ;
154+ var videoStream = videoMetadata . Streams . FirstOrDefault ( ) ;
155+ if ( videoStream is null )
156+ throw new Exception ( "Failed to parse video stream metadata" ) ;
157+
158+ videoInfo = new VideoInfo ( videoStream . Height , videoStream . Width , videoStream . Duration , videoStream . FramesPerSecond ) ;
159+ }
160+
161+ await metadataReader . WaitForExitAsync ( cancellationToken ) ;
162+ return videoInfo ;
163+ }
140164 }
141165
142166
@@ -308,7 +332,7 @@ private static Process CreateReader(string inputFile, float fps)
308332 {
309333 var ffmpegProcess = new Process ( ) ;
310334 ffmpegProcess . StartInfo . FileName = _configuration . FFmpegPath ;
311- ffmpegProcess . StartInfo . Arguments = $ "-hide_banner -loglevel error -i \" { inputFile } \" -c:v png -r { fps } -f image2pipe -";
335+ ffmpegProcess . StartInfo . Arguments = $ "-hide_banner -loglevel error -hwaccel:v auto - i \" { inputFile } \" -c:v png -r { fps } -f image2pipe -";
312336 ffmpegProcess . StartInfo . RedirectStandardOutput = true ;
313337 ffmpegProcess . StartInfo . UseShellExecute = false ;
314338 ffmpegProcess . StartInfo . CreateNoWindow = true ;
@@ -329,14 +353,31 @@ private static Process CreateWriter(string outputFile, float fps, double aspectR
329353 var codec = preserveTransparency ? "png" : "libx264" ;
330354 var format = preserveTransparency ? "yuva420p" : "yuv420p" ;
331355 ffmpegProcess . StartInfo . FileName = _configuration . FFmpegPath ;
332- ffmpegProcess . StartInfo . Arguments = $ "-hide_banner -loglevel error -framerate { fps : F4} -i - -c:v { codec } -movflags +faststart -vf format={ format } -aspect { aspectRatio } { outputFile } ";
356+ ffmpegProcess . StartInfo . Arguments = $ "-hide_banner -loglevel error -framerate { fps : F4} -hwaccel:v auto - i - -c:v { codec } -movflags +faststart -vf format={ format } -aspect { aspectRatio } { outputFile } ";
333357 ffmpegProcess . StartInfo . RedirectStandardInput = true ;
334358 ffmpegProcess . StartInfo . UseShellExecute = false ;
335359 ffmpegProcess . StartInfo . CreateNoWindow = true ;
336360 return ffmpegProcess ;
337361 }
338362
339363
364+ /// <summary>
365+ /// Creates the metadata reader.
366+ /// </summary>
367+ /// <param name="inputFile">The input file.</param>
368+ /// <returns></returns>
369+ private static Process CreateMetadataReader ( string inputFile )
370+ {
371+ var ffprobeProcess = new Process ( ) ;
372+ ffprobeProcess . StartInfo . FileName = _configuration . FFprobePath ;
373+ ffprobeProcess . StartInfo . Arguments = $ "-v quiet -print_format json -show_format -show_streams { inputFile } ";
374+ ffprobeProcess . StartInfo . RedirectStandardOutput = true ;
375+ ffprobeProcess . StartInfo . UseShellExecute = false ;
376+ ffprobeProcess . StartInfo . CreateNoWindow = true ;
377+ return ffprobeProcess ;
378+ }
379+
380+
340381 /// <summary>
341382 /// Determines whether we are at the start of a PNG image in the specified buffer.
342383 /// </summary>
0 commit comments