FF-1811: Fixing blocking issue with reading audio information

This commit is contained in:
John Andrews
2024-09-25 09:35:37 +12:00
parent 19eee14a51
commit 3fec621dca
3 changed files with 175 additions and 30 deletions

View File

@@ -34,37 +34,40 @@ public class FFmpegHelper(string ffmpeg, string ffprobe) : IFFmpegHelper
{
try
{
using (var process = new Process())
using var process = new Process();
process.StartInfo = new ProcessStartInfo
{
process.StartInfo = new ProcessStartInfo
{
FileName = ffmpeg,
UseShellExecute = false,
RedirectStandardOutput = true,
RedirectStandardError = true,
CreateNoWindow = true,
ArgumentList = {
"-hide_banner",
"-i",
file
}
};
process.Start();
bool exited = process.WaitForExit(60000);
if (exited == false)
{
process.Kill();
string pkOutput = process.StandardError.ReadToEnd()?.EmptyAsNull() ?? process.StandardOutput.ReadToEnd();
return Result<string>.Fail("Process timed out." + Environment.NewLine + pkOutput);
FileName = ffmpeg,
UseShellExecute = false,
RedirectStandardOutput = true,
RedirectStandardError = true,
CreateNoWindow = true,
ArgumentList = {
"-hide_banner",
"-i",
file
}
};
// we use error here, since we're not specify an output file, FFmpeg will report it as an error, but we don't care
string output = process.StandardOutput.ReadToEnd();
string error = process.StandardError.ReadToEnd();
process.Start();
return output?.EmptyAsNull() ?? error;
// Read asynchronously from both output and error streams
var outputTask = process.StandardOutput.ReadToEndAsync();
var errorTask = process.StandardError.ReadToEndAsync();
bool exited = process.WaitForExit(60000);
if (!exited)
{
process.Kill();
string pkOutput = errorTask.Result.EmptyAsNull() ?? outputTask.Result;
return Result<string>.Fail("Process timed out." + Environment.NewLine + pkOutput);
}
// Await both the output and error tasks
string output = outputTask.Result;
string error = errorTask.Result;
return output?.EmptyAsNull() ?? error;
}
catch (Exception ex)
{
@@ -93,18 +96,24 @@ public class FFmpegHelper(string ffmpeg, string ffprobe) : IFFmpegHelper
file
}
};
process.Start();
// Read asynchronously from both output and error streams
var outputTask = process.StandardOutput.ReadToEndAsync();
var errorTask = process.StandardError.ReadToEndAsync();
bool exited = process.WaitForExit(60000);
if (exited == false)
if (!exited)
{
process.Kill();
string pkOutput = process.StandardError.ReadToEnd()?.EmptyAsNull() ?? process.StandardOutput.ReadToEnd();
string pkOutput = errorTask.Result.EmptyAsNull() ?? outputTask.Result;
return Result<string>.Fail("Process timed out." + Environment.NewLine + pkOutput);
}
string output = process.StandardOutput.ReadToEnd();
string error = process.StandardError.ReadToEnd();
// Await both the output and error tasks
string output = outputTask.Result;
string error = errorTask.Result;
if (string.IsNullOrEmpty(error) == false)
return Result<string>.Fail($"Failed reading ffmpeg info: {error}");
@@ -116,4 +125,5 @@ public class FFmpegHelper(string ffmpeg, string ffprobe) : IFFmpegHelper
return Result<string>.Fail($"An error occurred: {ex.Message}");
}
}
}

View File

