diff --git a/FFMpegCore/FFMpeg/FFMpegArguments.cs b/FFMpegCore/FFMpeg/FFMpegArguments.cs index 09e1019..7e7b524 100644 --- a/FFMpegCore/FFMpeg/FFMpegArguments.cs +++ b/FFMpegCore/FFMpeg/FFMpegArguments.cs @@ -119,7 +119,7 @@ internal void Post() public TArgument Find() where TArgument : class, IArgument { - return _arguments.FirstOrDefault(arg => arg is TArgument) as TArgument; + return _arguments.OfType().FirstOrDefault(); } } } \ No newline at end of file diff --git a/FFMpegCore/FFMpegCore.csproj b/FFMpegCore/FFMpegCore.csproj index 3e43edf..3605560 100644 --- a/FFMpegCore/FFMpegCore.csproj +++ b/FFMpegCore/FFMpegCore.csproj @@ -9,12 +9,9 @@ 1.0.12 1.1.0.0 1.1.0.0 - - Support for .NET Standard 2.0 -- Minor fixes -- DemuxConcatArgument -- Fix error in static Convert + - Format property on MediaAnalysis with information from show_format 8 - 2.1.1 + 2.2.0 Vlad Jerca, Malte Rosenbjerg ffmpeg ffprobe convert video audio mediafile resize analyze muxing GitHub diff --git a/FFMpegCore/FFProbe/FFProbe.cs b/FFMpegCore/FFProbe/FFProbe.cs index 73d4c49..4959d0f 100644 --- a/FFMpegCore/FFProbe/FFProbe.cs +++ b/FFMpegCore/FFProbe/FFProbe.cs @@ -88,7 +88,7 @@ private static Instance PrepareInstance(string filePath, int outputCapacity) { FFProbeHelper.RootExceptionCheck(FFMpegOptions.Options.RootDirectory); var ffprobe = FFMpegOptions.Options.FFProbeBinary(); - var arguments = $"-print_format json -show_streams \"{filePath}\""; + var arguments = $"-print_format json -show_format -sexagesimal -show_streams \"{filePath}\""; var instance = new Instance(ffprobe, arguments) {DataBufferCapacity = outputCapacity}; return instance; } diff --git a/FFMpegCore/FFProbe/FFProbeAnalysis.cs b/FFMpegCore/FFProbe/FFProbeAnalysis.cs index c647437..1185998 100644 --- a/FFMpegCore/FFProbe/FFProbeAnalysis.cs +++ b/FFMpegCore/FFProbe/FFProbeAnalysis.cs @@ -1,4 +1,5 @@ -using System.Collections.Generic; +using System; +using System.Collections.Generic; using System.Text.Json.Serialization; namespace FFMpegCore @@ -7,6 +8,9 @@ public class FFProbeAnalysis { [JsonPropertyName("streams")] public List Streams { get; set; } = null!; + + [JsonPropertyName("format")] + public Format Format { get; set; } = null!; } public class FFProbeStream @@ -73,5 +77,43 @@ public class Tags [JsonPropertyName("language")] public string Language { get; set; } = null!; + + [JsonPropertyName("encoder")] + public string Encoder { get; set; } = null!; + } + public class Format + { + [JsonPropertyName("filename")] + public string Filename { get; set; } + + [JsonPropertyName("nb_streams")] + public int NbStreams { get; set; } + + [JsonPropertyName("nb_programs")] + public int NbPrograms { get; set; } + + [JsonPropertyName("format_name")] + public string FormatName { get; set; } + + [JsonPropertyName("format_long_name")] + public string FormatLongName { get; set; } + + [JsonPropertyName("start_time")] + public string StartTime { get; set; } + + [JsonPropertyName("duration")] + public string Duration { get; set; } + + [JsonPropertyName("size")] + public string Size { get; set; } + + [JsonPropertyName("bit_rate")] + public string BitRate { get; set; } + + [JsonPropertyName("probe_score")] + public int ProbeScore { get; set; } + + [JsonPropertyName("tags")] + public Tags Tags { get; set; } } } diff --git a/FFMpegCore/FFProbe/MediaAnalysis.cs b/FFMpegCore/FFProbe/MediaAnalysis.cs index d8661fb..4345016 100644 --- a/FFMpegCore/FFProbe/MediaAnalysis.cs +++ b/FFMpegCore/FFProbe/MediaAnalysis.cs @@ -10,6 +10,7 @@ public class MediaAnalysis private static readonly Regex DurationRegex = new Regex("^(\\d{1,2}:\\d{1,2}:\\d{1,2}(.\\d{1,7})?)", RegexOptions.Compiled); internal MediaAnalysis(string path, FFProbeAnalysis analysis) { + Format = ParseFormat(analysis.Format); VideoStreams = analysis.Streams.Where(stream => stream.CodecType == "video").Select(ParseVideoStream).ToList(); AudioStreams = analysis.Streams.Where(stream => stream.CodecType == "audio").Select(ParseAudioStream).ToList(); PrimaryVideoStream = VideoStreams.OrderBy(stream => stream.Index).FirstOrDefault(); @@ -17,13 +18,30 @@ internal MediaAnalysis(string path, FFProbeAnalysis analysis) Path = path; } + private MediaFormat ParseFormat(Format analysisFormat) + { + return new MediaFormat + { + Duration = TimeSpan.Parse(analysisFormat.Duration), + FormatName = analysisFormat.FormatName, + FormatLongName = analysisFormat.FormatLongName, + StreamCount = analysisFormat.NbStreams, + ProbeScore = analysisFormat.ProbeScore, + BitRate = long.Parse(analysisFormat.BitRate ?? "0") + }; + } public string Path { get; } public string Extension => System.IO.Path.GetExtension(Path); - public TimeSpan Duration => TimeSpan.FromSeconds(Math.Max( - PrimaryVideoStream?.Duration.TotalSeconds ?? 0, - PrimaryAudioStream?.Duration.TotalSeconds ?? 0)); + public TimeSpan Duration => new [] + { + Format.Duration, + PrimaryVideoStream?.Duration ?? TimeSpan.Zero, + PrimaryAudioStream?.Duration ?? TimeSpan.Zero + }.Max(); + + public MediaFormat Format { get; } public AudioStream PrimaryAudioStream { get; } public VideoStream PrimaryVideoStream { get; } @@ -54,8 +72,8 @@ private VideoStream ParseVideoStream(FFProbeStream stream) private static TimeSpan ParseDuration(FFProbeStream ffProbeStream) { - return ffProbeStream.Duration != null - ? TimeSpan.FromSeconds(ParseDoubleInvariant(ffProbeStream.Duration)) + return !string.IsNullOrEmpty(ffProbeStream.Duration) + ? TimeSpan.Parse(ffProbeStream.Duration) : TimeSpan.Parse(TrimTimeSpan(ffProbeStream.Tags?.Duration) ?? "0"); } private static string? TrimTimeSpan(string? durationTag) diff --git a/FFMpegCore/FFProbe/MediaFormat.cs b/FFMpegCore/FFProbe/MediaFormat.cs new file mode 100644 index 0000000..60c89b8 --- /dev/null +++ b/FFMpegCore/FFProbe/MediaFormat.cs @@ -0,0 +1,14 @@ +using System; + +namespace FFMpegCore +{ + public class MediaFormat + { + public TimeSpan Duration { get; set; } + public string FormatName { get; set; } + public string FormatLongName { get; set; } + public int StreamCount { get; set; } + public double ProbeScore { get; set; } + public double BitRate { get; set; } + } +} \ No newline at end of file