From d16efbda313187704fe32b9ccec6775d46ab90b3 Mon Sep 17 00:00:00 2001 From: hey-red Date: Sat, 23 Jan 2021 05:40:03 +0300 Subject: [PATCH 1/4] Fix incorrect condition --- FFMpegCore/FFMpeg/Enums/ContainerFormat.cs | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/FFMpegCore/FFMpeg/Enums/ContainerFormat.cs b/FFMpegCore/FFMpeg/Enums/ContainerFormat.cs index 37c2bda..90da0d2 100644 --- a/FFMpegCore/FFMpeg/Enums/ContainerFormat.cs +++ b/FFMpegCore/FFMpeg/Enums/ContainerFormat.cs @@ -10,6 +10,7 @@ public class ContainerFormat public bool DemuxingSupported { get; private set; } public bool MuxingSupported { get; private set; } public string Description { get; private set; } = null!; + public string Extension { get @@ -36,11 +37,11 @@ internal static bool TryParse(string line, out ContainerFormat fmt) fmt = new ContainerFormat(match.Groups[3].Value) { - DemuxingSupported = match.Groups[1].Value == " ", - MuxingSupported = match.Groups[2].Value == " ", + DemuxingSupported = match.Groups[1].Value != " ", + MuxingSupported = match.Groups[2].Value != " ", Description = match.Groups[4].Value }; return true; } } -} +} \ No newline at end of file From f603163e250b092da96a9138ca1f31c1dfcd89f4 Mon Sep 17 00:00:00 2001 From: hey-red Date: Fri, 29 Jan 2021 16:03:59 +0300 Subject: [PATCH 2/4] Add tags on media stream and format --- FFMpegCore/FFProbe/MediaAnalysis.cs | 16 ++++++++++++---- FFMpegCore/FFProbe/MediaFormat.cs | 2 ++ FFMpegCore/FFProbe/MediaStream.cs | 3 +++ 3 files changed, 17 insertions(+), 4 deletions(-) diff --git a/FFMpegCore/FFProbe/MediaAnalysis.cs b/FFMpegCore/FFProbe/MediaAnalysis.cs index 4717a6f..5a43aa2 100644 --- a/FFMpegCore/FFProbe/MediaAnalysis.cs +++ b/FFMpegCore/FFProbe/MediaAnalysis.cs @@ -8,6 +8,7 @@ namespace FFMpegCore internal class MediaAnalysis : IMediaAnalysis { 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); @@ -27,14 +28,15 @@ private MediaFormat ParseFormat(Format analysisFormat) FormatLongName = analysisFormat.FormatLongName, StreamCount = analysisFormat.NbStreams, ProbeScore = analysisFormat.ProbeScore, - BitRate = long.Parse(analysisFormat.BitRate ?? "0") + BitRate = long.Parse(analysisFormat.BitRate ?? "0"), + Tags = analysisFormat.Tags, }; } public string Path { get; } public string Extension => System.IO.Path.GetExtension(Path); - public TimeSpan Duration => new [] + public TimeSpan Duration => new[] { Format.Duration, PrimaryVideoStream?.Duration ?? TimeSpan.Zero, @@ -67,7 +69,8 @@ private VideoStream ParseVideoStream(FFProbeStream stream) Profile = stream.Profile, PixelFormat = stream.PixelFormat, Rotation = (int)float.Parse(stream.GetRotate() ?? "0"), - Language = stream.GetLanguage() + Language = stream.GetLanguage(), + Tags = stream.Tags, }; } @@ -77,6 +80,7 @@ private static TimeSpan ParseDuration(FFProbeStream ffProbeStream) ? TimeSpan.Parse(ffProbeStream.Duration) : TimeSpan.Parse(TrimTimeSpan(ffProbeStream.GetDuration()) ?? "0"); } + private static string? TrimTimeSpan(string? durationTag) { var durationMatch = DurationRegex.Match(durationTag ?? ""); @@ -96,17 +100,20 @@ private AudioStream ParseAudioStream(FFProbeStream stream) Duration = ParseDuration(stream), SampleRateHz = !string.IsNullOrEmpty(stream.SampleRate) ? ParseIntInvariant(stream.SampleRate) : default, Profile = stream.Profile, - Language = stream.GetLanguage() + Language = stream.GetLanguage(), + Tags = stream.Tags, }; } private static double DivideRatio((double, double) ratio) => ratio.Item1 / ratio.Item2; + private static (int, int) ParseRatioInt(string input, char separator) { if (string.IsNullOrEmpty(input)) return (0, 0); var ratio = input.Split(separator); return (ParseIntInvariant(ratio[0]), ParseIntInvariant(ratio[1])); } + private static (double, double) ParseRatioDouble(string input, char separator) { if (string.IsNullOrEmpty(input)) return (0, 0); @@ -116,6 +123,7 @@ private static (double, double) ParseRatioDouble(string input, char separator) private static double ParseDoubleInvariant(string line) => double.Parse(line, System.Globalization.NumberStyles.Any, System.Globalization.CultureInfo.InvariantCulture); + private static int ParseIntInvariant(string line) => int.Parse(line, System.Globalization.NumberStyles.Any, System.Globalization.CultureInfo.InvariantCulture); } diff --git a/FFMpegCore/FFProbe/MediaFormat.cs b/FFMpegCore/FFProbe/MediaFormat.cs index ea5c6f3..874317c 100644 --- a/FFMpegCore/FFProbe/MediaFormat.cs +++ b/FFMpegCore/FFProbe/MediaFormat.cs @@ -1,4 +1,5 @@ using System; +using System.Collections.Generic; namespace FFMpegCore { @@ -10,5 +11,6 @@ public class MediaFormat public int StreamCount { get; set; } public double ProbeScore { get; set; } public double BitRate { get; set; } + public Dictionary? Tags { get; set; } } } \ No newline at end of file diff --git a/FFMpegCore/FFProbe/MediaStream.cs b/FFMpegCore/FFProbe/MediaStream.cs index 61d548f..0780c8e 100644 --- a/FFMpegCore/FFProbe/MediaStream.cs +++ b/FFMpegCore/FFProbe/MediaStream.cs @@ -1,5 +1,7 @@ using FFMpegCore.Enums; + using System; +using System.Collections.Generic; namespace FFMpegCore { @@ -11,6 +13,7 @@ public class MediaStream public int BitRate { get; internal set; } public TimeSpan Duration { get; internal set; } public string? Language { get; internal set; } + public Dictionary? Tags { get; internal set; } public Codec GetCodecInfo() => FFMpeg.GetCodec(CodecName); } From 66cdb302efb3bc490b6c4d5eb137ab741a444fea Mon Sep 17 00:00:00 2001 From: Malte Rosenbjerg Date: Wed, 3 Feb 2021 23:20:12 +0100 Subject: [PATCH 3/4] Return null when no format detected during analysis --- FFMpegCore/FFProbe/FFProbe.cs | 15 ++++++++------- 1 file changed, 8 insertions(+), 7 deletions(-) diff --git a/FFMpegCore/FFProbe/FFProbe.cs b/FFMpegCore/FFProbe/FFProbe.cs index 076bbfd..8bb68db 100644 --- a/FFMpegCore/FFProbe/FFProbe.cs +++ b/FFMpegCore/FFProbe/FFProbe.cs @@ -12,7 +12,7 @@ namespace FFMpegCore { public static class FFProbe { - public static IMediaAnalysis Analyse(string filePath, int outputCapacity = int.MaxValue) + public static IMediaAnalysis? Analyse(string filePath, int outputCapacity = int.MaxValue) { if (!File.Exists(filePath)) throw new FFMpegException(FFMpegExceptionType.File, $"No file found at '{filePath}'"); @@ -21,13 +21,13 @@ public static IMediaAnalysis Analyse(string filePath, int outputCapacity = int.M instance.BlockUntilFinished(); return ParseOutput(filePath, instance); } - public static IMediaAnalysis Analyse(Uri uri, int outputCapacity = int.MaxValue) + public static IMediaAnalysis? Analyse(Uri uri, int outputCapacity = int.MaxValue) { using var instance = PrepareInstance(uri.AbsoluteUri, outputCapacity); instance.BlockUntilFinished(); return ParseOutput(uri.AbsoluteUri, instance); } - public static IMediaAnalysis Analyse(Stream stream, int outputCapacity = int.MaxValue) + public static IMediaAnalysis? Analyse(Stream stream, int outputCapacity = int.MaxValue) { var streamPipeSource = new StreamPipeSource(stream); var pipeArgument = new InputPipeArgument(streamPipeSource); @@ -50,7 +50,7 @@ public static IMediaAnalysis Analyse(Stream stream, int outputCapacity = int.Max return ParseOutput(pipeArgument.PipePath, instance); } - public static async Task AnalyseAsync(string filePath, int outputCapacity = int.MaxValue) + public static async Task AnalyseAsync(string filePath, int outputCapacity = int.MaxValue) { if (!File.Exists(filePath)) throw new FFMpegException(FFMpegExceptionType.File, $"No file found at '{filePath}'"); @@ -59,13 +59,13 @@ public static async Task AnalyseAsync(string filePath, int outpu await instance.FinishedRunning(); return ParseOutput(filePath, instance); } - public static async Task AnalyseAsync(Uri uri, int outputCapacity = int.MaxValue) + public static async Task AnalyseAsync(Uri uri, int outputCapacity = int.MaxValue) { using var instance = PrepareInstance(uri.AbsoluteUri, outputCapacity); await instance.FinishedRunning(); return ParseOutput(uri.AbsoluteUri, instance); } - public static async Task AnalyseAsync(Stream stream, int outputCapacity = int.MaxValue) + public static async Task AnalyseAsync(Stream stream, int outputCapacity = int.MaxValue) { var streamPipeSource = new StreamPipeSource(stream); var pipeArgument = new InputPipeArgument(streamPipeSource); @@ -92,13 +92,14 @@ public static async Task AnalyseAsync(Stream stream, int outputC return ParseOutput(pipeArgument.PipePath, instance); } - private static IMediaAnalysis ParseOutput(string filePath, Instance instance) + private static IMediaAnalysis? ParseOutput(string filePath, Instance instance) { var json = string.Join(string.Empty, instance.OutputData); var ffprobeAnalysis = JsonSerializer.Deserialize(json, new JsonSerializerOptions { PropertyNameCaseInsensitive = true })!; + if (ffprobeAnalysis?.Format == null) return null; return new MediaAnalysis(filePath, ffprobeAnalysis); } From 4cb80432f6c5f4c9d54a8fb4201d0c00ecc3bc8f Mon Sep 17 00:00:00 2001 From: Malte Rosenbjerg Date: Wed, 3 Feb 2021 23:20:26 +0100 Subject: [PATCH 4/4] Update FFMpegCore.csproj --- FFMpegCore/FFMpegCore.csproj | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/FFMpegCore/FFMpegCore.csproj b/FFMpegCore/FFMpegCore.csproj index ad8ad15..cb5d906 100644 --- a/FFMpegCore/FFMpegCore.csproj +++ b/FFMpegCore/FFMpegCore.csproj @@ -9,10 +9,10 @@ 3.0.0.0 3.0.0.0 3.0.0.0 - - Support for changing encoding used for parsing ffmpeg/ffprobe output -- Support for registrering action to invoke on ffmpeg output + - return null from FFProbe.Analyse* when no media format was detected +- Expose tags as string dictionary on IMediaAnalysis (thanks hey-red) 8 - 3.3.0 + 3.4.0 MIT Malte Rosenbjerg, Vlad Jerca ffmpeg ffprobe convert video audio mediafile resize analyze muxing @@ -31,7 +31,7 @@ - +