Parse Format from FFProbe show_format

This commit is contained in:
Malte Rosenbjerg 2020-06-20 14:50:46 +02:00
parent f0b83a8941
commit b7b15079eb
6 changed files with 84 additions and 13 deletions

View file

@ -119,7 +119,7 @@ internal void Post()
public TArgument Find<TArgument>() where TArgument : class, IArgument public TArgument Find<TArgument>() where TArgument : class, IArgument
{ {
return _arguments.FirstOrDefault(arg => arg is TArgument) as TArgument; return _arguments.OfType<TArgument>().FirstOrDefault();
} }
} }
} }

View file

@ -9,12 +9,9 @@
<Version>1.0.12</Version> <Version>1.0.12</Version>
<AssemblyVersion>1.1.0.0</AssemblyVersion> <AssemblyVersion>1.1.0.0</AssemblyVersion>
<FileVersion>1.1.0.0</FileVersion> <FileVersion>1.1.0.0</FileVersion>
<PackageReleaseNotes>- Support for .NET Standard 2.0 <PackageReleaseNotes>- Format property on MediaAnalysis with information from show_format</PackageReleaseNotes>
- Minor fixes
- DemuxConcatArgument
- Fix error in static Convert</PackageReleaseNotes>
<LangVersion>8</LangVersion> <LangVersion>8</LangVersion>
<PackageVersion>2.1.1</PackageVersion> <PackageVersion>2.2.0</PackageVersion>
<Authors>Vlad Jerca, Malte Rosenbjerg</Authors> <Authors>Vlad Jerca, Malte Rosenbjerg</Authors>
<PackageTags>ffmpeg ffprobe convert video audio mediafile resize analyze muxing</PackageTags> <PackageTags>ffmpeg ffprobe convert video audio mediafile resize analyze muxing</PackageTags>
<RepositoryType>GitHub</RepositoryType> <RepositoryType>GitHub</RepositoryType>

View file

@ -88,7 +88,7 @@ private static Instance PrepareInstance(string filePath, int outputCapacity)
{ {
FFProbeHelper.RootExceptionCheck(FFMpegOptions.Options.RootDirectory); FFProbeHelper.RootExceptionCheck(FFMpegOptions.Options.RootDirectory);
var ffprobe = FFMpegOptions.Options.FFProbeBinary(); 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}; var instance = new Instance(ffprobe, arguments) {DataBufferCapacity = outputCapacity};
return instance; return instance;
} }

View file

@ -1,4 +1,5 @@
using System.Collections.Generic; using System;
using System.Collections.Generic;
using System.Text.Json.Serialization; using System.Text.Json.Serialization;
namespace FFMpegCore namespace FFMpegCore
@ -7,6 +8,9 @@ public class FFProbeAnalysis
{ {
[JsonPropertyName("streams")] [JsonPropertyName("streams")]
public List<FFProbeStream> Streams { get; set; } = null!; public List<FFProbeStream> Streams { get; set; } = null!;
[JsonPropertyName("format")]
public Format Format { get; set; } = null!;
} }
public class FFProbeStream public class FFProbeStream
@ -73,5 +77,43 @@ public class Tags
[JsonPropertyName("language")] [JsonPropertyName("language")]
public string Language { get; set; } = null!; 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; }
} }
} }

View file

@ -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); 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) internal MediaAnalysis(string path, FFProbeAnalysis analysis)
{ {
Format = ParseFormat(analysis.Format);
VideoStreams = analysis.Streams.Where(stream => stream.CodecType == "video").Select(ParseVideoStream).ToList(); VideoStreams = analysis.Streams.Where(stream => stream.CodecType == "video").Select(ParseVideoStream).ToList();
AudioStreams = analysis.Streams.Where(stream => stream.CodecType == "audio").Select(ParseAudioStream).ToList(); AudioStreams = analysis.Streams.Where(stream => stream.CodecType == "audio").Select(ParseAudioStream).ToList();
PrimaryVideoStream = VideoStreams.OrderBy(stream => stream.Index).FirstOrDefault(); PrimaryVideoStream = VideoStreams.OrderBy(stream => stream.Index).FirstOrDefault();
@ -17,13 +18,30 @@ internal MediaAnalysis(string path, FFProbeAnalysis analysis)
Path = path; 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 Path { get; }
public string Extension => System.IO.Path.GetExtension(Path); public string Extension => System.IO.Path.GetExtension(Path);
public TimeSpan Duration => TimeSpan.FromSeconds(Math.Max( public TimeSpan Duration => new []
PrimaryVideoStream?.Duration.TotalSeconds ?? 0, {
PrimaryAudioStream?.Duration.TotalSeconds ?? 0)); Format.Duration,
PrimaryVideoStream?.Duration ?? TimeSpan.Zero,
PrimaryAudioStream?.Duration ?? TimeSpan.Zero
}.Max();
public MediaFormat Format { get; }
public AudioStream PrimaryAudioStream { get; } public AudioStream PrimaryAudioStream { get; }
public VideoStream PrimaryVideoStream { get; } public VideoStream PrimaryVideoStream { get; }
@ -54,8 +72,8 @@ private VideoStream ParseVideoStream(FFProbeStream stream)
private static TimeSpan ParseDuration(FFProbeStream ffProbeStream) private static TimeSpan ParseDuration(FFProbeStream ffProbeStream)
{ {
return ffProbeStream.Duration != null return !string.IsNullOrEmpty(ffProbeStream.Duration)
? TimeSpan.FromSeconds(ParseDoubleInvariant(ffProbeStream.Duration)) ? TimeSpan.Parse(ffProbeStream.Duration)
: TimeSpan.Parse(TrimTimeSpan(ffProbeStream.Tags?.Duration) ?? "0"); : TimeSpan.Parse(TrimTimeSpan(ffProbeStream.Tags?.Duration) ?? "0");
} }
private static string? TrimTimeSpan(string? durationTag) private static string? TrimTimeSpan(string? durationTag)

View file

@ -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; }
}
}