@@ -0,0 +1,68 @@
// using FileFlows.VideoNodes.FfmpegBuilderNodes.Models;
//
// namespace FileFlows.VideoNodes.FfmpegBuilderNodes;
//
// /// <summary>
// /// FFmpeg Builder flow element that burns in a subtitle
// /// </summary>
// public class FfmpegBuilderSubtitleBurnIn: TrackSelectorFlowElement<FfmpegBuilderSubtitleBurnIn>
// {
// /// <inheritdoc />
// public override string HelpUrl => "https://fileflows.com/docs/plugins/video-nodes/ffmpeg-builder/subtitle-burn-in";
// /// <inheritdoc />
// public override string Icon => "fas fa-fire";
// /// <inheritdoc />
// public override int Outputs => 2;
//
// /// <inheritdoc />
// public override int Execute(NodeParameters args)
// {
// // Select a single subtitle track to burn in
// var subtitleTrack = Model.SubtitleStreams.FirstOrDefault(track =>
// !track.Deleted && StreamMatches(track));
//
// if (subtitleTrack == null)
// {
// args.Logger?.ILog("No matching subtitle track found to burn in.");
// return 2; // No matching track, exit
// }
//
// args.Logger?.ILog($"Burning in subtitle track: {subtitleTrack}");
//
// // Build FFmpeg command for burning in the subtitle
// string subtitleFilter = BuildSubtitleFilter(subtitleTrack);
// if (string.IsNullOrEmpty(subtitleFilter))
// {
// args.Logger?.ILog("Failed to build subtitle filter for FFmpeg.");
// return 2; // Failed to create subtitle filter
// }
//
// Model.VideoStreams[0].Filter.Add(subtitleFilter); // Add the subtitle filter to the FFmpeg filter chain
// subtitleTrack.Deleted = true;
//
// return 1;
// }
//
// /// <summary>
// /// Builds the FFmpeg filter string for burning in the selected subtitle track.
// /// </summary>
// /// <param name="subtitleTrack">The subtitle track to burn in.</param>
// /// <returns>FFmpeg filter string for burning in the subtitle.</returns>
// private string BuildSubtitleFilter(FfmpegSubtitleStream subtitleTrack)
// {
// // For different subtitle codecs, we need different filter formats
// if (subtitleTrack.Codec.ToLowerInvariant() is "subrip" or "srt" or "ass")
// {
// // FFmpeg filter for SRT subtitles
// if (int.TryParse(subtitleTrack.Stream.IndexString.Split(':')[0], out int index) == false)
// return null;
// if (index < 0 || index > Model.InputFiles.Count)
// return null;
//
// return $"subtitles={Model.InputFiles[index].FileName}:{subtitleTrack.Stream.TypeIndex}";
// }
//
// // Unsupported subtitle format
// return null;
// }
// }

View File

@@ -0,0 +1,67 @@
// #if(DEBUG)
//
// using FileFlows.VideoNodes.FfmpegBuilderNodes;
// using Microsoft.VisualStudio.TestTools.UnitTesting;
// using VideoNodes.Tests;
//
// namespace FileFlows.VideoNodes.Tests.FfmpegBuilderTests;
//
// /// <summary>
// /// Tests the subtitle burning in
// /// </summary>
// [TestClass]
// public class FFmpegBuilder_SubtitleBurnInTests : VideoTestBase
// {
// NodeParameters args;
//
// /// <summary>
// /// Sets up the test environment before each test.
// /// Initializes video parameters and executes the video file setup.
// /// </summary>
// private void InitVideo(string file)
// {
// args = GetVideoNodeParameters(file);
// VideoFile vf = new VideoFile();
// vf.PreExecute(args);
// vf.Execute(args);
//
// FfmpegBuilderStart ffStart = new();
// ffStart.PreExecute(args);
// Assert.AreEqual(1, ffStart.Execute(args));
// }
//
// /// <summary>
// /// Burn In
// /// </summary>
// [TestMethod]
// public void BurnIn()
// {
// InitVideo(VideoSubtitles);
//
// var ffSubtitleBurnIn = new FfmpegBuilderSubtitleBurnIn()
// {
// CustomTrackSelection = true,
// TrackSelectionOptions = new()
// {
// new("Language", "English")
// }
// };
//
// ffSubtitleBurnIn.PreExecute(args);
// ffSubtitleBurnIn.Execute(args);
//
// var ffRemoveSubtitles = new FfmpegBuilderAudioTrackRemover();
// ffRemoveSubtitles.RemoveAll = true;
// ffRemoveSubtitles.StreamType = "Subtitle";
// ffRemoveSubtitles.PreExecute(args);
// ffRemoveSubtitles.Execute(args);
//
// var ffExecutor = new FfmpegBuilderExecutor();
// ffExecutor.PreExecute(args);
// int result = ffExecutor.Execute(args);
//
// Assert.AreEqual(1, result);
// }
// }
//
// #endif