Merge pull request #233 from alex6dj/feature/support-subtitles-stream

Basic ffprobe subtitle streams support
This commit is contained in:
Malte Rosenbjerg 2021-08-05 13:16:48 +02:00 committed by GitHub
commit 1a87b0b133
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
7 changed files with 53 additions and 3 deletions

View file

@ -83,6 +83,9 @@
<None Update="Resources\mute.mp4"> <None Update="Resources\mute.mp4">
<CopyToOutputDirectory>Always</CopyToOutputDirectory> <CopyToOutputDirectory>Always</CopyToOutputDirectory>
</None> </None>
<None Update="Resources\sample.srt">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</None>
</ItemGroup> </ItemGroup>
<ItemGroup> <ItemGroup>

View file

@ -100,5 +100,15 @@ public async Task Probe_Success_FromStream_Async()
var info = await FFProbe.AnalyseAsync(stream); var info = await FFProbe.AnalyseAsync(stream);
Assert.AreEqual(3, info.Duration.Seconds); Assert.AreEqual(3, info.Duration.Seconds);
} }
[TestMethod, Timeout(10000)]
public async Task Probe_Success_Subtitle_Async()
{
var info = await FFProbe.AnalyseAsync(TestResources.SrtSubtitle);
Assert.IsNotNull(info.PrimarySubtitleStream);
Assert.AreEqual(1, info.SubtitleStreams.Count);
Assert.AreEqual(0, info.AudioStreams.Count);
Assert.AreEqual(0, info.VideoStreams.Count);
}
} }
} }

View file

@ -20,5 +20,6 @@ public static class TestResources
public static readonly string Mp3Audio = "./Resources/audio.mp3"; public static readonly string Mp3Audio = "./Resources/audio.mp3";
public static readonly string PngImage = "./Resources/cover.png"; public static readonly string PngImage = "./Resources/cover.png";
public static readonly string ImageCollection = "./Resources/images"; public static readonly string ImageCollection = "./Resources/images";
public static readonly string SrtSubtitle = "./Resources/sample.srt";
} }
} }

View file

@ -0,0 +1,12 @@
1
00:00:00,000 --> 00:00:01,500
For www.forom.com
2
00:00:01,500 --> 00:00:02,500
<i>Tonight's the night.</i>
3
00:00:03,000 --> 00:00:15,000
<i>And it's going to happen
again and again --</i>

View file

@ -9,7 +9,9 @@ public interface IMediaAnalysis
MediaFormat Format { get; } MediaFormat Format { get; }
AudioStream? PrimaryAudioStream { get; } AudioStream? PrimaryAudioStream { get; }
VideoStream? PrimaryVideoStream { get; } VideoStream? PrimaryVideoStream { get; }
SubtitleStream? PrimarySubtitleStream { get; }
List<VideoStream> VideoStreams { get; } List<VideoStream> VideoStreams { get; }
List<AudioStream> AudioStreams { get; } List<AudioStream> AudioStreams { get; }
List<SubtitleStream> SubtitleStreams { get; }
} }
} }

View file

@ -12,8 +12,9 @@ internal MediaAnalysis(FFProbeAnalysis analysis)
Format = ParseFormat(analysis.Format); 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();
SubtitleStreams = analysis.Streams.Where(stream => stream.CodecType == "subtitle").Select(ParseSubtitleStream).ToList();
} }
private MediaFormat ParseFormat(Format analysisFormat) private MediaFormat ParseFormat(Format analysisFormat)
{ {
return new MediaFormat return new MediaFormat
@ -36,12 +37,14 @@ private MediaFormat ParseFormat(Format analysisFormat)
}.Max(); }.Max();
public MediaFormat Format { get; } public MediaFormat Format { get; }
public AudioStream? PrimaryAudioStream => AudioStreams.OrderBy(stream => stream.Index).FirstOrDefault(); public AudioStream? PrimaryAudioStream => AudioStreams.OrderBy(stream => stream.Index).FirstOrDefault();
public VideoStream? PrimaryVideoStream => VideoStreams.OrderBy(stream => stream.Index).FirstOrDefault(); public VideoStream? PrimaryVideoStream => VideoStreams.OrderBy(stream => stream.Index).FirstOrDefault();
public SubtitleStream? PrimarySubtitleStream => SubtitleStreams.OrderBy(stream => stream.Index).FirstOrDefault();
public List<VideoStream> VideoStreams { get; } public List<VideoStream> VideoStreams { get; }
public List<AudioStream> AudioStreams { get; } public List<AudioStream> AudioStreams { get; }
public List<SubtitleStream> SubtitleStreams { get; }
private VideoStream ParseVideoStream(FFProbeStream stream) private VideoStream ParseVideoStream(FFProbeStream stream)
{ {
@ -84,7 +87,19 @@ private AudioStream ParseAudioStream(FFProbeStream stream)
}; };
} }
private SubtitleStream ParseSubtitleStream(FFProbeStream stream)
{
return new SubtitleStream
{
Index = stream.Index,
BitRate = !string.IsNullOrEmpty(stream.BitRate) ? MediaAnalysisUtils.ParseIntInvariant(stream.BitRate) : default,
CodecName = stream.CodecName,
CodecLongName = stream.CodecLongName,
Duration = MediaAnalysisUtils.ParseDuration(stream),
Language = stream.GetLanguage(),
Tags = stream.Tags,
};
}
} }
public static class MediaAnalysisUtils public static class MediaAnalysisUtils

View file

@ -0,0 +1,7 @@
namespace FFMpegCore
{
public class SubtitleStream : MediaStream
{
}
}