diff options
| author | 7illusions <z@7illusions.com> | 2014-05-12 16:55:07 +0200 |
|---|---|---|
| committer | 7illusions <z@7illusions.com> | 2014-05-12 16:55:07 +0200 |
| commit | baf5cf2544fcaad2246923f60caaf3fed4a94aaf (patch) | |
| tree | a808b700095f876e437b95c432c0220e241f9fda /MediaBrowser.MediaEncoding/Subtitles | |
| parent | 8f3a6279e173dcbaaa05a56556afb410ee12dd4d (diff) | |
| parent | b9b568de13d81f9db1a8502d50940475c1d79c72 (diff) | |
Merge pull request #3 from MediaBrowser/master
Sync with Master
Diffstat (limited to 'MediaBrowser.MediaEncoding/Subtitles')
6 files changed, 204 insertions, 0 deletions
diff --git a/MediaBrowser.MediaEncoding/Subtitles/ISubtitleParser.cs b/MediaBrowser.MediaEncoding/Subtitles/ISubtitleParser.cs new file mode 100644 index 000000000..b983bc5d4 --- /dev/null +++ b/MediaBrowser.MediaEncoding/Subtitles/ISubtitleParser.cs @@ -0,0 +1,9 @@ +using System.IO; + +namespace MediaBrowser.MediaEncoding.Subtitles +{ + public interface ISubtitleParser + { + SubtitleTrackInfo Parse(Stream stream); + } +} diff --git a/MediaBrowser.MediaEncoding/Subtitles/ISubtitleWriter.cs b/MediaBrowser.MediaEncoding/Subtitles/ISubtitleWriter.cs new file mode 100644 index 000000000..9cbd09e7b --- /dev/null +++ b/MediaBrowser.MediaEncoding/Subtitles/ISubtitleWriter.cs @@ -0,0 +1,17 @@ +using System.IO; + +namespace MediaBrowser.MediaEncoding.Subtitles +{ + /// <summary> + /// Interface ISubtitleWriter + /// </summary> + public interface ISubtitleWriter + { + /// <summary> + /// Writes the specified information. + /// </summary> + /// <param name="info">The information.</param> + /// <param name="stream">The stream.</param> + void Write(SubtitleTrackInfo info, Stream stream); + } +} diff --git a/MediaBrowser.MediaEncoding/Subtitles/SrtParser.cs b/MediaBrowser.MediaEncoding/Subtitles/SrtParser.cs new file mode 100644 index 000000000..09bc52df4 --- /dev/null +++ b/MediaBrowser.MediaEncoding/Subtitles/SrtParser.cs @@ -0,0 +1,61 @@ +using System; +using System.Collections.Generic; +using System.Globalization; +using System.IO; +using System.Text.RegularExpressions; + +namespace MediaBrowser.MediaEncoding.Subtitles +{ + public class SrtParser : ISubtitleParser + { + private readonly CultureInfo _usCulture = new CultureInfo("en-US"); + public SubtitleTrackInfo Parse(Stream stream) { + var trackInfo = new SubtitleTrackInfo(); + using ( var reader = new StreamReader(stream)) + { + string line; + while ((line = reader.ReadLine()) != null) + { + if (string.IsNullOrWhiteSpace(line)) + { + continue; + } + var subEvent = new SubtitleTrackEvent {Id = line}; + line = reader.ReadLine(); + var time = Regex.Split(line, @"[\t ]*-->[\t ]*"); + subEvent.StartPositionTicks = GetTicks(time[0]); + var endTime = time[1]; + var idx = endTime.IndexOf(" ", StringComparison.Ordinal); + if (idx > 0) + endTime = endTime.Substring(0, idx); + subEvent.EndPositionTicks = GetTicks(endTime); + var multiline = new List<string>(); + while ((line = reader.ReadLine()) != null) + { + if (string.IsNullOrEmpty(line)) + { + break; + } + multiline.Add(line); + } + subEvent.Text = string.Join(@"\N", multiline); + subEvent.Text = Regex.Replace(subEvent.Text, @"\{(\\[\w]+\(?([\w\d]+,?)+\)?)+\}", string.Empty, RegexOptions.IgnoreCase); + subEvent.Text = Regex.Replace(subEvent.Text, "<", "<", RegexOptions.IgnoreCase); + subEvent.Text = Regex.Replace(subEvent.Text, ">", ">", RegexOptions.IgnoreCase); + subEvent.Text = Regex.Replace(subEvent.Text, "<(\\/?(font|b|u|i|s))((\\s+(\\w|\\w[\\w\\-]*\\w)(\\s*=\\s*(?:\\\".*?\\\"|'.*?'|[^'\\\">\\s]+))?)+\\s*|\\s*)(\\/?)>", "<$1$3$7>", RegexOptions.IgnoreCase); + subEvent.Text = Regex.Replace(subEvent.Text, @"\\N", "<br />",RegexOptions.IgnoreCase); + trackInfo.TrackEvents.Add(subEvent); + } + } + return trackInfo; + } + + long GetTicks(string time) { + TimeSpan span; + return TimeSpan.TryParseExact(time, @"hh\:mm\:ss\.fff", _usCulture, out span) + ? span.Ticks + : (TimeSpan.TryParseExact(time, @"hh\:mm\:ss\,fff", _usCulture, out span) + ? span.Ticks : 0); + } + } +} diff --git a/MediaBrowser.MediaEncoding/Subtitles/SsaParser.cs b/MediaBrowser.MediaEncoding/Subtitles/SsaParser.cs new file mode 100644 index 000000000..996ef1c4e --- /dev/null +++ b/MediaBrowser.MediaEncoding/Subtitles/SsaParser.cs @@ -0,0 +1,69 @@ +using System; +using System.Collections.Generic; +using System.Globalization; +using System.IO; +using System.Linq; +using System.Text.RegularExpressions; + +namespace MediaBrowser.MediaEncoding.Subtitles +{ + public class SsaParser : ISubtitleParser + { + private readonly CultureInfo _usCulture = new CultureInfo("en-US"); + + public SubtitleTrackInfo Parse(Stream stream) + { + var trackInfo = new SubtitleTrackInfo(); + var eventIndex = 1; + using (var reader = new StreamReader(stream)) + { + string line; + while (reader.ReadLine() != "[Events]") + {} + var headers = ParseFieldHeaders(reader.ReadLine()); + + while ((line = reader.ReadLine()) != null) + { + if (string.IsNullOrWhiteSpace(line)) + { + continue; + } + if(line.StartsWith("[")) + break; + if(string.IsNullOrEmpty(line)) + continue; + var subEvent = new SubtitleTrackEvent { Id = eventIndex.ToString(_usCulture) }; + eventIndex++; + var sections = line.Substring(10).Split(','); + + subEvent.StartPositionTicks = GetTicks(sections[headers["Start"]]); + subEvent.EndPositionTicks = GetTicks(sections[headers["End"]]); + subEvent.Text = string.Join(",", sections.Skip(headers["Text"])); + subEvent.Text = Regex.Replace(subEvent.Text, @"\{(\\[\w]+\(?([\w\d]+,?)+\)?)+\}", string.Empty, RegexOptions.IgnoreCase); + subEvent.Text = Regex.Replace(subEvent.Text, @"\\N", "<br />", RegexOptions.IgnoreCase); + + trackInfo.TrackEvents.Add(subEvent); + } + } + return trackInfo; + } + + long GetTicks(string time) + { + TimeSpan span; + return TimeSpan.TryParseExact(time, @"h\:mm\:ss\.ff", _usCulture, out span) + ? span.Ticks: 0; + } + + private Dictionary<string,int> ParseFieldHeaders(string line) { + var fields = line.Substring(8).Split(',').Select(x=>x.Trim()).ToList(); + + var result = new Dictionary<string, int> { + {"Start", fields.IndexOf("Start")}, + {"End", fields.IndexOf("End")}, + {"Text", fields.IndexOf("Text")} + }; + return result; + } + } +} diff --git a/MediaBrowser.MediaEncoding/Subtitles/SubtitleTrackInfo.cs b/MediaBrowser.MediaEncoding/Subtitles/SubtitleTrackInfo.cs new file mode 100644 index 000000000..67d70ed6e --- /dev/null +++ b/MediaBrowser.MediaEncoding/Subtitles/SubtitleTrackInfo.cs @@ -0,0 +1,22 @@ +using System.Collections.Generic; + +namespace MediaBrowser.MediaEncoding.Subtitles +{ + public class SubtitleTrackInfo + { + public List<SubtitleTrackEvent> TrackEvents { get; set; } + + public SubtitleTrackInfo() + { + TrackEvents = new List<SubtitleTrackEvent>(); + } + } + + public class SubtitleTrackEvent + { + public string Id { get; set; } + public string Text { get; set; } + public long StartPositionTicks { get; set; } + public long EndPositionTicks { get; set; } + } +} diff --git a/MediaBrowser.MediaEncoding/Subtitles/VttWriter.cs b/MediaBrowser.MediaEncoding/Subtitles/VttWriter.cs new file mode 100644 index 000000000..dc750fb6b --- /dev/null +++ b/MediaBrowser.MediaEncoding/Subtitles/VttWriter.cs @@ -0,0 +1,26 @@ +using System; +using System.Collections.Generic; +using System.IO; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace MediaBrowser.MediaEncoding.Subtitles +{ + public class VttWriter : ISubtitleWriter + { + public void Write(SubtitleTrackInfo info, Stream stream) { + using (var writer = new StreamWriter(stream)) + { + writer.WriteLine("WEBVTT"); + writer.WriteLine(string.Empty); + foreach (var trackEvent in info.TrackEvents) + { + writer.WriteLine(@"{0:hh\:mm\:ss\.fff} --> {1:hh\:mm\:ss\.fff}", TimeSpan.FromTicks(trackEvent.StartPositionTicks), TimeSpan.FromTicks(trackEvent.EndPositionTicks)); + writer.WriteLine(trackEvent.Text); + writer.WriteLine(string.Empty); + } + } + } + } +} |
