mirror of
https://github.com/revenz/FileFlowsPlugins.git
synced 2025-12-30 23:09:31 -06:00
FF-1255 - added ffmpeg model logging
This commit is contained in:
@@ -44,8 +44,30 @@ namespace FileFlows.VideoNodes.FfmpegBuilderNodes
|
||||
if(this is FfmpegBuilderStart == false && Model == null)
|
||||
throw new Exception("FFMPEG Builder Model not set, you must add and use the \"FFMPEG Builder Start\" node first");
|
||||
|
||||
if (this is FfmpegBuilderStart == false && Model.VideoInfo == null)
|
||||
throw new Exception("FFMPEG Builder VideoInfo is null");
|
||||
if (this is FfmpegBuilderStart == false)
|
||||
{
|
||||
if (Model.VideoInfo == null)
|
||||
throw new Exception("FFMPEG Builder VideoInfo is null");
|
||||
string header = "------------------------ Starting FFmpeg Builder Model ------------------------";
|
||||
args.Logger?.ILog(header);
|
||||
foreach (var stream in Model.VideoStreams ?? new List<FfmpegVideoStream>())
|
||||
{
|
||||
string line = "| Video Stream: " + stream;
|
||||
args.Logger?.ILog(line + new string(' ', Math.Max(1, header.Length - line.Length - 1)) + '|');
|
||||
}
|
||||
foreach (var stream in Model.AudioStreams ?? new List<FfmpegAudioStream>())
|
||||
{
|
||||
string line = "| Audio Stream: " + stream;
|
||||
args.Logger?.ILog(line + new string(' ', Math.Max(1, header.Length - line.Length - 1)) + '|');
|
||||
}
|
||||
foreach (var stream in Model.SubtitleStreams ?? new List<FfmpegSubtitleStream>())
|
||||
{
|
||||
string line = "| Subtitle Stream: " + stream;
|
||||
args.Logger?.ILog(line + new string(' ', Math.Max(1, header.Length - line.Length - 1)) + '|');
|
||||
}
|
||||
|
||||
args.Logger?.ILog(new string('-', header.Length));
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -136,7 +136,15 @@ public class FfmpegBuilderTrackSorter : FfmpegBuilderNode
|
||||
// Replace the unsorted items with the sorted ones
|
||||
for (int i = 0; i < streams.Count; i++)
|
||||
{
|
||||
changes |= streams[i] != orderedStreams[i];
|
||||
bool newDefault = i == 0;
|
||||
bool changed = streams[i] != orderedStreams[i] || orderedStreams[i].IsDefault != newDefault;
|
||||
streams[i].IsDefault = newDefault;
|
||||
if (changed)
|
||||
{
|
||||
streams[i].ForcedChange = true;
|
||||
orderedStreams[i].ForcedChange = true;
|
||||
}
|
||||
changes |= changed;
|
||||
streams[i] = orderedStreams[i];
|
||||
}
|
||||
|
||||
@@ -145,12 +153,13 @@ public class FfmpegBuilderTrackSorter : FfmpegBuilderNode
|
||||
|
||||
internal List<T> SortStreams<T>(NodeParameters args, List<T> streams) where T : FfmpegStream
|
||||
{
|
||||
if (streams?.Any() != true || Sorters?.Any() != true)
|
||||
if (streams?.Any() != true || Sorters?.Any() != true || streams.Count == 1)
|
||||
return streams;
|
||||
|
||||
return streams.OrderBy(stream =>
|
||||
{
|
||||
var sortKey = GetSortKey(args, stream);
|
||||
// we add a 1 to deleted ones first, so they are always sorted after non-deleted ones
|
||||
var sortKey = (stream.Deleted ? "1|" : "0|") + GetSortKey(args, stream);
|
||||
args.Logger?.ILog(stream.ToString() + " -> sort key = " + sortKey);
|
||||
return sortKey;
|
||||
})
|
||||
@@ -311,8 +320,8 @@ public class FfmpegBuilderTrackSorter : FfmpegBuilderNode
|
||||
// Make an educated guess for Mbps to kbps conversion
|
||||
return adjustedComparison[..^4] switch
|
||||
{
|
||||
{ } value when double.TryParse(value, out var numericValue) => (numericValue * 1_000_000).ToString(
|
||||
CultureInfo.InvariantCulture),
|
||||
{ } value when double.TryParse(value, out var numericValue) => (numericValue * 1_000_000)
|
||||
.ToString(CultureInfo.InvariantCulture),
|
||||
_ => comparisonValue
|
||||
};
|
||||
}
|
||||
@@ -321,32 +330,84 @@ public class FfmpegBuilderTrackSorter : FfmpegBuilderNode
|
||||
// Make an educated guess for kbps to bps conversion
|
||||
return adjustedComparison[..^4] switch
|
||||
{
|
||||
{ } value when double.TryParse(value, out var numericValue) => (numericValue * 1_000).ToString(
|
||||
CultureInfo.InvariantCulture),
|
||||
{ } value when double.TryParse(value, out var numericValue) => (numericValue * 1_000)
|
||||
.ToString(CultureInfo.InvariantCulture),
|
||||
_ => comparisonValue
|
||||
};
|
||||
}
|
||||
if (adjustedComparison.EndsWith("kb"))
|
||||
{
|
||||
return adjustedComparison[..^2] switch
|
||||
{
|
||||
{ } value when double.TryParse(value, out var numericValue) => (numericValue * 1_000 )
|
||||
.ToString(CultureInfo.InvariantCulture),
|
||||
_ => comparisonValue
|
||||
};
|
||||
}
|
||||
if (adjustedComparison.EndsWith("mb"))
|
||||
{
|
||||
return adjustedComparison[..^2] switch
|
||||
{
|
||||
{ } value when double.TryParse(value, out var numericValue) => (numericValue * 1_000_000 )
|
||||
.ToString(CultureInfo.InvariantCulture),
|
||||
_ => comparisonValue
|
||||
};
|
||||
}
|
||||
if (adjustedComparison.EndsWith("gb"))
|
||||
{
|
||||
// Make an educated guess for GB to bytes conversion
|
||||
return adjustedComparison[..^2] switch
|
||||
{
|
||||
{ } value when double.TryParse(value, out var numericValue) => (numericValue * Math.Pow(1024, 3))
|
||||
{ } value when double.TryParse(value, out var numericValue) => (numericValue * 1_000_000_000 )
|
||||
.ToString(CultureInfo.InvariantCulture),
|
||||
_ => comparisonValue
|
||||
};
|
||||
}
|
||||
if (adjustedComparison.EndsWith("tb"))
|
||||
{
|
||||
// Make an educated guess for TB to bytes conversion
|
||||
return adjustedComparison[..^2] switch
|
||||
{
|
||||
{ } value when double.TryParse(value, out var numericValue) => (numericValue * Math.Pow(1024, 4))
|
||||
{ } value when double.TryParse(value, out var numericValue) => (numericValue * 1_000_000_000_000)
|
||||
.ToString(CultureInfo.InvariantCulture),
|
||||
_ => comparisonValue
|
||||
};
|
||||
}
|
||||
|
||||
if (adjustedComparison.EndsWith("kib"))
|
||||
{
|
||||
return adjustedComparison[..^3] switch
|
||||
{
|
||||
{ } value when double.TryParse(value, out var numericValue) => (numericValue * 1_024 )
|
||||
.ToString(CultureInfo.InvariantCulture),
|
||||
_ => comparisonValue
|
||||
};
|
||||
}
|
||||
if (adjustedComparison.EndsWith("mib"))
|
||||
{
|
||||
return adjustedComparison[..^3] switch
|
||||
{
|
||||
{ } value when double.TryParse(value, out var numericValue) => (numericValue * 1_048_576 )
|
||||
.ToString(CultureInfo.InvariantCulture),
|
||||
_ => comparisonValue
|
||||
};
|
||||
}
|
||||
if (adjustedComparison.EndsWith("gib"))
|
||||
{
|
||||
return adjustedComparison[..^3] switch
|
||||
{
|
||||
{ } value when double.TryParse(value, out var numericValue) => (numericValue * 1_099_511_627_776 )
|
||||
.ToString(CultureInfo.InvariantCulture),
|
||||
_ => comparisonValue
|
||||
};
|
||||
}
|
||||
if (adjustedComparison.EndsWith("tib"))
|
||||
{
|
||||
return adjustedComparison[..^3] switch
|
||||
{
|
||||
{ } value when double.TryParse(value, out var numericValue) => (numericValue * 1_000_000_000_000)
|
||||
.ToString(CultureInfo.InvariantCulture),
|
||||
_ => comparisonValue
|
||||
};
|
||||
}
|
||||
return comparisonValue;
|
||||
}
|
||||
|
||||
@@ -420,6 +481,7 @@ public class FfmpegBuilderTrackSorter : FfmpegBuilderNode
|
||||
case "==":
|
||||
return Math.Abs(Convert.ToDouble(value) - Convert.ToDouble(AdjustComparisonValue(operation[2..].Trim()))) < 0.05f;
|
||||
case "!=":
|
||||
case "<>":
|
||||
return Math.Abs(Convert.ToDouble(value) - Convert.ToDouble(AdjustComparisonValue(operation[2..].Trim()))) > 0.05f;
|
||||
}
|
||||
|
||||
|
||||
@@ -99,7 +99,7 @@
|
||||
public override string ToString()
|
||||
{
|
||||
if (Stream != null)
|
||||
return Stream.ToString();
|
||||
return Stream.ToString() + (Deleted ? " / Deleted" : "");
|
||||
// can be null in unit tests
|
||||
return string.Join(" / ", new string[]
|
||||
{
|
||||
@@ -107,7 +107,8 @@
|
||||
Language,
|
||||
Codec,
|
||||
Title,
|
||||
Channels > 0 ? Channels.ToString("0.0") : null
|
||||
Channels > 0 ? Channels.ToString("0.0") : null,
|
||||
Deleted ? "Deleted" : null
|
||||
}.Where(x => string.IsNullOrWhiteSpace(x) == false));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -92,14 +92,16 @@ public class FfmpegSubtitleStream : FfmpegStream
|
||||
public override string ToString()
|
||||
{
|
||||
if (Stream != null)
|
||||
return Stream.ToString();
|
||||
return Stream.ToString() + (Deleted ? " / Deleted" : "");
|
||||
|
||||
// can be null in unit tests
|
||||
return string.Join(" / ", new string[]
|
||||
{
|
||||
Index.ToString(),
|
||||
Language,
|
||||
Codec,
|
||||
Title
|
||||
Title,
|
||||
Deleted ? "Deleted" : null
|
||||
}.Where(x => string.IsNullOrWhiteSpace(x) == false));
|
||||
}
|
||||
}
|
||||
@@ -1,115 +1,135 @@
|
||||
namespace FileFlows.VideoNodes.FfmpegBuilderNodes.Models
|
||||
namespace FileFlows.VideoNodes.FfmpegBuilderNodes.Models;
|
||||
|
||||
public class FfmpegVideoStream : FfmpegStream
|
||||
{
|
||||
public class FfmpegVideoStream : FfmpegStream
|
||||
public VideoStream Stream { get; set; }
|
||||
|
||||
private List<string> _Filter = new List<string>();
|
||||
public List<string> Filter
|
||||
{
|
||||
public VideoStream Stream { get; set; }
|
||||
|
||||
private List<string> _Filter = new List<string>();
|
||||
public List<string> Filter
|
||||
get => _Filter;
|
||||
set
|
||||
{
|
||||
get => _Filter;
|
||||
set
|
||||
{
|
||||
_Filter = value ?? new List<string>();
|
||||
}
|
||||
_Filter = value ?? new List<string>();
|
||||
}
|
||||
private List<string> _OptionalFilter = new List<string>();
|
||||
}
|
||||
private List<string> _OptionalFilter = new List<string>();
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets filters that will process but only if processing is needed, these won't trigger a has changed
|
||||
/// value of the video file by themselves
|
||||
/// </summary>
|
||||
public List<string> OptionalFilter
|
||||
/// <summary>
|
||||
/// Gets or sets filters that will process but only if processing is needed, these won't trigger a has changed
|
||||
/// value of the video file by themselves
|
||||
/// </summary>
|
||||
public List<string> OptionalFilter
|
||||
{
|
||||
get => _OptionalFilter;
|
||||
set
|
||||
{
|
||||
get => _OptionalFilter;
|
||||
set
|
||||
{
|
||||
_OptionalFilter = value ?? new List<string>();
|
||||
}
|
||||
_OptionalFilter = value ?? new List<string>();
|
||||
}
|
||||
}
|
||||
|
||||
private List<string> _EncodingParameters = new List<string>();
|
||||
public List<string> EncodingParameters
|
||||
private List<string> _EncodingParameters = new List<string>();
|
||||
public List<string> EncodingParameters
|
||||
{
|
||||
get => _EncodingParameters;
|
||||
set
|
||||
{
|
||||
get => _EncodingParameters;
|
||||
set
|
||||
{
|
||||
_EncodingParameters = value ?? new List<string>();
|
||||
}
|
||||
_EncodingParameters = value ?? new List<string>();
|
||||
}
|
||||
// private List<string> _OptionalEncodingParameters = new List<string>();
|
||||
// /// <summary>
|
||||
// /// Gets or sets encoding paramaters that will process but only if processing is needed, these won't trigger a has changed
|
||||
// /// value of the video file by themselves
|
||||
// /// </summary>
|
||||
// public List<string> OptionalEncodingParameters
|
||||
// {
|
||||
// get => _OptionalEncodingParameters;
|
||||
// set
|
||||
// {
|
||||
// _OptionalEncodingParameters = value ?? new List<string>();
|
||||
// }
|
||||
// }
|
||||
private List<string> _AdditionalParameters = new List<string>();
|
||||
public List<string> AdditionalParameters
|
||||
}
|
||||
// private List<string> _OptionalEncodingParameters = new List<string>();
|
||||
// /// <summary>
|
||||
// /// Gets or sets encoding paramaters that will process but only if processing is needed, these won't trigger a has changed
|
||||
// /// value of the video file by themselves
|
||||
// /// </summary>
|
||||
// public List<string> OptionalEncodingParameters
|
||||
// {
|
||||
// get => _OptionalEncodingParameters;
|
||||
// set
|
||||
// {
|
||||
// _OptionalEncodingParameters = value ?? new List<string>();
|
||||
// }
|
||||
// }
|
||||
private List<string> _AdditionalParameters = new List<string>();
|
||||
public List<string> AdditionalParameters
|
||||
{
|
||||
get => _AdditionalParameters;
|
||||
set
|
||||
{
|
||||
get => _AdditionalParameters;
|
||||
set
|
||||
{
|
||||
_AdditionalParameters = value ?? new List<string>();
|
||||
}
|
||||
_AdditionalParameters = value ?? new List<string>();
|
||||
}
|
||||
public override bool HasChange => EncodingParameters.Any() || Filter.Any() || AdditionalParameters.Any();
|
||||
}
|
||||
public override bool HasChange => EncodingParameters.Any() || Filter.Any() || AdditionalParameters.Any();
|
||||
|
||||
|
||||
public override string[] GetParameters(GetParametersArgs args)
|
||||
public override string[] GetParameters(GetParametersArgs args)
|
||||
{
|
||||
if (Deleted)
|
||||
return new string[] { };
|
||||
|
||||
var results = new List<string> { "-map", "0:v:{sourceTypeIndex}" };
|
||||
if (Filter.Any() == false && EncodingParameters.Any() == false && AdditionalParameters.Any() == false)
|
||||
{
|
||||
if (Deleted)
|
||||
return new string[] { };
|
||||
|
||||
var results = new List<string> { "-map", "0:v:{sourceTypeIndex}" };
|
||||
if (Filter.Any() == false && EncodingParameters.Any() == false && AdditionalParameters.Any() == false)
|
||||
results.Add("-c:v:{index}");
|
||||
results.Add("copy");
|
||||
return results.ToArray();
|
||||
}
|
||||
else
|
||||
{
|
||||
if (EncodingParameters.Any())
|
||||
{
|
||||
results.Add("-c:v:{index}");
|
||||
results.Add("copy");
|
||||
return results.ToArray();
|
||||
results.Add("-c:v:" + Stream.TypeIndex);
|
||||
results.AddRange(EncodingParameters.Select(x => x.Replace("{index}", args.OutputTypeIndex.ToString())));
|
||||
// if(OptionalEncodingParameters.Any())
|
||||
// results.AddRange(OptionalEncodingParameters.Select(x => x.Replace("{index}", args.OutputTypeIndex.ToString())));
|
||||
}
|
||||
else
|
||||
{
|
||||
if (EncodingParameters.Any())
|
||||
{
|
||||
results.Add("-c:v:" + Stream.TypeIndex);
|
||||
results.AddRange(EncodingParameters.Select(x => x.Replace("{index}", args.OutputTypeIndex.ToString())));
|
||||
// if(OptionalEncodingParameters.Any())
|
||||
// results.AddRange(OptionalEncodingParameters.Select(x => x.Replace("{index}", args.OutputTypeIndex.ToString())));
|
||||
}
|
||||
else
|
||||
{
|
||||
// we need to set this codec since a filter will be applied, so we cant copy it.
|
||||
//results.Add("copy");
|
||||
}
|
||||
if (AdditionalParameters.Any())
|
||||
results.AddRange(AdditionalParameters.Select(x => x.Replace("{index}", args.OutputTypeIndex.ToString())));
|
||||
|
||||
if (Filter.Any() || OptionalFilter.Any())
|
||||
{
|
||||
results.Add("-filter:v:" + args.OutputTypeIndex);
|
||||
results.Add(string.Join(", ", Filter.Concat(OptionalFilter)).Replace("{index}", args.OutputTypeIndex.ToString()));
|
||||
}
|
||||
// we need to set this codec since a filter will be applied, so we cant copy it.
|
||||
//results.Add("copy");
|
||||
}
|
||||
if (AdditionalParameters.Any())
|
||||
results.AddRange(AdditionalParameters.Select(x => x.Replace("{index}", args.OutputTypeIndex.ToString())));
|
||||
|
||||
if (string.IsNullOrWhiteSpace(this.Title) == false)
|
||||
if (Filter.Any() || OptionalFilter.Any())
|
||||
{
|
||||
results.Add($"-metadata:s:v:{args.OutputTypeIndex}");
|
||||
results.Add($"title={(this.Title == FfmpegStream.REMOVED ? "" : this.Title)}");
|
||||
results.Add("-filter:v:" + args.OutputTypeIndex);
|
||||
results.Add(string.Join(", ", Filter.Concat(OptionalFilter)).Replace("{index}", args.OutputTypeIndex.ToString()));
|
||||
}
|
||||
|
||||
if (Metadata.Any())
|
||||
{
|
||||
results.AddRange(Metadata.Select(x => x.Replace("{index}", args.OutputTypeIndex.ToString())));
|
||||
}
|
||||
|
||||
return results.ToArray();
|
||||
}
|
||||
|
||||
if (string.IsNullOrWhiteSpace(this.Title) == false)
|
||||
{
|
||||
results.Add($"-metadata:s:v:{args.OutputTypeIndex}");
|
||||
results.Add($"title={(this.Title == FfmpegStream.REMOVED ? "" : this.Title)}");
|
||||
}
|
||||
|
||||
if (Metadata.Any())
|
||||
{
|
||||
results.AddRange(Metadata.Select(x => x.Replace("{index}", args.OutputTypeIndex.ToString())));
|
||||
}
|
||||
|
||||
return results.ToArray();
|
||||
}
|
||||
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// Converts the object to a string
|
||||
/// </summary>
|
||||
/// <returns>the string representation of stream</returns>
|
||||
public override string ToString()
|
||||
{
|
||||
if (Stream != null)
|
||||
return Stream.ToString() + (Deleted ? " / Deleted" : "");
|
||||
|
||||
// can be null in unit tests
|
||||
return string.Join(" / ", new string[]
|
||||
{
|
||||
Index.ToString(),
|
||||
Codec,
|
||||
Title,
|
||||
Deleted ? "Deleted" : null
|
||||
}.Where(x => string.IsNullOrWhiteSpace(x) == false));
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user