mirror of
https://github.com/revenz/FileFlowsPlugins.git
synced 2026-01-06 07:39:30 -06:00
FF-1279 - added MXF container
This commit is contained in:
@@ -27,17 +27,64 @@ public class FfmpegBuilderAudioConverter : FfmpegBuilderNode
|
||||
{
|
||||
new () { Label = "AAC", Value = "aac"},
|
||||
new () { Label = "AC3", Value = "ac3"},
|
||||
new () { Label = "DTS", Value = "dts" },
|
||||
new () { Label = "EAC3", Value = "eac3" },
|
||||
new () { Label = "FLAC", Value ="flac" },
|
||||
new () { Label = "MP3", Value = "mp3"},
|
||||
new () { Label = "PCM", Value ="pcm" },
|
||||
new () { Label = "OPUS", Value = "opus"},
|
||||
new () { Label = "Vorbis", Value ="libvorbis" },
|
||||
};
|
||||
}
|
||||
return _CodecOptions;
|
||||
}
|
||||
}
|
||||
|
||||
[DefaultValue("pcm_s16le")]
|
||||
[Select(nameof(PcmFormats), 2)]
|
||||
[ConditionEquals(nameof(Codec), "pcm")]
|
||||
public string PcmFormat { get; set; }
|
||||
|
||||
private static List<ListOption> _PcmFormats;
|
||||
public static List<ListOption> PcmFormats
|
||||
{
|
||||
get
|
||||
{
|
||||
if (_PcmFormats == null)
|
||||
{
|
||||
_PcmFormats = new List<ListOption>
|
||||
{
|
||||
new () { Label = "Common", Value = "###GROUP###" },
|
||||
new () { Label = "Signed 16-bit Little Endian", Value = "pcm_s16le" },
|
||||
new () { Label = "Signed 24-bit Little Endian", Value = "pcm_s24le"},
|
||||
|
||||
new () { Label = "Signed", Value = "###GROUP###" },
|
||||
new () { Label = "8-bit", Value = "pcm_s8"},
|
||||
new () { Label = "16-bit Little Endian", Value = "pcm_s16le" },
|
||||
new () { Label = "16-bit Big Endian", Value = "pcm_s16be"},
|
||||
new () { Label = "24-bit Little Endian", Value = "pcm_s24le"},
|
||||
new () { Label = "24-bit Big Endian", Value = "pcm_s24be"},
|
||||
new () { Label = "32-bit Little Endian", Value = "pcm_s32le"},
|
||||
new () { Label = "32-bit Big Endian", Value = "pcm_s32be"},
|
||||
new () { Label = "64-bit Little Endian", Value = "pcm_s64le"},
|
||||
new () { Label = "64-bit Big Endian", Value = "pcm_s64be"},
|
||||
new () { Label = "Floating-point", Value = "###GROUP###" },
|
||||
new () { Label = "32-bit Little Endian", Value = "pcm_f32le"},
|
||||
new () { Label = "32-bit Big Endian", Value = "pcm_f32be"},
|
||||
new () { Label = "16-bit Little Endian", Value = "pcm_f16le"},
|
||||
new () { Label = "24-bit Little Endian", Value = "pcm_f24le"},
|
||||
new () { Label = "64-bit Little Endian", Value = "pcm_f64le"},
|
||||
new () { Label = "64-bit Big Endian", Value = "pcm_f64be"},
|
||||
};
|
||||
|
||||
}
|
||||
return _PcmFormats;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
[DefaultValue(0)]
|
||||
[Select(nameof(ChannelsOptions), 2)]
|
||||
[Select(nameof(ChannelsOptions), 3)]
|
||||
public float Channels { get; set; }
|
||||
|
||||
private static List<ListOption> _ChannelsOptions;
|
||||
@@ -60,7 +107,7 @@ public class FfmpegBuilderAudioConverter : FfmpegBuilderNode
|
||||
}
|
||||
}
|
||||
|
||||
[Select(nameof(BitrateOptions), 3)]
|
||||
[Select(nameof(BitrateOptions), 4)]
|
||||
public int Bitrate { get; set; }
|
||||
|
||||
private static List<ListOption> _BitrateOptions;
|
||||
@@ -85,13 +132,13 @@ public class FfmpegBuilderAudioConverter : FfmpegBuilderNode
|
||||
}
|
||||
|
||||
|
||||
[TextVariable(4)]
|
||||
[TextVariable(5)]
|
||||
public string Pattern { get; set; }
|
||||
|
||||
[Boolean(5)]
|
||||
[Boolean(6)]
|
||||
public bool NotMatching { get; set; }
|
||||
|
||||
[Boolean(6)]
|
||||
[Boolean(7)]
|
||||
public bool UseLanguageCode { get; set; }
|
||||
|
||||
public override int Execute(NodeParameters args)
|
||||
@@ -157,7 +204,11 @@ public class FfmpegBuilderAudioConverter : FfmpegBuilderNode
|
||||
/// <returns>if the stream had to be converted or not</returns>
|
||||
private bool ConvertTrack(NodeParameters args, FfmpegAudioStream stream)
|
||||
{
|
||||
bool codecSame = stream.Stream.Codec?.ToLower() == Codec?.ToLower();
|
||||
string codec = Codec?.ToLowerInvariant() ?? string.Empty;
|
||||
if (codec == "pcm")
|
||||
codec = PcmFormat;
|
||||
|
||||
bool codecSame = stream.Stream.Codec?.ToLowerInvariant() == codec;
|
||||
bool channelsSame = Channels == 0 || Math.Abs(Channels - stream.Stream.Channels) < 0.05f;
|
||||
bool bitrateSame = Bitrate < 2 || stream.Stream.Bitrate == 0 ||
|
||||
Math.Abs(stream.Stream.Bitrate - Bitrate) < 0.05f;
|
||||
@@ -170,7 +221,7 @@ public class FfmpegBuilderAudioConverter : FfmpegBuilderNode
|
||||
|
||||
stream.Codec = Codec.ToLowerInvariant();
|
||||
|
||||
stream.EncodingParameters.AddRange(FfmpegBuilderAudioAddTrack.GetNewAudioTrackParameters(args, stream, Codec, Channels, Bitrate, 0));
|
||||
stream.EncodingParameters.AddRange(FfmpegBuilderAudioAddTrack.GetNewAudioTrackParameters(args, stream, codec, Channels, Bitrate, 0));
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -145,7 +145,13 @@ public class FfmpegBuilderTrackSorter : FfmpegBuilderNode
|
||||
if (changed)
|
||||
{
|
||||
streams[i].ForcedChange = true;
|
||||
orderedStreams[i].ForcedChange = true;
|
||||
args.Logger?.ILog("Stream has change[1]: " + streams[i]);
|
||||
|
||||
if (streams[i] != orderedStreams[i])
|
||||
{
|
||||
orderedStreams[i].ForcedChange = true;
|
||||
args.Logger?.ILog("Stream has change[2]: " + orderedStreams[i]);
|
||||
}
|
||||
}
|
||||
changes |= changed;
|
||||
streams[i] = orderedStreams[i];
|
||||
|
||||
@@ -98,8 +98,8 @@
|
||||
/// <returns>the string representation of stream</returns>
|
||||
public override string ToString()
|
||||
{
|
||||
if (Stream != null)
|
||||
return Stream.ToString() + (Deleted ? " / Deleted" : "");
|
||||
// if (Stream != null)
|
||||
// return Stream.ToString() + (Deleted ? " / Deleted" : "");
|
||||
// can be null in unit tests
|
||||
return string.Join(" / ", new string[]
|
||||
{
|
||||
@@ -108,7 +108,9 @@
|
||||
Codec,
|
||||
Title,
|
||||
Channels > 0 ? Channels.ToString("0.0") : null,
|
||||
Deleted ? "Deleted" : null
|
||||
IsDefault ? "Default" : null,
|
||||
Deleted ? "Deleted" : null,
|
||||
HasChange ? "Changed" : null
|
||||
}.Where(x => string.IsNullOrWhiteSpace(x) == false));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -97,6 +97,7 @@
|
||||
Language = item.stream.Language,
|
||||
Stream = item.stream,
|
||||
Channels = item.stream.Channels,
|
||||
IsDefault = item.stream.Default,
|
||||
Codec = item.stream.Codec
|
||||
});
|
||||
}
|
||||
@@ -115,9 +116,15 @@
|
||||
}
|
||||
|
||||
if(info.FileName.ToLower().EndsWith(".mp4"))
|
||||
model.Extension = info.FileName.Substring(info.FileName.LastIndexOf(".") + 1);
|
||||
if (info.FileName.ToLower().EndsWith(".mkv"))
|
||||
model.Extension = info.FileName.Substring(info.FileName.LastIndexOf(".") + 1);
|
||||
model.Extension = info.FileName[(info.FileName.LastIndexOf(".", StringComparison.Ordinal) + 1)..];
|
||||
else if (info.FileName.ToLower().EndsWith(".mkv"))
|
||||
model.Extension = info.FileName[(info.FileName.LastIndexOf(".", StringComparison.Ordinal) + 1)..];
|
||||
else if (info.FileName.ToLower().EndsWith(".mov"))
|
||||
model.Extension = info.FileName[(info.FileName.LastIndexOf(".", StringComparison.Ordinal) + 1)..];
|
||||
else if (info.FileName.ToLower().EndsWith(".mxf"))
|
||||
model.Extension = info.FileName[(info.FileName.LastIndexOf(".", StringComparison.Ordinal) + 1)..];
|
||||
else if (info.FileName.ToLower().EndsWith(".webm"))
|
||||
model.Extension = info.FileName[(info.FileName.LastIndexOf(".", StringComparison.Ordinal) + 1)..];
|
||||
|
||||
return model;
|
||||
}
|
||||
|
||||
@@ -91,8 +91,8 @@ public class FfmpegSubtitleStream : FfmpegStream
|
||||
/// <returns>the string representation of stream</returns>
|
||||
public override string ToString()
|
||||
{
|
||||
if (Stream != null)
|
||||
return Stream.ToString() + (Deleted ? " / Deleted" : "");
|
||||
// if (Stream != null)
|
||||
// return Stream.ToString() + (Deleted ? " / Deleted" : "");
|
||||
|
||||
// can be null in unit tests
|
||||
return string.Join(" / ", new string[]
|
||||
@@ -101,7 +101,9 @@ public class FfmpegSubtitleStream : FfmpegStream
|
||||
Language,
|
||||
Codec,
|
||||
Title,
|
||||
Deleted ? "Deleted" : null
|
||||
IsDefault ? "Default" : null,
|
||||
Deleted ? "Deleted" : null,
|
||||
HasChange ? "Changed" : null
|
||||
}.Where(x => string.IsNullOrWhiteSpace(x) == false));
|
||||
}
|
||||
}
|
||||
@@ -120,8 +120,8 @@ public class FfmpegVideoStream : FfmpegStream
|
||||
/// <returns>the string representation of stream</returns>
|
||||
public override string ToString()
|
||||
{
|
||||
if (Stream != null)
|
||||
return Stream.ToString() + (Deleted ? " / Deleted" : "");
|
||||
// if (Stream != null)
|
||||
// return Stream.ToString() + (Deleted ? " / Deleted" : "");
|
||||
|
||||
// can be null in unit tests
|
||||
return string.Join(" / ", new string[]
|
||||
@@ -129,7 +129,8 @@ public class FfmpegVideoStream : FfmpegStream
|
||||
Index.ToString(),
|
||||
Codec,
|
||||
Title,
|
||||
Deleted ? "Deleted" : null
|
||||
Deleted ? "Deleted" : null,
|
||||
HasChange ? "Changed" : null
|
||||
}.Where(x => string.IsNullOrWhiteSpace(x) == false));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,24 @@
|
||||
namespace FileFlows.VideoNodes.FfmpegBuilderNodes;
|
||||
|
||||
/// <summary>
|
||||
/// Remuxes a file to the MXF container
|
||||
/// </summary>
|
||||
public class FfmpegBuilderRemuxToMxf : FfmpegBuilderNode
|
||||
{
|
||||
/// <summary>
|
||||
/// Gets or sets the URL to the helper page
|
||||
/// </summary>
|
||||
public override string HelpUrl => "https://fileflows.com/docs/plugins/video-nodes/ffmpeg-builder/remux-to-mxf";
|
||||
|
||||
/// <summary>
|
||||
/// Gets that this is an enterprise flow element
|
||||
/// </summary>
|
||||
public override bool Enterprise => true;
|
||||
|
||||
/// <inheritdoc />
|
||||
public override int Execute(NodeParameters args)
|
||||
{
|
||||
this.Model.Extension = "mxf";
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
@@ -176,6 +176,11 @@ public class AudioStream : VideoFileStream
|
||||
/// </summary>
|
||||
public int SampleRate { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// If this is a the default audio track
|
||||
/// </summary>
|
||||
public bool Default { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Converts the steam to a string
|
||||
/// </summary>
|
||||
@@ -187,7 +192,8 @@ public class AudioStream : VideoFileStream
|
||||
Language,
|
||||
Codec,
|
||||
Title,
|
||||
Channels > 0 ? Channels.ToString("0.0") : null
|
||||
Channels > 0 ? Channels.ToString("0.0") : null,
|
||||
Default ? "Default" : null
|
||||
}.Where(x => string.IsNullOrWhiteSpace(x) == false));
|
||||
}
|
||||
|
||||
|
||||
@@ -315,6 +315,7 @@ public class VideoInfoHelper
|
||||
audio.Codec = audio.Codec[..^1].Trim();
|
||||
|
||||
audio.Language = GetLanguage(line);
|
||||
audio.Default = info.Contains("(default)");
|
||||
// if (info.IndexOf("0 channels", StringComparison.Ordinal) >= 0)
|
||||
// {
|
||||
// logger?.WLog("Stream contained '0 Channels'");
|
||||
|
||||
@@ -175,6 +175,8 @@
|
||||
"Fields": {
|
||||
"Channels": "Channels",
|
||||
"Channels-Help": "The number of channels this new audio track will be.\nIf you specify more channels than the source, FFMPEG will automatically upmix it.\nIf you specify fewer channels than the source, FFMPEG will automatically down mix it.",
|
||||
"PcmFormat": "Format",
|
||||
"PcmFormat-Help": "The PCM format to use for encoding PCM audio.",
|
||||
"Bitrate": "Bitrate",
|
||||
"Bitrate-Help": "Bitrate of the audio track",
|
||||
"Codec": "Codec",
|
||||
@@ -470,6 +472,8 @@
|
||||
"1": "Video set to use prores"
|
||||
},
|
||||
"Fields": {
|
||||
"Encoder": "Encoder",
|
||||
"Encoder-Help": "Which FFmpeg prores encoder to use.",
|
||||
"Quality": "Quality",
|
||||
"Quality-Help": "0 for maximum quality, 32 for minimum quality. 9 to 13 are good values to use.",
|
||||
"Profile": "Profile",
|
||||
@@ -490,6 +494,13 @@
|
||||
"1": "FFMPEG Builder set to remux to MKV"
|
||||
}
|
||||
},
|
||||
"FfmpegBuilderRemuxToMxf": {
|
||||
"Label": "FFMPEG Builder: Remux to MXF",
|
||||
"Description": "Remuxes a video file into a MXF container.",
|
||||
"Outputs": {
|
||||
"1": "FFMPEG Builder set to remux to MXF"
|
||||
}
|
||||
},
|
||||
"FfmpegBuilderRemuxToMP4": {
|
||||
"Label": "FFMPEG Builder: Remux to MP4",
|
||||
"Description": "Remuxes a video file into a MP4 container.",
|
||||
|
||||
@@ -90,11 +90,48 @@ namespace FileFlows.VideoNodes
|
||||
var videoInfo = new VideoInfoHelper(ffmpegExe, args.Logger).Read(outputFile);
|
||||
SetVideoInfo(args, videoInfo, this.Variables ?? new Dictionary<string, object>());
|
||||
}
|
||||
else if (success.successs == false)
|
||||
{
|
||||
// look for known error messages
|
||||
var lines = success.output.Split(new string[] { "\r\n", "\n" }, StringSplitOptions.RemoveEmptyEntries)
|
||||
.ToArray();
|
||||
|
||||
if (lines.Count() >= 50) {
|
||||
lines = lines.TakeLast(50).ToArray();
|
||||
}
|
||||
|
||||
string line;
|
||||
if (HasLine(lines, "is not supported by the bitstream filter", out line))
|
||||
{
|
||||
// get that line, more efficiently that twice
|
||||
int codecIndex = line.IndexOf("Codec", StringComparison.InvariantCulture);
|
||||
if (codecIndex > 0)
|
||||
line = line[codecIndex..];
|
||||
int periodIndex = line.IndexOf(".", StringComparison.InvariantCulture);
|
||||
if (periodIndex > 0)
|
||||
line = line[..periodIndex];
|
||||
args.FailureReason = line;
|
||||
}
|
||||
else if (HasLine(lines, "codec not currently supported in container", out line))
|
||||
{
|
||||
args.FailureReason = "Codec not currently supported in container";
|
||||
}
|
||||
else if (HasLine(lines, "encoding with ProRes Proxy/LT/422/422 HQ (apco, apcs, apcn, ap4h) profile, need YUV422P10 input", out line))
|
||||
{
|
||||
args.FailureReason = "Encoding with ProRes Proxy/LT/422/422 HQ (apco, apcs, apcn, ap4h) profile, need YUV422P10 input";
|
||||
}
|
||||
}
|
||||
Encoder.AtTime -= AtTimeEvent;
|
||||
Encoder.OnStatChange -= EncoderOnOnStatChange;
|
||||
Encoder = null;
|
||||
output = success.output;
|
||||
return success.successs;
|
||||
|
||||
bool HasLine(string[] lines, string text, out string line)
|
||||
{
|
||||
line = lines.FirstOrDefault(x => x.Contains(text));
|
||||
return line != null;
|
||||
}
|
||||
}
|
||||
|
||||
public override Task Cancel()
|
||||
|
||||
Reference in New Issue
Block a user