public override string ToText(Subtitle subtitle, string title) { StringBuilder sb = new StringBuilder(); sb.Append("{\"words\":["); for (int i = 0; i < subtitle.Paragraphs.Count; i++) { Paragraph p = subtitle.Paragraphs[i]; // split words string text = p.Text.Replace(Environment.NewLine, " ").Replace(" ", " "); string[] words = text.Split(new[] { ' ' }, StringSplitOptions.RemoveEmptyEntries); List<string> times = GenerateTimes(words, text, p.StartTime, p.EndTime); for (int j = 0; j < words.Length; j++) { sb.Append("[\""); sb.Append(times[j]); sb.Append("\",\""); sb.Append(Json.EncodeJsonText(words[j])); sb.Append("\"]"); sb.Append(','); } Paragraph next = subtitle.GetParagraphOrDefault(i + 1); if (next == null || next.StartTime.TotalMilliseconds - 200 < p.EndTime.TotalMilliseconds) { sb.Append("[\""); sb.Append(Convert.ToInt64(p.EndTime.TotalMilliseconds)); sb.Append("\",\""); sb.Append("\"]"); sb.Append(','); } } return sb.ToString().Trim().TrimEnd(',') + "],\"paragraphs\":[],\"speakers\":{}}"; }
internal void Initialize(Subtitle subtitle, int firstSelectedIndex) { var sb = new StringBuilder(); foreach (Paragraph p in subtitle.Paragraphs) sb.AppendLine(p.Text); string watermark = ReadWaterMark(sb.ToString().Trim()); LabelWatermark.Text = string.Format("Watermark: {0}", watermark); if (watermark.Length == 0) { buttonRemove.Enabled = false; textBoxWatermark.Focus(); } else { groupBoxGenerate.Enabled = false; buttonOK.Focus(); } _firstSelectedIndex = firstSelectedIndex; Paragraph current = subtitle.GetParagraphOrDefault(_firstSelectedIndex); if (current != null) radioButtonCurrentLine.Text = radioButtonCurrentLine.Text + " " + current.Text.Replace(Environment.NewLine, Configuration.Settings.General.ListViewLineSeparatorString); else radioButtonCurrentLine.Enabled = false; }
public override string ToText(Subtitle subtitle, string title) { StringBuilder sb = new StringBuilder(); sb.AppendLine("#\tAppearance\tCaption\t"); sb.AppendLine(); int count = 1; for (int i = 0; i < subtitle.Paragraphs.Count; i++) { Paragraph p = subtitle.Paragraphs[i]; string text = HtmlUtil.RemoveHtmlTags(p.Text); sb.AppendLine(string.Format("{0}\t{1}\t{2}\t", count.ToString().PadLeft(5, ' '), MakeTimeCode(p.StartTime), text)); sb.AppendLine("\t\t\t\t"); Paragraph next = subtitle.GetParagraphOrDefault(i + 1); if (next == null || Math.Abs(p.EndTime.TotalMilliseconds - next.StartTime.TotalMilliseconds) > 50) { count++; sb.AppendLine(string.Format("{0}\t{1}", count.ToString().PadLeft(5, ' '), MakeTimeCode(p.EndTime))); } count++; } RichTextBox rtBox = new RichTextBox(); rtBox.Text = sb.ToString(); string rtf = rtBox.Rtf; rtBox.Dispose(); return rtf; }
public override string ToText(Subtitle subtitle, string title) { string header = @"<!DOCTYPE html> <html> <head>" + Environment.NewLine + "\t<meta charset=\"utf-8\">" + Environment.NewLine + "\t<title>SMIL Timesheet</title>" + @" </head> <body>" + Environment.NewLine + "\t<div id=\"media\" data-timecontainer=\"excl\" data-timeaction=\"display\">" + Environment.NewLine + "\t\t<video data-syncmaster=\"true\" data-timeaction=\"none\" controls=\"true\" preload=\"auto\">" + Environment.NewLine + "\t\t\t<source type=\"video/webm\" src=\"_TITLE_.webm\"/>" + Environment.NewLine + "\t\t\t<source type=\"video/ogg\" src=\"_TITLE_.ogv\" />" + Environment.NewLine + "\t\t\t<source type=\"video/mp4\" src=\"_TITLE_.mp4\" />" + Environment.NewLine + "\t\t\tYour browser does not support the HTML5 <video> tag" + Environment.NewLine + "\t\t</video>" + Environment.NewLine; const string paragraphWriteFormatOpen = "\t\t<p data-begin=\"{0}\">\r\n{1}\r\n</p>"; const string paragraphWriteFormat = "\t\t<p data-begin=\"{0}\" data-end=\"{1}\">\r\n{2}\r\n</p>"; int count = 1; StringBuilder sb = new StringBuilder(); sb.AppendLine(header.Replace("_TITLE_", title)); foreach (Paragraph p in subtitle.Paragraphs) { Paragraph next = subtitle.GetParagraphOrDefault(count); string text = p.Text; if (next != null && Math.Abs(next.StartTime.TotalMilliseconds - p.EndTime.TotalMilliseconds) < 100) { sb.AppendLine(string.Format(paragraphWriteFormatOpen, EncodeTime(p.StartTime), text)); } else { sb.AppendLine(string.Format(paragraphWriteFormat, EncodeTime(p.StartTime), EncodeTime(p.EndTime), text)); } count++; } sb.AppendLine("\t</div>"); sb.AppendLine("</body>"); sb.AppendLine("</html>"); return sb.ToString().Trim(); }
public Subtitle AdjustAllParagraphs(Subtitle subtitle) { foreach (Paragraph p in subtitle.Paragraphs) { AdjustParagraph(p); } for (int i = 0; i < subtitle.Paragraphs.Count; i++) { Paragraph p = subtitle.Paragraphs[i]; Paragraph next = subtitle.GetParagraphOrDefault(i + 1); if (next != null) { if (p.EndTime.TotalMilliseconds >= next.StartTime.TotalMilliseconds) p.EndTime.TotalMilliseconds = next.StartTime.TotalMilliseconds - 1; } } return subtitle; }
public override string ToText(Subtitle subtitle, string title) { StringBuilder sb = new StringBuilder(); int index = 0; int index2 = 0; foreach (Paragraph p in subtitle.Paragraphs) { index++; StringBuilder text = new StringBuilder(); text.Append(HtmlUtil.RemoveHtmlTags(p.Text.Replace(Environment.NewLine, " "))); while (text.Length < 34) { text.Append(' '); } sb.AppendFormat("{0}{1}", text, EncodeTimeCode(p.StartTime)); if (index % 50 == 1) { index2++; sb.Append(new string(' ', 25) + index2); } sb.AppendLine(); Paragraph next = subtitle.GetParagraphOrDefault(index); if (next != null && next.StartTime.TotalMilliseconds - p.EndTime.TotalMilliseconds > 150) { text = new StringBuilder(); while (text.Length < 34) { text.Append(' '); } sb.AppendLine(string.Format("{0}{1}", text, EncodeTimeCode(p.EndTime))); } } return sb.ToString(); }
public Paragraph GetSelectedParagraph(Subtitle subtitle) { if (subtitle != null && SelectedItems.Count > 0) return subtitle.GetParagraphOrDefault(SelectedItems[0].Index); return null; }
public static string FixHyphensRemove(Subtitle subtitle, int i) { Paragraph p = subtitle.Paragraphs[i]; string text = p.Text; if (text.TrimStart().StartsWith('-') || text.TrimStart().StartsWith("<i>-", StringComparison.OrdinalIgnoreCase) || text.TrimStart().StartsWith("<i> -", StringComparison.OrdinalIgnoreCase) || text.Contains(Environment.NewLine + '-') || text.Contains(Environment.NewLine + " -") || text.Contains(Environment.NewLine + "<i>-") || text.Contains(Environment.NewLine + "<i> -") || text.Contains(Environment.NewLine + "<I>-") || text.Contains(Environment.NewLine + "<I> -")) { Paragraph prev = subtitle.GetParagraphOrDefault(i - 1); if (prev == null || !HtmlUtil.RemoveHtmlTags(prev.Text).TrimEnd().EndsWith('-') || HtmlUtil.RemoveHtmlTags(prev.Text).TrimEnd().EndsWith("--", StringComparison.Ordinal)) { string[] noTaglines = HtmlUtil.RemoveHtmlTags(p.Text).SplitToLines(); int startHyphenCount = noTaglines.Count(line => line.TrimStart().StartsWith('-')); if (startHyphenCount == 1) { bool remove = true; string[] noTagparts = HtmlUtil.RemoveHtmlTags(text).SplitToLines(); if (noTagparts.Length == 2) { if (noTagparts[0].TrimStart().StartsWith('-') && noTagparts[1].Contains(": ")) { remove = false; } if (noTagparts[1].TrimStart().StartsWith('-') && noTagparts[0].Contains(": ")) { remove = false; } } if (remove) { int idx = text.IndexOf('-'); StripableText st = new StripableText(text); if (idx < 5 && st.Pre.Length >= idx) { text = text.Remove(idx, 1).TrimStart(); idx = text.IndexOf('-'); st = new StripableText(text); if (idx < 5 && idx >= 0 && st.Pre.Length >= idx) { text = text.Remove(idx, 1).TrimStart(); st = new StripableText(text); } idx = text.IndexOf('-'); if (idx < 5 && idx >= 0 && st.Pre.Length >= idx) { text = text.Remove(idx, 1).TrimStart(); } text = RemoveSpacesBeginLine(text); } else { int indexOfNewLine = text.IndexOf(Environment.NewLine, StringComparison.Ordinal); if (indexOfNewLine > 0) { idx = text.IndexOf('-', indexOfNewLine); if (idx >= 0 && indexOfNewLine + 5 > indexOfNewLine) { text = text.Remove(idx, 1).TrimStart().Replace(Environment.NewLine + " ", Environment.NewLine); idx = text.IndexOf('-', indexOfNewLine); if (idx >= 0 && indexOfNewLine + 5 > indexOfNewLine) { text = text.Remove(idx, 1).TrimStart(); text = RemoveSpacesBeginLine(text); } } } } } } } } else if (text.StartsWith("<font ", StringComparison.Ordinal)) { Paragraph prev = subtitle.GetParagraphOrDefault(i - 1); if (prev == null || !HtmlUtil.RemoveHtmlTags(prev.Text).TrimEnd().EndsWith('-') || HtmlUtil.RemoveHtmlTags(prev.Text).TrimEnd().EndsWith("--", StringComparison.Ordinal)) { StripableText st = new StripableText(text); if (st.Pre.EndsWith('-') || st.Pre.EndsWith("- ", StringComparison.Ordinal)) { text = st.Pre.TrimEnd('-', ' ') + st.StrippedText + st.Post; } } } return text; }
public override void LoadSubtitle(Subtitle subtitle, List<string> lines, string fileName) { this._errorCount = 0; Paragraph p = null; foreach (string line in lines) { string s = line.Trim(); if (s.Length > 4 && s[2] == ':' && regexTimeCodes.Match(s).Success) { if (p != null && !string.IsNullOrEmpty(p.Text)) { subtitle.Paragraphs.Add(p); } p = new Paragraph(); try { string[] arr = s.Substring(0, 8).Split(':'); if (arr.Length == 3) { int hours = int.Parse(arr[0]); int minutes = int.Parse(arr[1]); int seconds = int.Parse(arr[2]); p.StartTime = new TimeCode(hours, minutes, seconds, 0); string text = s.Remove(0, 12).Trim(); p.Text = text; } } catch { this._errorCount++; } } else if (p != null && regexNumberAndText.Match(s).Success) { if (p.Text.Length > 1000) { this._errorCount += 100; return; } string text = s.Remove(0, 2).Trim(); p.Text = (p.Text + Environment.NewLine + text).Trim(); } else if (s.Length > 0 && !Utilities.IsInteger(s)) { this._errorCount++; } } if (p != null && !string.IsNullOrEmpty(p.Text)) { subtitle.Paragraphs.Add(p); } int index = 1; foreach (Paragraph paragraph in subtitle.Paragraphs) { Paragraph next = subtitle.GetParagraphOrDefault(index); if (next != null) { paragraph.EndTime.TotalMilliseconds = next.StartTime.TotalMilliseconds - 1; } index++; } subtitle.RemoveEmptyLines(); subtitle.Renumber(); }
public override void LoadSubtitle(Subtitle subtitle, List<string> lines, string fileName) { _errorCount = 0; var sb = new StringBuilder(); foreach (string l in lines) sb.AppendLine(l); string allInput = sb.ToString(); string allInputLower = allInput.ToLower(); const string syncTag = "<p "; var syncStartPos = allInputLower.IndexOf(syncTag, StringComparison.Ordinal); int index = syncStartPos + syncTag.Length; while (syncStartPos >= 0) { var syncEndPos = allInputLower.IndexOf("</p>", index, StringComparison.Ordinal); if (syncEndPos > 0) { string s = allInput.Substring(syncStartPos + 2, syncEndPos - syncStartPos - 2); int indexOfBegin = s.IndexOf(" data-begin=", StringComparison.Ordinal); int indexOfAttributesEnd = s.IndexOf('>'); if (indexOfBegin >= 0 && indexOfAttributesEnd > indexOfBegin) { string text = s.Substring(indexOfAttributesEnd + 1).Trim(); text = text.Replace("<br>", Environment.NewLine); text = text.Replace("<br/>", Environment.NewLine); text = text.Replace("<br />", Environment.NewLine); text = text.Replace("\t", " "); while (text.Contains(" ")) text = text.Replace(" ", " "); while (text.Contains(Environment.NewLine + " ")) text = text.Replace(Environment.NewLine + " ", Environment.NewLine); while (text.Contains(Environment.NewLine + Environment.NewLine)) text = text.Replace(Environment.NewLine + Environment.NewLine, Environment.NewLine); string begin = s.Substring(indexOfBegin + " data-begin=".Length); var tcBegin = new StringBuilder(); for (int i = 0; i <= 10; i++) { if (begin.Length > i && @"0123456789:.".Contains(begin[i])) { tcBegin.Append(begin[i]); } } var tcEnd = new StringBuilder(); var indexOfEnd = s.IndexOf(" data-end=", StringComparison.Ordinal); if (indexOfEnd >= 0) { string end = s.Substring(indexOfEnd + " data-end=".Length); for (int i = 0; i <= 10; i++) { if (end.Length > i && @"0123456789:.".Contains(end[i])) { tcEnd.Append(end[i]); } } } var arr = tcBegin.ToString().Split(new[] { '.', ':' }, StringSplitOptions.RemoveEmptyEntries); if (arr.Length == 3 || arr.Length == 4) { var p = new Paragraph(); p.Text = text; try { p.StartTime = DecodeTimeCode(arr); if (tcEnd.Length > 0) { arr = tcEnd.ToString().Split(new[] { '.', ':' }, StringSplitOptions.RemoveEmptyEntries); p.EndTime = DecodeTimeCode(arr); } subtitle.Paragraphs.Add(p); } catch { _errorCount++; } } } } if (syncEndPos <= 0) { syncStartPos = -1; } else { syncStartPos = allInputLower.IndexOf(syncTag, syncEndPos, StringComparison.Ordinal); index = syncStartPos + syncTag.Length; } } index = 1; foreach (Paragraph paragraph in subtitle.Paragraphs) { Paragraph next = subtitle.GetParagraphOrDefault(index); if (next != null) { paragraph.EndTime.TotalMilliseconds = next.StartTime.TotalMilliseconds - 1; } else if (paragraph.EndTime.TotalMilliseconds < 50) { paragraph.EndTime.TotalMilliseconds = paragraph.StartTime.TotalMilliseconds + Utilities.GetOptimalDisplayMilliseconds(paragraph.Text); } if (paragraph.Duration.TotalMilliseconds > Configuration.Settings.General.SubtitleMaximumDisplayMilliseconds) { paragraph.EndTime.TotalMilliseconds = paragraph.StartTime.TotalMilliseconds + Utilities.GetOptimalDisplayMilliseconds(paragraph.Text); } index++; } foreach (Paragraph p2 in subtitle.Paragraphs) p2.Text = WebUtility.HtmlDecode(p2.Text); subtitle.Renumber(); }
public override void LoadSubtitle(Subtitle subtitle, List<string> lines, string fileName) { _errorCount = 0; Paragraph p = null; subtitle.Paragraphs.Clear(); foreach (string line in lines) { string s = line.Trim(); var match = regexTimeCodes2.Match(s); if (match.Success) { s = s.Substring(0, match.Index + 13).Trim(); } match = regexTimeCodes1.Match(s); if (match.Success && match.Index > 13) { string text = s.Substring(0, match.Index).Trim(); string timeCode = s.Substring(match.Index).Trim(); string[] startParts = timeCode.Split(new[] { ':' }, StringSplitOptions.RemoveEmptyEntries); if (startParts.Length == 4) { try { p = new Paragraph(DecodeTimeCode(startParts), new TimeCode(0, 0, 0, 0), text); subtitle.Paragraphs.Add(p); } catch (Exception exception) { _errorCount++; System.Diagnostics.Debug.WriteLine(exception.Message); } } } else if (string.IsNullOrWhiteSpace(line) || regexTimeCodes1.IsMatch(" " + s)) { // skip empty lines } else if (!string.IsNullOrWhiteSpace(line) && p != null) { _errorCount++; } } for (int i = 0; i < subtitle.Paragraphs.Count; i++) { Paragraph current = subtitle.Paragraphs[i]; Paragraph next = subtitle.GetParagraphOrDefault(i + 1); if (next != null) current.EndTime.TotalMilliseconds = next.StartTime.TotalMilliseconds - Configuration.Settings.General.MinimumMillisecondsBetweenLines; else current.EndTime.TotalMilliseconds = current.StartTime.TotalMilliseconds + Utilities.GetOptimalDisplayMilliseconds(current.Text); if (current.Duration.TotalMilliseconds > Configuration.Settings.General.SubtitleMaximumDisplayMilliseconds) current.EndTime.TotalMilliseconds = current.StartTime.TotalMilliseconds + Configuration.Settings.General.SubtitleMaximumDisplayMilliseconds; } subtitle.RemoveEmptyLines(); subtitle.Renumber(); }
public Subtitle MergeLineswithSameTextInSubtitle(Subtitle subtitle, List<int> mergedIndexes, out int numberOfMerges, bool clearFixes, bool fixIncrementing, bool lineAfterNext, int maxMsBetween) { var removed = new List<int>(); if (!_loading) listViewFixes.ItemChecked -= listViewFixes_ItemChecked; if (clearFixes) listViewFixes.Items.Clear(); numberOfMerges = 0; var mergedSubtitle = new Subtitle(); bool lastMerged = false; Paragraph p = null; var lineNumbers = new StringBuilder(); for (int i = 1; i < subtitle.Paragraphs.Count; i++) { if (!lastMerged) { p = new Paragraph(subtitle.GetParagraphOrDefault(i - 1)); mergedSubtitle.Paragraphs.Add(p); } Paragraph next = subtitle.GetParagraphOrDefault(i); Paragraph afterNext = subtitle.GetParagraphOrDefault(i + 1); if (next != null) { if ((QualifiesForMerge(p, next, maxMsBetween) || (fixIncrementing && QualifiesForMergeIncrement(p, next, maxMsBetween))) && IsFixAllowed(p)) { p.Text = next.Text; p.EndTime = next.EndTime; if (lastMerged) { lineNumbers.Append(next.Number); lineNumbers.Append(','); } else { lineNumbers.Append(p.Number); lineNumbers.Append(','); lineNumbers.Append(next.Number); lineNumbers.Append(','); } lastMerged = true; removed.Add(i); numberOfMerges++; if (!mergedIndexes.Contains(i)) mergedIndexes.Add(i); if (!mergedIndexes.Contains(i - 1)) mergedIndexes.Add(i - 1); } else if (lineAfterNext && QualifiesForMerge(p, afterNext, maxMsBetween) && p.Duration.TotalMilliseconds > afterNext.Duration.TotalMilliseconds && IsFixAllowed(p)) { removed.Add(i + 2); numberOfMerges++; if (lastMerged) { lineNumbers.Append(afterNext.Number); lineNumbers.Append(','); } else { lineNumbers.Append(p.Number); lineNumbers.Append(','); lineNumbers.Append(afterNext.Number); lineNumbers.Append(','); } lastMerged = true; if (!mergedIndexes.Contains(i)) mergedIndexes.Add(i); if (!mergedIndexes.Contains(i - 1)) mergedIndexes.Add(i - 1); } else { lastMerged = false; } } else { lastMerged = false; } if (!removed.Contains(i) && lineNumbers.Length > 0 && clearFixes) { AddToListView(p, lineNumbers.ToString(), p.Text); lineNumbers = new StringBuilder(); } } if (lineNumbers.Length > 0 && clearFixes && p != null) { AddToListView(p, lineNumbers.ToString(), p.Text); } if (!lastMerged) mergedSubtitle.Paragraphs.Add(new Paragraph(subtitle.GetParagraphOrDefault(subtitle.Paragraphs.Count - 1))); if (!_loading) listViewFixes.ItemChecked += listViewFixes_ItemChecked; mergedSubtitle.Renumber(); return mergedSubtitle; }
public override string ToText(Subtitle subtitle, string title) { var sb = new StringBuilder(); sb.Append("{\"text_tees\":["); for (int i = 0; i < subtitle.Paragraphs.Count; i++) { Paragraph p = subtitle.Paragraphs[i]; sb.Append(p.StartTime.TotalMilliseconds); sb.Append(','); sb.Append(p.EndTime.TotalMilliseconds); if (i < subtitle.Paragraphs.Count - 1) sb.Append(','); } sb.Append("],"); sb.Append("\"text_target\":["); for (int i = 0; i < subtitle.Paragraphs.Count; i++) { sb.Append("[\"w1\",\"w3\"],[\"w1\",\"w3\"]"); if (i < subtitle.Paragraphs.Count - 1) sb.Append(','); } sb.Append("],"); sb.Append("\"text_content\":["); for (int i = 0; i < subtitle.Paragraphs.Count; i++) { sb.Append('['); Paragraph p = subtitle.Paragraphs[i]; var lines = p.Text.Replace(Environment.NewLine, "\n").Split('\n'); for (int j = 0; j < lines.Length; j++) { sb.Append('"'); sb.Append(Json.EncodeJsonText(lines[j])); sb.Append('"'); if (j < lines.Length - 1) sb.Append(','); } sb.Append("],"); if (i < subtitle.Paragraphs.Count - 1) sb.Append("[\"\",\"\"],"); else sb.Append("[\"\",\"\"]"); } sb.Append("],"); sb.Append("\"text_styles\":["); for (int i = 0; i < subtitle.Paragraphs.Count; i++) { sb.Append("[\"s1\",\"s2\"],[\"s1\",\"s2\"]"); if (i < subtitle.Paragraphs.Count - 1) sb.Append(','); } sb.Append("],"); sb.Append("\"timerange\":["); Paragraph timerageP = subtitle.GetParagraphOrDefault(0); if (timerageP == null) sb.Append('0'); else sb.Append(timerageP.StartTime.TotalMilliseconds); sb.Append(','); timerageP = subtitle.GetParagraphOrDefault(subtitle.Paragraphs.Count - 1); if (timerageP == null) sb.Append('0'); else sb.Append(timerageP.EndTime.TotalMilliseconds); sb.Append(']'); sb.Append('}'); return sb.ToString().Trim(); }
private static Subtitle ImportTimeCodesOnSameSeparateLine(List <string> lines) { Paragraph p = null; var subtitle = new Subtitle(); var sb = new StringBuilder(); char[] splitChars = { ' ', '\t' }; for (int idx = 0; idx < lines.Count; idx++) { string line = lines[idx]; string lineWithPerhapsOnlyNumbers = GetLineWithPerhapsOnlyNumbers(line); bool allNumbers = lineWithPerhapsOnlyNumbers.Length > 0; foreach (char c in lineWithPerhapsOnlyNumbers) { if (!char.IsDigit(c)) { allNumbers = false; break; } } if (allNumbers && lineWithPerhapsOnlyNumbers.Length > 5) { if (line.Contains("->")) { line = line.RemoveChar(' '); } string[] arr = line.Replace('-', ' ').Replace('>', ' ').Replace('{', ' ').Replace('}', ' ').Replace('[', ' ').Replace(']', ' ').Trim().Split(splitChars, StringSplitOptions.RemoveEmptyEntries); if (arr.Length == 2) { string[] start = arr[0].Trim().Split(ExpectedSplitChars, StringSplitOptions.RemoveEmptyEntries); string[] end = arr[1].Trim().Split(ExpectedSplitChars, StringSplitOptions.RemoveEmptyEntries); if ((start.Length == 3 || start.Length == 4) && (end.Length == 3 || end.Length == 4)) { if (p != null) { p.Text = sb.ToString().Trim(); subtitle.Paragraphs.Add(p); } p = new Paragraph(); sb.Clear(); p.StartTime = DecodeTime(start); p.EndTime = DecodeTime(end); } } else if (arr.Length > 3) { string[] start; string[] end; if (arr[0].Length > 9) { start = arr[0].Trim().Split(ExpectedSplitChars, StringSplitOptions.RemoveEmptyEntries); end = arr[1].Trim().Split(ExpectedSplitChars, StringSplitOptions.RemoveEmptyEntries); } else { start = arr[1].Trim().Split(ExpectedSplitChars, StringSplitOptions.RemoveEmptyEntries); end = arr[2].Trim().Split(ExpectedSplitChars, StringSplitOptions.RemoveEmptyEntries); } if ((start.Length == 3 || start.Length == 4) && (end.Length == 3 || end.Length == 4)) { if (p != null) { p.Text = sb.ToString().Trim(); subtitle.Paragraphs.Add(p); } p = new Paragraph(); sb = new StringBuilder(); p.StartTime = DecodeTime(start); p.EndTime = DecodeTime(end); } } } if (p != null && !allNumbers && line.Length > 1) { line = line.Trim(); if (line.StartsWith("}{}", StringComparison.Ordinal) || line.StartsWith("][]", StringComparison.Ordinal)) { line = line.Remove(0, 3); } sb.AppendLine(line.Trim()); } } if (p != null) { p.Text = sb.ToString().Trim(); subtitle.Paragraphs.Add(p); } double averateDuration = 0; foreach (Paragraph a in subtitle.Paragraphs) { double d = a.Duration.TotalSeconds; if (d > 10) { d = 8; } averateDuration += d; } averateDuration = averateDuration / subtitle.Paragraphs.Count; if (averateDuration < 0.2 || (averateDuration < 0.5 && subtitle.Paragraphs.Count > 100 && subtitle.Paragraphs[subtitle.Paragraphs.Count - 1].StartTime.TotalSeconds < 140 && subtitle.Paragraphs[subtitle.Paragraphs.Count - 2].StartTime.TotalSeconds < 140)) { subtitle = ImportTimeCodesOnSameSeperateLineNoMilliseconds(lines); int i = 0; foreach (Paragraph a in subtitle.Paragraphs) { i++; var next = subtitle.GetParagraphOrDefault(i); if (next != null && a.EndTime.TotalMilliseconds >= next.StartTime.TotalMilliseconds) { a.EndTime.TotalMilliseconds = next.StartTime.TotalMilliseconds - Configuration.Settings.General.MinimumMillisecondsBetweenLines; } } return(subtitle); } subtitle.Renumber(); return(subtitle); }
private static Subtitle ImportTimeCodesAndTextOnSameLine(List <string> lines) { var regexTimeCodes1 = new Regex(@"\d+[:.,;]{1}\d\d[:.,;]{1}\d\d[:.,;]{1}\d+", RegexOptions.Compiled); var regexTimeCodes2 = new Regex(@"\d+[:.,;]{1}\d\d[:.,;]{1}\d+", RegexOptions.Compiled); Paragraph p = null; var subtitle = new Subtitle(); var sb = new StringBuilder(); var isFirstLineNumber = false; var hasOnlyOneTimeCode = true; int count = -1; for (int idx = 0; idx < lines.Count; idx++) { string line = lines[idx]; var matches = regexTimeCodes1.Matches(line); if (matches.Count == 0) { matches = regexTimeCodes2.Matches(line); if (!string.IsNullOrWhiteSpace(line)) { hasOnlyOneTimeCode = false; } } if (matches.Count == 2) { hasOnlyOneTimeCode = false; var start = matches[0].Value.Split(ExpectedSplitChars, StringSplitOptions.RemoveEmptyEntries); if (int.TryParse(start[0], out var i)) { if (count == -1 && i < 2) { count = i; } if (count != i) { isFirstLineNumber = false; break; } count++; } } if (count > 2) { isFirstLineNumber = true; } } for (int idx = 0; idx < lines.Count; idx++) { string line = lines[idx]; if (isFirstLineNumber) { while (line.Length > 0 && char.IsDigit(line[0])) { line = line.Remove(0, 1); } } var matches = regexTimeCodes1.Matches(line); if (matches.Count == 0) { matches = regexTimeCodes2.Matches(line); } if (matches.Count == 1 && hasOnlyOneTimeCode) { var start = matches[0].ToString().Split(ExpectedSplitChars, StringSplitOptions.RemoveEmptyEntries); if (start.Length == 3 || start.Length == 4) { if (p != null) { p.Text = sb.ToString().Trim(); subtitle.Paragraphs.Add(p); } p = new Paragraph(); sb.Clear(); p.StartTime = DecodeTime(start); } if (matches[0].Index < 9) { line = line.Remove(0, matches[0].Index); } line = line.Replace(matches[0].ToString(), string.Empty); line = line.Trim().TrimStart(']'); if (Utilities.IsInteger(line.RemoveChar('[').RemoveChar(']'))) { line = string.Empty; } if (line.StartsWith("}{}", StringComparison.Ordinal) || line.StartsWith("][]", StringComparison.Ordinal)) { line = line.Remove(0, 3); } line = line.Trim(); } else if (matches.Count == 2) { var start = matches[0].ToString().Split(ExpectedSplitChars, StringSplitOptions.RemoveEmptyEntries); var end = matches[1].ToString().Split(ExpectedSplitChars, StringSplitOptions.RemoveEmptyEntries); if ((start.Length == 3 || start.Length == 4) && (end.Length == 3 || end.Length == 4)) { if (p != null) { p.Text = sb.ToString().Trim(); subtitle.Paragraphs.Add(p); } p = new Paragraph(); sb.Clear(); p.StartTime = DecodeTime(start); p.EndTime = DecodeTime(end); } if (matches[0].Index < 9) { line = line.Remove(0, matches[0].Index); } line = line.Replace(matches[0].ToString(), string.Empty); line = line.Replace(matches[1].ToString(), string.Empty); line = line.Trim().TrimStart(']'); if (Utilities.IsInteger(line.RemoveChar('[').RemoveChar(']'))) { line = string.Empty; } if (line.StartsWith("}{}", StringComparison.Ordinal) || line.StartsWith("][]", StringComparison.Ordinal)) { line = line.Remove(0, 3); } line = line.Trim(); } if (p != null && line.Length > 1) { sb.AppendLine(line.Trim()); } } if (p != null) { p.Text = sb.ToString().Trim(); subtitle.Paragraphs.Add(p); } // fix end time if (hasOnlyOneTimeCode) { for (var index = 0; index < subtitle.Paragraphs.Count; index++) { var paragraph = subtitle.Paragraphs[index]; var next = subtitle.GetParagraphOrDefault(index + 1); var optimalDurationMs = Utilities.GetOptimalDisplayMilliseconds(paragraph.Text); if (next == null) { paragraph.Duration.TotalMilliseconds = optimalDurationMs; } else { if (next.StartTime.TotalMilliseconds < paragraph.StartTime.TotalMilliseconds + optimalDurationMs * 2) { paragraph.EndTime.TotalMilliseconds = next.StartTime.TotalMilliseconds; } else { paragraph.EndTime.TotalMilliseconds = paragraph.StartTime.TotalMilliseconds + optimalDurationMs; } } } } // remove all equal headers if (subtitle.Paragraphs.Count > 5) { string prefix = subtitle.Paragraphs[0].Text; foreach (var paragraph in subtitle.Paragraphs) { string text = paragraph.Text.Trim(); var newPrefix = new StringBuilder(); int i = 0; while (i < prefix.Length && i < text.Length && text[i] == prefix[i]) { newPrefix.Append(text[i]); i++; } prefix = newPrefix.ToString(); } if (prefix.Length > 3 && prefix[1] == ':' && prefix[2] == '\\') { prefix = string.Empty; } if (prefix.Length > 0) { foreach (var paragraph in subtitle.Paragraphs) { string text = paragraph.Text.Trim(); if (text.StartsWith(prefix, StringComparison.Ordinal)) { paragraph.Text = text.Remove(0, prefix.Length); } } } } subtitle.Renumber(); return(subtitle); }
public override void LoadSubtitle(Subtitle subtitle, List<string> lines, string fileName) { // 00:18:02: (斉藤)失礼な大人って! (悠子)何言ってんのあんた? Paragraph p = null; subtitle.Paragraphs.Clear(); _errorCount = 0; foreach (string line in lines) { string s = line.Trim(); if (regexTimeCodes.IsMatch(s)) { var temp = s.Substring(0, 8); string[] startParts = temp.Split(new[] { ':' }, StringSplitOptions.RemoveEmptyEntries); if (startParts.Length == 3) { try { string text = s.Remove(0, 10).Trim(); text = text.Replace(" ", Environment.NewLine); p = new Paragraph(DecodeTimeCode(startParts), new TimeCode(0, 0, 0, 0), text); subtitle.Paragraphs.Add(p); } catch (Exception exception) { _errorCount++; System.Diagnostics.Debug.WriteLine(exception.Message); } } } else if (string.IsNullOrWhiteSpace(line)) { // skip empty lines } else if (p != null) { _errorCount++; } } for (int i = 0; i < subtitle.Paragraphs.Count; i++) { Paragraph current = subtitle.Paragraphs[i]; Paragraph next = subtitle.GetParagraphOrDefault(i + 1); if (next != null) current.EndTime.TotalMilliseconds = next.StartTime.TotalMilliseconds - Configuration.Settings.General.MinimumMillisecondsBetweenLines; else current.EndTime.TotalMilliseconds = current.StartTime.TotalMilliseconds + Utilities.GetOptimalDisplayMilliseconds(current.Text); if (current.Duration.TotalMilliseconds > Configuration.Settings.General.SubtitleMaximumDisplayMilliseconds) current.EndTime.TotalMilliseconds = current.StartTime.TotalMilliseconds + Configuration.Settings.General.SubtitleMaximumDisplayMilliseconds; } subtitle.Renumber(); }
/// <summary> /// The load subtitle. /// </summary> /// <param name="subtitle"> /// The subtitle. /// </param> /// <param name="lines"> /// The lines. /// </param> /// <param name="fileName"> /// The file name. /// </param> public override void LoadSubtitle(Subtitle subtitle, List<string> lines, string fileName) { this._errorCount = 0; StringBuilder sb = new StringBuilder(); foreach (string s in lines) { sb.Append(s); } string allText = sb.ToString(); if (!allText.Contains("\"words\"") && !allText.Contains("'words'")) { return; } List<string> words = Json.ReadArray(allText, "words"); foreach (string word in words) { List<string> elements = Json.ReadArray(word); if (elements.Count == 2) { string milliseconds = elements[0].Trim('"').Trim(); string text = elements[1].Trim(); if (text.StartsWith('"')) { text = text.Remove(0, 1); } if (text.EndsWith('"')) { text = text.Remove(text.Length - 1, 1); } long number; if (long.TryParse(milliseconds, out number)) { subtitle.Paragraphs.Add(new Paragraph(text, number, number)); } else { this._errorCount++; } } } sb = new StringBuilder(); Subtitle sub = new Subtitle(); double startMilliseconds = 0; if (subtitle.Paragraphs.Count > 0) { startMilliseconds = subtitle.Paragraphs[0].StartTime.TotalMilliseconds; } for (int i = 0; i < subtitle.Paragraphs.Count - 1; i++) { Paragraph p = subtitle.Paragraphs[i]; Paragraph next = subtitle.Paragraphs[i + 1]; Paragraph prev = subtitle.GetParagraphOrDefault(i - 1); if (sb.Length + p.Text.Length > (Configuration.Settings.General.SubtitleLineMaximumLength * 2) - 15) { // text too big Paragraph newParagraph = new Paragraph(sb.ToString(), startMilliseconds, prev.EndTime.TotalMilliseconds); sub.Paragraphs.Add(newParagraph); sb = new StringBuilder(); if (!string.IsNullOrWhiteSpace(p.Text)) { sb.Append(p.Text); startMilliseconds = p.StartTime.TotalMilliseconds; } } else if (next.StartTime.TotalMilliseconds - p.EndTime.TotalMilliseconds > 2000) { // long time to next sub if (!string.IsNullOrWhiteSpace(p.Text)) { sb.Append(' '); sb.Append(p.Text); } Paragraph newParagraph = new Paragraph(sb.ToString(), startMilliseconds, next.StartTime.TotalMilliseconds); sub.Paragraphs.Add(newParagraph); sb = new StringBuilder(); startMilliseconds = next.StartTime.TotalMilliseconds; } else if (string.IsNullOrWhiteSpace(p.Text)) { // empty text line if (string.IsNullOrWhiteSpace(next.Text) && sb.Length > 0) { Paragraph newParagraph = new Paragraph(sb.ToString(), startMilliseconds, next.StartTime.TotalMilliseconds); sub.Paragraphs.Add(newParagraph); sb = new StringBuilder(); } } else { // just add word to current sub if (sb.Length == 0) { startMilliseconds = p.StartTime.TotalMilliseconds; } if (!string.IsNullOrWhiteSpace(p.Text)) { sb.Append(' '); sb.Append(p.Text); } } } if (sb.Length > 0) { Paragraph newParagraph = new Paragraph(sb.ToString().Trim(), startMilliseconds, Utilities.GetOptimalDisplayMilliseconds(sb.ToString())); sub.Paragraphs.Add(newParagraph); } subtitle.Paragraphs.Clear(); foreach (Paragraph p in sub.Paragraphs) { p.Text = Utilities.AutoBreakLine(p.Text); subtitle.Paragraphs.Add(new Paragraph(p)); } subtitle.RemoveEmptyLines(); subtitle.Renumber(); }
public Subtitle MergeShortLinesInSubtitle(Subtitle subtitle, List<int> mergedIndexes, out int numberOfMerges, double maxMillisecondsBetweenLines, int maxCharacters, bool clearFixes) { listViewFixes.ItemChecked -= listViewFixes_ItemChecked; if (clearFixes) listViewFixes.Items.Clear(); numberOfMerges = 0; string language = Utilities.AutoDetectGoogleLanguage(subtitle); var mergedSubtitle = new Subtitle(); bool lastMerged = false; Paragraph p = null; var lineNumbers = new StringBuilder(); for (int i = 1; i < subtitle.Paragraphs.Count; i++) { if (!lastMerged) { p = new Paragraph(subtitle.GetParagraphOrDefault(i - 1)); mergedSubtitle.Paragraphs.Add(p); } Paragraph next = subtitle.GetParagraphOrDefault(i); if (next != null) { if (QualifiesForMerge(p, next, maxMillisecondsBetweenLines, maxCharacters) && IsFixAllowed(p)) { if (GetStartTag(p.Text) == GetStartTag(next.Text) && GetEndTag(p.Text) == GetEndTag(next.Text)) { string s1 = p.Text.Trim(); s1 = s1.Substring(0, s1.Length - GetEndTag(s1).Length); string s2 = next.Text.Trim(); s2 = s2.Substring(GetStartTag(s2).Length); p.Text = Utilities.AutoBreakLine(s1 + Environment.NewLine + s2, language); } else { p.Text = Utilities.AutoBreakLine(p.Text + Environment.NewLine + next.Text, language); } p.EndTime = next.EndTime; if (lastMerged) { lineNumbers.Append(next.Number); lineNumbers.Append(','); } else { lineNumbers.Append(p.Number); lineNumbers.Append(','); lineNumbers.Append(next.Number); lineNumbers.Append(','); } lastMerged = true; numberOfMerges++; if (!mergedIndexes.Contains(i)) mergedIndexes.Add(i); if (!mergedIndexes.Contains(i - 1)) mergedIndexes.Add(i - 1); } else { lastMerged = false; } } else { lastMerged = false; } if (!lastMerged && lineNumbers.Length > 0 && clearFixes) { AddToListView(p, lineNumbers.ToString(), p.Text); lineNumbers = new StringBuilder(); } } if (!lastMerged) mergedSubtitle.Paragraphs.Add(new Paragraph(subtitle.GetParagraphOrDefault(subtitle.Paragraphs.Count - 1))); listViewFixes.ItemChecked += listViewFixes_ItemChecked; return mergedSubtitle; }
/// <summary> /// The save. /// </summary> /// <param name="fileName"> /// The file name. /// </param> /// <param name="subtitle"> /// The subtitle. /// </param> /// <param name="batchMode"> /// The batch mode. /// </param> public static void Save(string fileName, Subtitle subtitle, bool batchMode) { EbuGeneralSubtitleInformation header = new EbuGeneralSubtitleInformation(); using (EbuSaveOptions saveOptions = new EbuSaveOptions()) { if (subtitle.Header != null && subtitle.Header.Length > 1024 && (subtitle.Header.Contains("STL24") || subtitle.Header.Contains("STL25") || subtitle.Header.Contains("STL29") || subtitle.Header.Contains("STL30"))) { header = ReadHeader(Encoding.UTF8.GetBytes(subtitle.Header)); saveOptions.Initialize(header, 0, null, subtitle); } else { saveOptions.Initialize(header, 0, fileName, subtitle); } if (!batchMode && saveOptions.ShowDialog() != DialogResult.OK) { return; } using (FileStream fs = new FileStream(fileName, FileMode.Create, FileAccess.Write)) { header.TotalNumberOfSubtitles = subtitle.Paragraphs.Count.ToString("D5"); // seems to be 1 higher than actual number of subtitles header.TotalNumberOfTextAndTimingInformationBlocks = header.TotalNumberOfSubtitles; string today = string.Format("{0:yyMMdd}", DateTime.Now); if (today.Length == 6) { header.CreationDate = today; header.RevisionDate = today; } Paragraph firstParagraph = subtitle.GetParagraphOrDefault(0); if (firstParagraph != null) { TimeCode tc = firstParagraph.StartTime; string firstTimeCode = string.Format("{0:00}{1:00}{2:00}{3:00}", tc.Hours, tc.Minutes, tc.Seconds, EbuTextTimingInformation.GetFrameFromMilliseconds(tc.Milliseconds, header.FrameRate)); if (firstTimeCode.Length == 8) { header.TimeCodeFirstInCue = firstTimeCode; } } byte[] buffer = Encoding.Default.GetBytes(header.ToString()); fs.Write(buffer, 0, buffer.Length); int subtitleNumber = 0; foreach (Paragraph p in subtitle.Paragraphs) { EbuTextTimingInformation tti = new EbuTextTimingInformation(); int rows; if (!int.TryParse(header.MaximumNumberOfDisplayableRows, out rows)) { rows = 23; } if (header.DisplayStandardCode == "1" || header.DisplayStandardCode == "2") { // teletext rows = 23; } else if (header.DisplayStandardCode == "0" && header.MaximumNumberOfDisplayableRows == "02") { // open subtitling rows = 15; } if (p.Text.StartsWith("{\\an7}", StringComparison.Ordinal) || p.Text.StartsWith("{\\an8}", StringComparison.Ordinal) || p.Text.StartsWith("{\\an9}", StringComparison.Ordinal)) { tti.VerticalPosition = 1; // top (vertical) } else if (p.Text.StartsWith("{\\an4}", StringComparison.Ordinal) || p.Text.StartsWith("{\\an5}", StringComparison.Ordinal) || p.Text.StartsWith("{\\an6}", StringComparison.Ordinal)) { tti.VerticalPosition = (byte)(rows / 2); // middle (vertical) } else { int startRow = (rows - 1) - Utilities.CountTagInText(p.Text, Environment.NewLine) * 2; if (startRow < 0) { startRow = 0; } tti.VerticalPosition = (byte)startRow; // bottom (vertical) } tti.JustificationCode = saveOptions.JustificationCode; if (p.Text.StartsWith("{\\an1}", StringComparison.Ordinal) || p.Text.StartsWith("{\\an4}", StringComparison.Ordinal) || p.Text.StartsWith("{\\an7}", StringComparison.Ordinal)) { tti.JustificationCode = 1; // 01h=left-justified text } else if (p.Text.StartsWith("{\\an3}", StringComparison.Ordinal) || p.Text.StartsWith("{\\an6}", StringComparison.Ordinal) || p.Text.StartsWith("{\\an9}", StringComparison.Ordinal)) { tti.JustificationCode = 3; // 03h=right-justified } else { // If it's not left- or right-justified, it's centred. tti.JustificationCode = 2; // 02h=centred text } tti.SubtitleNumber = (ushort)subtitleNumber; tti.TextField = p.Text; int startTag = tti.TextField.IndexOf('}'); if (tti.TextField.StartsWith("{\\", StringComparison.Ordinal) && startTag > 0 && startTag < 10) { tti.TextField = tti.TextField.Remove(0, startTag + 1); } tti.TimeCodeInHours = p.StartTime.Hours; tti.TimeCodeInMinutes = p.StartTime.Minutes; tti.TimeCodeInSeconds = p.StartTime.Seconds; tti.TimeCodeInMilliseconds = p.StartTime.Milliseconds; tti.TimeCodeOutHours = p.EndTime.Hours; tti.TimeCodeOutMinutes = p.EndTime.Minutes; tti.TimeCodeOutSeconds = p.EndTime.Seconds; tti.TimeCodeOutMilliseconds = p.EndTime.Milliseconds; buffer = tti.GetBytes(header); fs.Write(buffer, 0, buffer.Length); subtitleNumber++; } } } }
public override void LoadSubtitle(Subtitle subtitle, List<string> lines, string fileName) { this._errorCount = 0; subtitle.Paragraphs.Clear(); subtitle.Header = null; byte[] buffer = FileUtil.ReadAllBytesShared(fileName); string title = Encoding.ASCII.GetString(buffer, 82, 66); int i = 128; Encoding encoding = Encoding.GetEncoding(1252); while (i < buffer.Length - 66) { if (buffer[i] == 0xff && buffer[i + 1] == 0xff && buffer[i + 3] != 0xff && buffer[i - 1] != 0xff && buffer[i + 64] == 0xff && buffer[i + 65] == 0xff) { Paragraph p = new Paragraph(); StringBuilder sb = new StringBuilder(); int j = i + 4; while (j < i + 64) { if (buffer[j] == 0) { break; } if (buffer[j] == 0xd) { sb.AppendLine(); j += 3; } else if (buffer[j] == 0x87) { sb.Append('♪'); j++; } else { sb.Append(encoding.GetString(buffer, j, 1)); j++; } } p.Text = sb.ToString(); subtitle.Paragraphs.Add(p); i += 62; } else { i++; } } subtitle.Renumber(); if (buffer[0] == 0x43 && // CAPT.1.2 buffer[1] == 0x41 && buffer[2] == 0x50 && buffer[3] == 0x54 && buffer[4] == 0x00 && buffer[5] == 0x31 && buffer[6] == 0x2e && buffer[7] == 0x32) { i = 396; int start = i; int number = 0; while (i < buffer.Length - 66) { if (buffer[i] == 0xff && buffer[i + 1] == 0xff && buffer[i + 2] != 0xff && buffer[i + 28] == 0xff && buffer[i + 29] == 0xff && buffer[i + 30] != 0xff) { if (buffer[i + 14] == number + 1) { Paragraph p = subtitle.GetParagraphOrDefault(number); if (p != null) { p.StartTime = DecodeTimeCode(buffer, i + 18); p.EndTime = DecodeTimeCode(buffer, i + 22); number++; } i += 25; } } i++; } } else { i = 230; int countTimecodes = 0; int start = i; int lastNumber = -1; while (i < buffer.Length - 66) { if (buffer[i] == 0xff && buffer[i + 1] == 0xff && buffer[i + 2] == 0xff && buffer[i + 3] == 0xff) { int length = i - start - 2; if (length >= 10) { int count = length / 14; if (length % 14 == 10) { count++; } else { // System.Windows.Forms.MessageBox.Show("Problem at with a length of " + length.ToString() + " at file position " + (i + 2) + " which gives remainer: " + (length % 14)); if (length % 14 == 8) { count++; } } for (int k = 0; k < count; k++) { int index = start + 2 + (14 * k); int number = buffer[index] + buffer[index + 1] * 256; if (number != lastNumber + 1) { int tempNumber = buffer[index - 2] + buffer[index - 1] * 256; if (tempNumber == lastNumber + 1) { index -= 2; number = tempNumber; } } if (number > lastNumber) { lastNumber = number; Paragraph p = subtitle.GetParagraphOrDefault(number); if (p != null) { if (k < count - 1) { p.StartTime = DecodeTimeCode(buffer, index + 6); p.EndTime = DecodeTimeCode(buffer, index + 10); } else { p.StartTime = DecodeTimeCode(buffer, index + 6); } countTimecodes++; } } } } start = i + 2; i += 5; } i++; } } for (i = 0; i < subtitle.Paragraphs.Count; i++) { Paragraph p = subtitle.GetParagraphOrDefault(i); Paragraph next = subtitle.GetParagraphOrDefault(i + 1); if (next != null && p.EndTime.TotalMilliseconds == 0) { p.EndTime.TotalMilliseconds = next.StartTime.TotalMilliseconds - 1; } } for (i = 0; i < subtitle.Paragraphs.Count; i++) { Paragraph p = subtitle.GetParagraphOrDefault(i); Paragraph next = subtitle.GetParagraphOrDefault(i + 1); if (p.Duration.TotalMilliseconds <= 0 && next != null) { p.EndTime.TotalMilliseconds = next.StartTime.TotalMilliseconds - 1; } } subtitle.RemoveEmptyLines(); Paragraph last = subtitle.GetParagraphOrDefault(subtitle.Paragraphs.Count - 1); if (last != null) { last.EndTime.TotalMilliseconds = last.StartTime.TotalMilliseconds + Utilities.GetOptimalDisplayMilliseconds(last.Text); } subtitle.Renumber(); }
public override string ToText(Subtitle subtitle, string title) { var sb = new StringBuilder(); sb.AppendLine(@"File Format=MacCaption_MCC V1.0 /////////////////////////////////////////////////////////////////////////////////// // Computer Prompting and Captioning Company // Ancillary Data Packet Transfer File // // Permission to generate this format is granted provided that // 1. This ANC Transfer file format is used on an as-is basis and no warranty is given, and // 2. This entire descriptive information text is included in a generated .mcc file. // // General file format: // HH:MM:SS:FF(tab)[Hexadecimal ANC data in groups of 2 characters] // Hexadecimal data starts with the Ancillary Data Packet DID (Data ID defined in S291M) // and concludes with the Check Sum following the User Data Words. // Each time code line must contain at most one complete ancillary data packet. // To transfer additional ANC Data successive lines may contain identical time code. // Time Code Rate=[24, 25, 30, 30DF, 50, 60] // // ANC data bytes may be represented by one ASCII character according to the following schema: // G FAh 00h 00h // H 2 x (FAh 00h 00h) // I 3 x (FAh 00h 00h) // J 4 x (FAh 00h 00h) // K 5 x (FAh 00h 00h) // L 6 x (FAh 00h 00h) // M 7 x (FAh 00h 00h) // N 8 x (FAh 00h 00h) // O 9 x (FAh 00h 00h) // P FBh 80h 80h // Q FCh 80h 80h // R FDh 80h 80h // S 96h 69h // T 61h 01h // U E1h 00h 00h // Z 00h // ///////////////////////////////////////////////////////////////////////////////////"); sb.AppendLine(); sb.AppendLine("UUID=" + Guid.NewGuid().ToString().ToUpper());// UUID=9F6112F4-D9D0-4AAF-AA95-854710D3B57A sb.AppendLine("Creation Program=Subtitle Edit"); sb.AppendLine("Creation Date=" + DateTime.Now.ToLongDateString()); sb.AppendLine("Creation Time=" + DateTime.Now.ToShortTimeString()); sb.AppendLine(); for (int i = 0; i < subtitle.Paragraphs.Count; i++) { Paragraph p = subtitle.Paragraphs[i]; sb.AppendLine(string.Format("{0}\t{1}", ToTimeCode(p.StartTime.TotalMilliseconds), p.Text)); // TODO: Encode text - how??? sb.AppendLine(); Paragraph next = subtitle.GetParagraphOrDefault(i + 1); if (next == null || Math.Abs(next.StartTime.TotalMilliseconds - p.EndTime.TotalMilliseconds) > 100) { sb.AppendLine(string.Format("{0}\t???", ToTimeCode(p.EndTime.TotalMilliseconds))); // TODO: Some end text??? sb.AppendLine(); } } return sb.ToString(); }
private static Subtitle ImportTimeCodesOnSameSeperateLine(string[] lines) { Paragraph p = null; var subtitle = new Subtitle(); var sb = new StringBuilder(); char[] SplitChars = { ' ', '\t' }; for (int idx = 0; idx < lines.Length; idx++) { string line = lines[idx]; string lineWithPerhapsOnlyNumbers = GetLineWithPerhapsOnlyNumbers(line); bool allNumbers = lineWithPerhapsOnlyNumbers.Length > 0; foreach (char c in lineWithPerhapsOnlyNumbers) { if (!char.IsDigit(c)) allNumbers = false; } if (allNumbers && lineWithPerhapsOnlyNumbers.Length > 5) { string[] arr = line.Replace('-', ' ').Replace('>', ' ').Replace('{', ' ').Replace('}', ' ').Replace('[', ' ').Replace(']', ' ').Trim().Split(SplitChars, StringSplitOptions.RemoveEmptyEntries); if (arr.Length == 2) { string[] start = arr[0].Trim().Split(ExpectedSplitChars, StringSplitOptions.RemoveEmptyEntries); string[] end = arr[1].Trim().Split(ExpectedSplitChars, StringSplitOptions.RemoveEmptyEntries); if ((start.Length == 3 || start.Length == 4) && (end.Length == 3 || end.Length == 4)) { if (p != null) { p.Text = sb.ToString().Trim(); subtitle.Paragraphs.Add(p); } p = new Paragraph(); sb = new StringBuilder(); p.StartTime = DecodeTime(start); p.EndTime = DecodeTime(end); } } else if (arr.Length == 3) { string[] start = arr[0].Trim().Split(ExpectedSplitChars, StringSplitOptions.RemoveEmptyEntries); string[] end = arr[1].Trim().Split(ExpectedSplitChars, StringSplitOptions.RemoveEmptyEntries); string[] duration = arr[2].Trim().Split(ExpectedSplitChars, StringSplitOptions.RemoveEmptyEntries); if (start.Length < 3) { start = end; end = duration; } if ((start.Length == 3 || start.Length == 4) && (end.Length == 3 || end.Length == 4)) { if (p != null) { p.Text = sb.ToString().Trim(); subtitle.Paragraphs.Add(p); } p = new Paragraph(); sb = new StringBuilder(); p.StartTime = DecodeTime(start); p.EndTime = DecodeTime(end); } } } if (p != null && !allNumbers && line.Length > 1) { line = line.Trim(); if (line.StartsWith("}{}", StringComparison.Ordinal) || line.StartsWith("][]", StringComparison.Ordinal)) line = line.Remove(0, 3); sb.AppendLine(line.Trim()); } } if (p != null) { p.Text = sb.ToString().Trim(); subtitle.Paragraphs.Add(p); } double averateDuration = 0; foreach (Paragraph a in subtitle.Paragraphs) { double d = a.Duration.TotalSeconds; if (d > 10) d = 8; averateDuration += d; } averateDuration = averateDuration / subtitle.Paragraphs.Count; if (averateDuration < 0.2 || (averateDuration < 0.5 && subtitle.Paragraphs.Count > 100 && subtitle.Paragraphs[subtitle.Paragraphs.Count - 1].StartTime.TotalSeconds < 140 && subtitle.Paragraphs[subtitle.Paragraphs.Count - 2].StartTime.TotalSeconds < 140)) { subtitle = ImportTimeCodesOnSameSeperateLineNoMilliseconds(lines); int i = 0; foreach (Paragraph a in subtitle.Paragraphs) { i++; var next = subtitle.GetParagraphOrDefault(i); if (next != null && a.EndTime.TotalMilliseconds >= next.StartTime.TotalMilliseconds) { a.EndTime.TotalMilliseconds = next.StartTime.TotalMilliseconds - Configuration.Settings.General.MinimumMillisecondsBetweenLines; } } return subtitle; } subtitle.Renumber(); return subtitle; }
public override void LoadSubtitle(Subtitle subtitle, List<string> lines, string fileName) { _errorCount = 0; Paragraph p = null; var header = new StringBuilder(); foreach (string line in lines) { string s = line.Trim(); if (s.StartsWith("//") || s.StartsWith("File Format=MacCaption_MCC") || s.StartsWith("UUID=") || s.StartsWith("Creation Program=") || s.StartsWith("Creation Date=") || s.StartsWith("Creation Time=") || s.StartsWith("Code Rate=") || s.StartsWith("Time Code Rate=") || string.IsNullOrEmpty(s)) { header.AppendLine(line); } else { var match = RegexTimeCodes.Match(s); if (match.Success) { TimeCode startTime = ParseTimeCode(s.Substring(0, match.Length - 1)); string text = GetSccText(s.Substring(match.Index)); if (text == "942c 942c" || text == "942c") { p.EndTime = new TimeCode(startTime.TotalMilliseconds); } else { p = new Paragraph(startTime, new TimeCode(startTime.TotalMilliseconds), text); subtitle.Paragraphs.Add(p); } } } } for (int i = subtitle.Paragraphs.Count - 2; i >= 0; i--) { p = subtitle.GetParagraphOrDefault(i); Paragraph next = subtitle.GetParagraphOrDefault(i + 1); if (p != null && next != null && p.EndTime.TotalMilliseconds == p.StartTime.TotalMilliseconds) p.EndTime = new TimeCode(next.StartTime.TotalMilliseconds); if (next != null && string.IsNullOrEmpty(next.Text)) subtitle.Paragraphs.Remove(next); } p = subtitle.GetParagraphOrDefault(0); if (p != null && string.IsNullOrEmpty(p.Text)) subtitle.Paragraphs.Remove(p); subtitle.Renumber(); }
private void LoadParagraphs(Subtitle subtitle, int primarySelectedIndex, List<int> selectedIndexes) { if (_subtitle == null) { _subtitle = new Subtitle(); _displayableParagraphs = new List<Paragraph>(); _allSelectedParagraphs = new List<Paragraph>(); } _subtitle.Paragraphs.Clear(); _displayableParagraphs.Clear(); _selectedParagraph = null; _allSelectedParagraphs.Clear(); if (_wavePeaks == null) return; const double additionalSeconds = 15.0; // Helps when scrolling double startThresholdMilliseconds = (StartPositionSeconds - additionalSeconds) * TimeCode.BaseUnit; double endThresholdMilliseconds = (EndPositionSeconds + additionalSeconds) * TimeCode.BaseUnit; for (int i = 0; i < subtitle.Paragraphs.Count; i++) { Paragraph p = subtitle.Paragraphs[i]; if (p.StartTime.IsMaxTime) continue; _subtitle.Paragraphs.Add(p); if (p.EndTime.TotalMilliseconds >= startThresholdMilliseconds && p.StartTime.TotalMilliseconds <= endThresholdMilliseconds) _displayableParagraphs.Add(p); } Action<int, bool> addSelection = (index, isPrimary) => { Paragraph p = subtitle.GetParagraphOrDefault(index); if (p == null || p.StartTime.IsMaxTime) return; if (isPrimary) _selectedParagraph = p; _allSelectedParagraphs.Add(p); }; addSelection(primarySelectedIndex, true); foreach (int selectedIndex in selectedIndexes) addSelection(selectedIndex, false); }
public override void LoadSubtitle(Subtitle subtitle, List<string> lines, string fileName) { this._errorCount = 0; Paragraph p = null; foreach (string line in lines) { string s = line.Trim(); if (regexTimeCodes.Match(s).Success) { if (p != null && !string.IsNullOrEmpty(p.Text)) { subtitle.Paragraphs.Add(p); } p = new Paragraph(); try { string[] arr = s.Substring(0, 11).Split(':'); if (arr.Length == 4) { int hours = int.Parse(arr[0]); int minutes = int.Parse(arr[1]); int seconds = int.Parse(arr[2]); int frames = int.Parse(arr[3]); p.StartTime = new TimeCode(hours, minutes, seconds, FramesToMillisecondsMax999(frames)); string text = s.Remove(0, 11).Trim(); p.Text = text; if (text.Length > 1 && Utilities.IsInteger(text.Substring(0, 2))) { this._errorCount++; } } } catch { this._errorCount++; } } else if (s.Length > 0) { this._errorCount++; } } if (p != null && !string.IsNullOrEmpty(p.Text)) { subtitle.Paragraphs.Add(p); } int index = 1; foreach (Paragraph paragraph in subtitle.Paragraphs) { paragraph.Text = paragraph.Text.Replace("\\M", "♪"); Paragraph next = subtitle.GetParagraphOrDefault(index); if (next != null) { paragraph.EndTime.TotalMilliseconds = next.StartTime.TotalMilliseconds - 1; } else { paragraph.EndTime.TotalMilliseconds = paragraph.StartTime.TotalMilliseconds + Utilities.GetOptimalDisplayMilliseconds(paragraph.Text); } index++; } subtitle.RemoveEmptyLines(); }
public override void LoadSubtitle(Subtitle subtitle, List<string> lines, string fileName) { var paragraph = new Paragraph(); _errorCount = 0; subtitle.Paragraphs.Clear(); for (int i = 0; i < lines.Count; i++) { string line = lines[i].TrimEnd(); string next = string.Empty; if (i + 1 < lines.Count) next = lines[i + 1]; if (line.Contains(':') && !next.Contains(':') && RegexTimeCodes.IsMatch(line) && !RegexTimeCodes.IsMatch(next)) { paragraph = new Paragraph(); if (TryReadTimeCodesLine(line, paragraph)) { paragraph.Text = next; if (!string.IsNullOrWhiteSpace(paragraph.Text)) subtitle.Paragraphs.Add(paragraph); } else if (!string.IsNullOrWhiteSpace(line)) { _errorCount++; } } else { _errorCount++; } } foreach (Paragraph p in subtitle.Paragraphs) p.Text = p.Text.Replace(Environment.NewLine + Environment.NewLine, Environment.NewLine); int index = 0; foreach (Paragraph p in subtitle.Paragraphs) { index++; Paragraph nextParagraph = subtitle.GetParagraphOrDefault(index); if (nextParagraph != null) p.EndTime.TotalMilliseconds = nextParagraph.StartTime.TotalMilliseconds - 1; else p.EndTime.TotalMilliseconds = p.StartTime.TotalMilliseconds + 2500; p.Text = p.Text.Replace(Environment.NewLine + Environment.NewLine, Environment.NewLine); } subtitle.Renumber(); }
public static Subtitle SplitLongLinesInSubtitle(Subtitle subtitle, int totalLineMaxCharacters, int singleLineMaxCharacters) { var splittedIndexes = new List<int>(); var autoBreakedIndexes = new List<int>(); var splittedSubtitle = new Subtitle(); string language = Utilities.AutoDetectGoogleLanguage(subtitle); for (int i = 0; i < subtitle.Paragraphs.Count; i++) { bool added = false; var p = subtitle.GetParagraphOrDefault(i); if (p != null && p.Text != null) { if (QualifiesForSplit(p.Text, singleLineMaxCharacters, totalLineMaxCharacters)) { var text = Utilities.AutoBreakLine(p.Text, language); if (!QualifiesForSplit(text, singleLineMaxCharacters, totalLineMaxCharacters)) { var newParagraph = new Paragraph(p) { Text = text }; autoBreakedIndexes.Add(splittedSubtitle.Paragraphs.Count); splittedSubtitle.Paragraphs.Add(newParagraph); added = true; } else { if (text.Contains(Environment.NewLine)) { var arr = text.SplitToLines(); if (arr.Length == 2) { var minMsBtwnLnBy2 = Configuration.Settings.General.MinimumMillisecondsBetweenLines / 2; int spacing1 = minMsBtwnLnBy2; int spacing2 = minMsBtwnLnBy2; if (Configuration.Settings.General.MinimumMillisecondsBetweenLines % 2 == 1) spacing2++; double duration = p.Duration.TotalMilliseconds / 2.0; var newParagraph1 = new Paragraph(p); var newParagraph2 = new Paragraph(p); newParagraph1.Text = Utilities.AutoBreakLine(arr[0], language); newParagraph1.EndTime.TotalMilliseconds = p.StartTime.TotalMilliseconds + duration - spacing1; newParagraph2.Text = Utilities.AutoBreakLine(arr[1], language); newParagraph2.StartTime.TotalMilliseconds = newParagraph1.EndTime.TotalMilliseconds + spacing2; splittedIndexes.Add(splittedSubtitle.Paragraphs.Count); splittedIndexes.Add(splittedSubtitle.Paragraphs.Count + 1); string p1 = HtmlUtil.RemoveHtmlTags(newParagraph1.Text); var len = p1.Length - 1; if (p1.Length > 0 && (p1[len] == '.' || p1[len] == '!' || p1[len] == '?' || p1[len] == ':' || p1[len] == ')' || p1[len] == ']' || p1[len] == '♪')) { if (newParagraph1.Text.StartsWith('-') && newParagraph2.Text.StartsWith('-')) { newParagraph1.Text = newParagraph1.Text.Remove(0, 1).Trim(); newParagraph2.Text = newParagraph2.Text.Remove(0, 1).Trim(); } else if (newParagraph1.Text.StartsWith("<i>-", StringComparison.Ordinal) && newParagraph2.Text.StartsWith('-')) { newParagraph1.Text = newParagraph1.Text.Remove(3, 1).Trim(); if (newParagraph1.Text.StartsWith("<i> ", StringComparison.Ordinal)) newParagraph1.Text = newParagraph1.Text.Remove(3, 1).Trim(); newParagraph2.Text = newParagraph2.Text.Remove(0, 1).Trim(); } } else { if (newParagraph1.Text.EndsWith("</i>", StringComparison.Ordinal)) { const string post = "</i>"; newParagraph1.Text = newParagraph1.Text.Remove(newParagraph1.Text.Length - post.Length); } //newParagraph1.Text += comboBoxLineContinuationEnd.Text.TrimEnd() + post; if (newParagraph2.Text.StartsWith("<i>", StringComparison.Ordinal)) { const string pre = "<i>"; newParagraph2.Text = newParagraph2.Text.Remove(0, pre.Length); } //newParagraph2.Text = pre + comboBoxLineContinuationBegin.Text + newParagraph2.Text; } var indexOfItalicOpen1 = newParagraph1.Text.IndexOf("<i>", StringComparison.Ordinal); if (indexOfItalicOpen1 >= 0 && indexOfItalicOpen1 < 10 && newParagraph1.Text.IndexOf("</i>", StringComparison.Ordinal) < 0 && newParagraph2.Text.Contains("</i>") && newParagraph2.Text.IndexOf("<i>", StringComparison.Ordinal) < 0) { newParagraph1.Text += "</i>"; newParagraph2.Text = "<i>" + newParagraph2.Text; } splittedSubtitle.Paragraphs.Add(newParagraph1); splittedSubtitle.Paragraphs.Add(newParagraph2); added = true; } } } } } if (!added) splittedSubtitle.Paragraphs.Add(new Paragraph(p)); } splittedSubtitle.Renumber(); return splittedSubtitle; }
public static string FixHyphensAdd(Subtitle subtitle, int i, string language) { Paragraph p = subtitle.Paragraphs[i]; string text = p.Text; string textCache = HtmlUtil.RemoveHtmlTags(text.TrimStart()); if (textCache.StartsWith('-') || textCache.Contains(Environment.NewLine + "-")) { Paragraph prev = subtitle.GetParagraphOrDefault(i - 1); if (prev == null || !HtmlUtil.RemoveHtmlTags(prev.Text).TrimEnd().EndsWith('-') || HtmlUtil.RemoveHtmlTags(prev.Text).TrimEnd().EndsWith("--", StringComparison.Ordinal)) { string[] lines = HtmlUtil.RemoveHtmlTags(p.Text).SplitToLines(); int startHyphenCount = lines.Count(line => line.TrimStart().StartsWith('-')); int totalSpaceHyphen = Utilities.CountTagInText(text, " -"); if (startHyphenCount == 1 && totalSpaceHyphen == 0) { string[] parts = HtmlUtil.RemoveHtmlTags(text).SplitToLines(); if (parts.Length == 2) { string part0 = parts[0].TrimEnd(); bool doAdd = "!?.".Contains(part0[part0.Length - 1]) || language == "ko"; if (parts[0].TrimStart().StartsWith('-') && parts[1].Contains(':') && !doAdd) { doAdd = false; } if (parts[1].TrimStart().StartsWith('-') && parts[0].Contains(':') && !doAdd) { doAdd = false; } if (doAdd) { int idx = text.IndexOf('-'); int newLineIdx = text.IndexOf(Environment.NewLine, StringComparison.Ordinal); bool addSecondLine = idx < newLineIdx ? true : false; if (addSecondLine && idx > 0 && Utilities.AllLetters.Contains(text[idx - 1])) { addSecondLine = false; } if (addSecondLine) { // add dash in second line. newLineIdx += 2; if (text.LineBreakStartsWithHtmlTag(true)) { text = text.Insert(newLineIdx + 3, "- ").TrimEnd(); } else { text = text.Replace(Environment.NewLine, Environment.NewLine + "- ").Replace(Environment.NewLine + "- ", Environment.NewLine + "- "); } } else { // add dash in first line. if (text.LineStartsWithHtmlTag(true)) { text = text.Substring(0, 3) + "- " + text.Remove(0, 3).TrimEnd(); } else if (text.StartsWith("{\\an", StringComparison.Ordinal) && text.Length > 6 && text[5] == '}') { text = text.Insert(6, "- "); } else { text = "- " + text.Trim(); } } } } } // - Shut it off. -Get the f**k<br/>out of here, Darryl. if (totalSpaceHyphen == 1 && startHyphenCount == 1) { int idx = text.IndexOf(" -", StringComparison.Ordinal); if (idx > 1 && ".?!".Contains(text[idx - 1]) && idx + 2 < text.Length) { string firstLine = text.Substring(0, idx).Replace(Environment.NewLine, " ").Trim(); string secondLine = text.Substring(idx + 1).Insert(1, " ").Replace(Environment.NewLine, " ").Trim(); text = firstLine + Environment.NewLine + secondLine; } } } } return text; }
public override void LoadSubtitle(Subtitle subtitle, List<string> lines, string fileName) { _errorCount = 0; Paragraph p = null; foreach (string line in lines) { string s = line.Trim(); var match = RegexTimeCodes.Match(s); if (match.Success) { TimeCode startTime = ParseTimeCode(s.Substring(0, match.Length - 1)); string text = GetSccText(s.Substring(match.Index), ref _errorCount); if (text == "942c 942c" || text == "942c") { p.EndTime = new TimeCode(startTime.TotalMilliseconds); } else { p = new Paragraph(startTime, new TimeCode(startTime.TotalMilliseconds), text); subtitle.Paragraphs.Add(p); } } } for (int i = subtitle.Paragraphs.Count - 2; i >= 0; i--) { p = subtitle.GetParagraphOrDefault(i); Paragraph next = subtitle.GetParagraphOrDefault(i + 1); if (p != null && next != null && p.EndTime.TotalMilliseconds == p.StartTime.TotalMilliseconds) p.EndTime = new TimeCode(next.StartTime.TotalMilliseconds); if (next != null && string.IsNullOrEmpty(next.Text)) subtitle.Paragraphs.Remove(next); } p = subtitle.GetParagraphOrDefault(0); if (p != null && string.IsNullOrEmpty(p.Text)) subtitle.Paragraphs.Remove(p); subtitle.Renumber(); }
public override void LoadSubtitle(Subtitle subtitle, List<string> lines, string fileName) { _errorCount = 0; foreach (string line in lines) { string s = RemoveIllegalSpacesAndFixEmptyCodes(line); if (_regexMicroDvdLine.IsMatch(s)) { try { int textIndex = GetTextStartIndex(s); if (textIndex < s.Length) { string text = s.Substring(textIndex); string temp = s.Substring(0, textIndex - 1); string[] frames = temp.Replace("}{", ";").Replace("{", string.Empty).Replace("}", string.Empty).Split(';'); TimeCode startTime = DecodeTimeCode(frames[0]); TimeCode endTime = DecodeTimeCode(frames[1]); string post = string.Empty; string[] parts = text.Split(new[] { '|' }, StringSplitOptions.RemoveEmptyEntries); int count = 0; StringBuilder lineSb = new StringBuilder(); foreach (string s2 in parts) { if (count > 0) lineSb.AppendLine(); s = s2.Trim(); if (s.StartsWith("{Y:i}")) { s = "<i>" + s.Replace("{Y:i}", string.Empty); post += "</i>"; } else if (s.StartsWith("{Y:b}")) { s = "<b>" + s.Replace("{Y:b}", string.Empty); post += "</b>"; } else if (s.StartsWith("{Y:u}")) { s = "<u>" + s.Replace("{Y:u}", string.Empty); post += "</u>"; } else if (s.StartsWith("{y:i}")) { s = "<i>" + s.Replace("{y:i}", string.Empty) + "</i>"; } else if (s.StartsWith("{y:b}")) { s = "<b>" + s.Replace("{y:b}", string.Empty) + "</b>"; } else if (s.StartsWith("{y:u}")) { s = "<u>" + s.Replace("{y:u}", string.Empty) + "</u>"; } s = s.Replace("{Y:i}", string.Empty).Replace("{y:i}", string.Empty); s = s.Replace("{Y:b}", string.Empty).Replace("{y:b}", string.Empty); s = s.Replace("{Y:u}", string.Empty).Replace("{y:u}", string.Empty); lineSb.Append(s); count++; } text = lineSb + post; subtitle.Paragraphs.Add(new Paragraph(startTime, endTime, text)); } } catch { _errorCount++; } } else { _errorCount++; } } int i = 0; foreach (Paragraph p in subtitle.Paragraphs) { Paragraph previous = subtitle.GetParagraphOrDefault(i - 1); if (p.StartFrame == 0 && previous != null) { p.StartFrame = previous.EndFrame + 1; } if (p.EndFrame == 0) { p.EndFrame = p.StartFrame; } i++; } subtitle.Renumber(); }
public override string ToText(Subtitle subtitle, string title) { var sb = new StringBuilder(); sb.AppendLine("Scenarist_SCC V1.0"); sb.AppendLine(); string language = Utilities.AutoDetectGoogleLanguage(subtitle); for (int i = 0; i < subtitle.Paragraphs.Count; i++) { Paragraph p = subtitle.Paragraphs[i]; sb.AppendLine(string.Format("{0}\t94ae 94ae 9420 9420 {1} 942f 942f", ToTimeCode(p.StartTime.TotalMilliseconds), ToSccText(p.Text, language))); sb.AppendLine(); Paragraph next = subtitle.GetParagraphOrDefault(i + 1); if (next == null || Math.Abs(next.StartTime.TotalMilliseconds - p.EndTime.TotalMilliseconds) > 100) { sb.AppendLine(string.Format("{0}\t942c 942c", ToTimeCode(p.EndTime.TotalMilliseconds))); sb.AppendLine(); } } return sb.ToString(); }
private void CompareSubtitles() { timer1.Stop(); var sub1 = new Subtitle(_subtitle1); var sub2 = new Subtitle(_subtitle2); int index = 0; Paragraph p1 = sub1.GetParagraphOrDefault(index); Paragraph p2 = sub2.GetParagraphOrDefault(index); int max = sub1.Paragraphs.Count; if (max < sub2.Paragraphs.Count) max = sub2.Paragraphs.Count; while (index < max) { if (p1 != null && p2 != null) { if (p1.ToString() == p2.ToString()) { } else { if (GetColumnsEqualExceptNumber(p1, p2) == 0) { int oldIndex = index; for (int i = 1; oldIndex + i < max; i++) { if (GetColumnsEqualExceptNumber(sub1.GetParagraphOrDefault(index + i), p2) > 1) { for (int j = 0; j < i; j++) { sub2.Paragraphs.Insert(index, new Paragraph()); index++; } break; } if (GetColumnsEqualExceptNumber(p1, sub2.GetParagraphOrDefault(index + i)) > 1) { for (int j = 0; j < i; j++) { sub1.Paragraphs.Insert(index, new Paragraph()); index++; } break; } } } } } index++; p1 = sub1.GetParagraphOrDefault(index); p2 = sub2.GetParagraphOrDefault(index); } subtitleListView1.Fill(sub1); subtitleListView2.Fill(sub2); // coloring + differences index list _differences = new List<int>(); index = 0; p1 = sub1.GetParagraphOrDefault(index); p2 = sub2.GetParagraphOrDefault(index); int totalWords = 0; int wordsChanged = 0; if (checkBoxOnlyListDifferencesInText.Checked) { while (index < sub1.Paragraphs.Count || index < sub2.Paragraphs.Count) { if (p1 != null && p2 != null) { Utilities.GetTotalAndChangedWords(p1.Text, p2.Text, ref totalWords, ref wordsChanged, checkBoxIgnoreLineBreaks.Checked, GetBreakToLetter()); if (FixWhitespace(p1.ToString()) == FixWhitespace(p2.ToString()) && p1.Number == p2.Number) { // no differences } else if (p1.ToString() == new Paragraph().ToString()) { _differences.Add(index); subtitleListView1.ColorOut(index, Color.Salmon); } else if (p2.ToString() == new Paragraph().ToString()) { _differences.Add(index); subtitleListView2.ColorOut(index, Color.Salmon); } else if (FixWhitespace(p1.Text) != FixWhitespace(p2.Text)) { _differences.Add(index); subtitleListView1.SetBackgroundColor(index, Color.LightGreen, SubtitleListView.ColumnIndexText); } } else { if (p1 != null && p1.Text != null) totalWords += Utilities.SplitForChangedCalc(p1.Text, checkBoxIgnoreLineBreaks.Checked, GetBreakToLetter()).Length; else if (p2 != null && p2.Text != null) totalWords += Utilities.SplitForChangedCalc(p2.Text, checkBoxIgnoreLineBreaks.Checked, GetBreakToLetter()).Length; _differences.Add(index); } index++; p1 = sub1.GetParagraphOrDefault(index); p2 = sub2.GetParagraphOrDefault(index); } } else { while (index < sub1.Paragraphs.Count || index < sub2.Paragraphs.Count) { if (p1 != null && p2 != null) { Utilities.GetTotalAndChangedWords(p1.Text, p2.Text, ref totalWords, ref wordsChanged, checkBoxIgnoreLineBreaks.Checked, GetBreakToLetter()); if (FixWhitespace(p1.ToString()) != FixWhitespace(p2.ToString())) _differences.Add(index); if (FixWhitespace(p1.ToString()) == FixWhitespace(p2.ToString()) && p1.Number == p2.Number) { // no differences } else if (p1.ToString() == new Paragraph().ToString()) { subtitleListView1.ColorOut(index, Color.Salmon); } else if (p2.ToString() == new Paragraph().ToString()) { subtitleListView2.ColorOut(index, Color.Salmon); } else { int columnsAlike = GetColumnsEqualExceptNumber(p1, p2); if (columnsAlike > 0) { if (p1.StartTime.TotalMilliseconds != p2.StartTime.TotalMilliseconds) { subtitleListView1.SetBackgroundColor(index, Color.LightGreen, SubtitleListView.ColumnIndexStart); subtitleListView2.SetBackgroundColor(index, Color.LightGreen, SubtitleListView.ColumnIndexStart); } if (p1.EndTime.TotalMilliseconds != p2.EndTime.TotalMilliseconds) { subtitleListView1.SetBackgroundColor(index, Color.LightGreen, SubtitleListView.ColumnIndexEnd); subtitleListView2.SetBackgroundColor(index, Color.LightGreen, SubtitleListView.ColumnIndexEnd); } if (p1.Duration.TotalMilliseconds != p2.Duration.TotalMilliseconds) { subtitleListView1.SetBackgroundColor(index, Color.LightGreen, SubtitleListView.ColumnIndexDuration); subtitleListView2.SetBackgroundColor(index, Color.LightGreen, SubtitleListView.ColumnIndexDuration); } if (FixWhitespace(p1.Text.Trim()) != FixWhitespace(p2.Text.Trim())) { subtitleListView1.SetBackgroundColor(index, Color.LightGreen, SubtitleListView.ColumnIndexText); subtitleListView2.SetBackgroundColor(index, Color.LightGreen, SubtitleListView.ColumnIndexText); } if (p1.Number != p2.Number) { subtitleListView1.SetBackgroundColor(index, Color.LightYellow, SubtitleListView.ColumnIndexNumber); subtitleListView2.SetBackgroundColor(index, Color.LightYellow, SubtitleListView.ColumnIndexNumber); } } } } else { if (p1 != null && p1.Text != null) totalWords += Utilities.SplitForChangedCalc(p1.Text, checkBoxIgnoreLineBreaks.Checked, GetBreakToLetter()).Length; else if (p2 != null && p2.Text != null) totalWords += Utilities.SplitForChangedCalc(p2.Text, checkBoxIgnoreLineBreaks.Checked, GetBreakToLetter()).Length; _differences.Add(index); } index++; p1 = sub1.GetParagraphOrDefault(index); p2 = sub2.GetParagraphOrDefault(index); } } UpdatePreviousAndNextButtons(); if (max == _differences.Count) { labelStatus.Text = Configuration.Settings.Language.CompareSubtitles.SubtitlesNotAlike; labelStatus.Font = new Font(labelStatus.Font.FontFamily, labelStatus.Font.Size, FontStyle.Bold); } else { if (wordsChanged != totalWords && wordsChanged > 0) { string formatString = Configuration.Settings.Language.CompareSubtitles.XNumberOfDifferenceAndPercentChanged; if (GetBreakToLetter()) formatString = Configuration.Settings.Language.CompareSubtitles.XNumberOfDifferenceAndPercentLettersChanged; labelStatus.Text = string.Format(formatString, _differences.Count, wordsChanged * 100 / totalWords); } else { labelStatus.Text = string.Format(Configuration.Settings.Language.CompareSubtitles.XNumberOfDifference, _differences.Count); } labelStatus.Font = new Font(labelStatus.Font.FontFamily, labelStatus.Font.Size); } if (checkBoxShowOnlyDifferences.Checked) { // Remove all lines with no difference subtitleListView1.BeginUpdate(); subtitleListView2.BeginUpdate(); if (max != _differences.Count) { for (index = Math.Max(subtitleListView1.Items.Count, subtitleListView2.Items.Count); index >= 0; index--) { if (!_differences.Contains(index)) { if (subtitleListView1.Items.Count > index) subtitleListView1.Items.RemoveAt(index); if (subtitleListView2.Items.Count > index) subtitleListView2.Items.RemoveAt(index); } } } subtitleListView1.EndUpdate(); subtitleListView2.EndUpdate(); _differences = new List<int>(); for (index = 0; index < Math.Max(subtitleListView1.Items.Count, subtitleListView2.Items.Count); index++) _differences.Add(index); } timer1.Start(); subtitleListView1.FirstVisibleIndex = -1; subtitleListView1.SelectIndexAndEnsureVisible(0); }
private static Subtitle ImportTimeCodesOnSameSeperateLine(string[] lines) { Paragraph p = null; var subtitle = new Subtitle(); var sb = new StringBuilder(); for (int idx = 0; idx < lines.Length; idx++) { string line = lines[idx]; string lineWithPerhapsOnlyNumbers = line.Replace(" ", string.Empty).Replace(".", string.Empty).Replace(",", string.Empty).Replace("\t", string.Empty).Replace(":", string.Empty).Replace(";", string.Empty).Replace("{", string.Empty).Replace("}", string.Empty).Replace("[", string.Empty).Replace("]", string.Empty).Replace("-", string.Empty).Replace(">", string.Empty).Replace("<", string.Empty); bool allNumbers = lineWithPerhapsOnlyNumbers.Length > 0; foreach (char c in lineWithPerhapsOnlyNumbers) { if (!char.IsDigit(c)) { allNumbers = false; } } if (allNumbers && lineWithPerhapsOnlyNumbers.Length > 5) { string[] arr = line.Replace("-", " ").Replace(">", " ").Replace("{", " ").Replace("}", " ").Replace("[", " ").Replace("]", " ").Trim().Split(new[] { ' ', '\t' }, StringSplitOptions.RemoveEmptyEntries); if (arr.Length == 2) { string[] start = arr[0].Trim().Split(new[] { '.', ',', ';', ':' }, StringSplitOptions.RemoveEmptyEntries); string[] end = arr[1].Trim().Split(new[] { '.', ',', ';', ':' }, StringSplitOptions.RemoveEmptyEntries); if ((start.Length == 3 || start.Length == 4) && (end.Length == 3 || end.Length == 4)) { if (p != null) { p.Text = sb.ToString().Trim(); subtitle.Paragraphs.Add(p); } p = new Paragraph(); sb = new StringBuilder(); p.StartTime = DecodeTime(start); p.EndTime = DecodeTime(end); } } else if (arr.Length == 3) { string[] start = arr[0].Trim().Split(new[] { '.', ',', ';', ':' }, StringSplitOptions.RemoveEmptyEntries); string[] end = arr[1].Trim().Split(new[] { '.', ',', ';', ':' }, StringSplitOptions.RemoveEmptyEntries); string[] duration = arr[2].Trim().Split(new[] { '.', ',', ';', ':' }, StringSplitOptions.RemoveEmptyEntries); if (start.Length < 3) { start = end; end = duration; } if ((start.Length == 3 || start.Length == 4) && (end.Length == 3 || end.Length == 4)) { if (p != null) { p.Text = sb.ToString().Trim(); subtitle.Paragraphs.Add(p); } p = new Paragraph(); sb = new StringBuilder(); p.StartTime = DecodeTime(start); p.EndTime = DecodeTime(end); } } } if (p != null && !allNumbers && line.Length > 1) { line = line.Trim(); if (line.StartsWith("}{}") || line.StartsWith("][]")) { line = line.Remove(0, 3); } sb.AppendLine(line.Trim()); } } if (p != null) { p.Text = sb.ToString().Trim(); subtitle.Paragraphs.Add(p); } double averateDuration = 0; foreach (Paragraph a in subtitle.Paragraphs) { double d = a.Duration.TotalSeconds; if (d > 10) { d = 8; } averateDuration += d; } averateDuration = averateDuration / subtitle.Paragraphs.Count; if (averateDuration < 0.2 || (averateDuration < 0.5 && subtitle.Paragraphs.Count > 100 && subtitle.Paragraphs[subtitle.Paragraphs.Count - 1].StartTime.TotalSeconds < 140 && subtitle.Paragraphs[subtitle.Paragraphs.Count - 2].StartTime.TotalSeconds < 140)) { subtitle = ImportTimeCodesOnSameSeperateLineNoMilliseconds(lines); int i = 0; foreach (Paragraph a in subtitle.Paragraphs) { i++; var next = subtitle.GetParagraphOrDefault(i); if (next != null && a.EndTime.TotalMilliseconds >= next.StartTime.TotalMilliseconds) { a.EndTime.TotalMilliseconds = next.StartTime.TotalMilliseconds - Configuration.Settings.General.MinimumMillisecondsBetweenLines; } } return(subtitle); } subtitle.Renumber(); return(subtitle); }