Example #1
0
 public InfoCombined(InfoLine subs1, InfoLine subs2, bool active)
 {
     this.subs1  = subs1;
     this.subs2  = subs2;
     this.active = active;
     this.onlyNeededForContext = false;
 }
        /// <summary>
        /// Create a line info object based on the given parameters.
        /// </summary>
        private InfoLine createLineInfo(string lineText, DateTime startTime, DateTime endTime)
        {
            lineText = lineText.Replace("\r\n", " ");
            lineText = lineText.Replace("\r", " ");
            lineText = lineText.Replace("\n", " ");
            lineText = lineText.Replace("\t", " ");
            lineText = lineText.Trim();

            InfoLine info = new InfoLine(startTime, endTime, lineText);

            return(info);
        }
Example #3
0
        /// <summary>
        /// Create a line info object based on the given parameters.
        /// </summary>
        private InfoLine createLineInfo(string lineText, string rawStartTime, string rawEndTime)
        {
            DateTime startTime = parseTime(rawStartTime);
            DateTime endTime   = parseTime(rawEndTime);

            lineText = lineText.Replace("\t", " ");
            lineText = Regex.Replace(lineText, "</?[ibuIBU]>", "").Trim();

            InfoLine info = new InfoLine(startTime, endTime, lineText);

            return(info);
        }
Example #4
0
        /// <summary>
        /// Given a line from Subs1, get the closest matching line from a list of Subs2 lines based on timestamp.
        /// May return null if Subs1 RemoveNoCounterpart is set and there is no obvious Subs2 counterpart.
        /// </summary>
        private InfoCombined getCombinedOverlap(InfoLine subs1LineInfo, List <InfoLine> subs2LineInfos)
        {
            InfoLine bestMatch   = new InfoLine();
            double   bestOverlap = -999999999999999999.0;
            int      stopCount   = 0;

            // Compare the given Subs1 against each of the Subs2 lines
            foreach (InfoLine info in subs2LineInfos)
            {
                // How well did these lines overlap (1.0 is the max)
                double overlap = UtilsSubs.getOverlap(subs1LineInfo.StartTime, subs1LineInfo.EndTime, info.StartTime,
                                                      info.EndTime);

                // Did the current pair of lines overlap more than any pair thus far?
                if (overlap >= bestOverlap)
                {
                    bestMatch.Actor     = info.Actor;
                    bestMatch.EndTime   = info.EndTime;
                    bestMatch.StartTime = info.StartTime;
                    bestMatch.Text      = info.Text;

                    bestOverlap = overlap;

                    stopCount = 0; // Reset
                }
                else
                {
                    stopCount++;

                    // Stop trying to find matches after a while
                    if (stopCount == 20)
                    {
                        break;
                    }
                }
            }

            // If no overlap, don't use provided Subs1 line
            if (Settings.Instance.Subs[0].RemoveNoCounterpart &&
                bestOverlap < 0.0)
            {
                return(null);
            }

            return(new InfoCombined(subs1LineInfo, bestMatch));
        }
Example #5
0
        /// <summary>
        /// Given the index of the first line of a partial sentence,
        ///   1) Find the index of the last line of the partial sentence.
        ///   2) Combine all lines between the first and last lines.
        /// </summary>
        private int findEndLineOfCurrentSentence(List <InfoLine> infoLines, int startLineIdx,
                                                 string continuationChars, out InfoLine combinedLines)
        {
            combinedLines = infoLines[startLineIdx];
            int lineIdx = startLineIdx + 1;

            // If given the last line, we can't go any further
            if (lineIdx >= infoLines.Count)
            {
                return(startLineIdx);
            }

            // Find the end line
            for (; lineIdx < infoLines.Count; lineIdx++)
            {
                InfoLine curLine = infoLines[lineIdx];

                if (curLine.Text.Length == 0)
                {
                    continue;
                }

                string lastCharInLine = curLine.Text[curLine.Text.Length - 1].ToString();

                combinedLines.Text   += " " + curLine.Text;
                combinedLines.EndTime = curLine.EndTime;

                // If we have found the end line of the current sentence
                if (!continuationChars.Contains(lastCharInLine))
                {
                    break;
                }
            }

            return(lineIdx);
        }
Example #6
0
        /// <summary>
        /// Combine lines if the last character of the line indicates that it should be joined with the next line.
        /// Example:
        ///
        ///   LineA,
        ///   LineB.
        ///
        ///   If comma is the character that indicates a partial line, then the above lines would be combined as:
        ///
        ///   LineA, LineB.
        ///
        ///  continuationChars is a string containing all of the characters that can indicate a partial line.
        ///  Example: ",、 →"
        ///
        /// </summary>
        private List <InfoLine> combinePartialLinesIntoSentence(List <InfoLine> infoLines, string continuationChars)
        {
            if (continuationChars.Length == 0 || infoLines.Count == 0)
            {
                return(infoLines);
            }

            List <InfoLine> outInfoLines = new List <InfoLine>();

            for (int lineIdx = 0; lineIdx < infoLines.Count; lineIdx++)
            {
                InfoLine curLine = infoLines[lineIdx];

                if (curLine.Text.Length == 0)
                {
                    continue;
                }

                string lastCharInLine = curLine.Text[curLine.Text.Length - 1].ToString();

                // If this is a partial line of a sentence, combine
                if (continuationChars.Contains(lastCharInLine))
                {
                    InfoLine combinedLines;
                    int      endIdx = findEndLineOfCurrentSentence(infoLines, lineIdx, continuationChars, out combinedLines);
                    outInfoLines.Add(combinedLines);
                    lineIdx = endIdx;
                }
                else
                {
                    outInfoLines.Add(curLine);
                }
            }

            return(outInfoLines);
        }
Example #7
0
        /// <summary>
        /// Parse the subtitle file and return a list of lines.
        /// </summary>
        override public List <InfoLine> parse()
        {
            List <InfoLine> lineInfos = new List <InfoLine>(2000);

            SubtitleCreator.SUP.reset();
            SubtitleCreator.SUP sup = SubtitleCreator.SUP.Instance;

            // Load in the .idx/.sub file (takes a while)
            sup.Filename = this.File;

            if (Settings.Instance.VobSubColors.Enabled)
            {
                sup.ReadSUP(this.Stream, Settings.Instance.VobSubColors.Colors, Settings.Instance.VobSubColors.TransparencyEnabled);
            }
            else
            {
                sup.ReadSUP(this.Stream, null, null);
            }

            UtilsName name = new UtilsName(Settings.Instance.DeckName, 0, 0, new DateTime(),
                                           Settings.Instance.VideoClips.Size.Width, Settings.Instance.VideoClips.Size.Height);

            for (int i = 0; i < sup.GetNoOfSubtitles(); i++)
            {
                DateTime startTime = sup.GetStartTime(i);
                DateTime endTime   = sup.GetEndTime(i);

                // Used for the filename and the desision to save the image file.
                // Not used to set the time of the InfoLine because the shift is
                // also applied in WorkerSubs
                DateTime shiftedStartTime = sup.GetStartTime(i);
                DateTime shiftedEndTime   = sup.GetEndTime(i);

                if (Settings.Instance.TimeShiftEnabled)
                {
                    shiftedStartTime = UtilsSubs.shiftTiming(shiftedStartTime, Settings.Instance.Subs[SubsNum - 1].TimeShift);
                    shiftedEndTime   = UtilsSubs.shiftTiming(shiftedEndTime, Settings.Instance.Subs[SubsNum - 1].TimeShift);
                }

                string bitmapFile = string.Format("{0}_{1:000.}_Stream_{2:00.}_Subs{3}_{4:000.}.{5:00.}.{6:00.}-{7:000.}.{8:00.}.{9:00.}.png",
                                                  Settings.Instance.DeckName,
                                                  this.Episode,
                                                  this.Stream,
                                                  this.SubsNum,
                                                  (int)shiftedStartTime.TimeOfDay.TotalMinutes,
                                                  (int)shiftedStartTime.TimeOfDay.Seconds,
                                                  (int)(shiftedStartTime.TimeOfDay.Milliseconds * 0.1),
                                                  (int)shiftedEndTime.TimeOfDay.TotalMinutes,
                                                  (int)shiftedEndTime.TimeOfDay.Seconds,
                                                  (int)(shiftedEndTime.TimeOfDay.Milliseconds * 0.1));

                DateTime spanStart = Settings.Instance.SpanStart;
                DateTime spanEnd   = Settings.Instance.SpanEnd;

                // Create a image file for each line of dialog
                if ((this.WorkerVars.ProcessingType == WorkerVars.SubsProcessingType.Preview) || // Always save the image when previewing
                    (!Settings.Instance.SpanEnabled) || // Always save the image when span is not enabled
                    ((shiftedStartTime >= spanStart) && (shiftedEndTime <= spanEnd))) // When span is enabled, only save the images that are within the span
                {
                    string imageSavePath = Path.Combine(this.WorkerVars.MediaDir, bitmapFile);
                    sup.GetBitmap(i).Save(imageSavePath, System.Drawing.Imaging.ImageFormat.Png);
                }

                string prefixStr = name.createName(ConstantSettings.SrsVobsubFilenamePrefix, 0, 0, new DateTime(), new DateTime(), "", "");
                string suffixStr = name.createName(ConstantSettings.SrsVobsubFilenameSuffix, 0, 0, new DateTime(), new DateTime(), "", "");

                // Set the line of dialog to the bitmap file
                string text = String.Format("{0}{1}{2}",
                                            prefixStr,  // {0}
                                            bitmapFile, // {1}
                                            suffixStr); // {2}

                InfoLine info = new InfoLine(startTime, endTime, text);
                lineInfos.Add(info);
            }

            lineInfos.Sort();

            return(lineInfos);
        }
Example #8
0
        /// <summary>
        /// Parse the subtitle file and return a list of lines.
        /// </summary>
        override public List <InfoLine> parse()
        {
            List <string>   rawLines  = new List <string>(2000);
            List <InfoLine> lineInfos = new List <InfoLine>(2000);
            StreamReader    subFile   = new StreamReader(this.File, this.SubsEncoding);
            string          fileLine;

            // Store all of the file's lines in a list
            while ((fileLine = subFile.ReadLine()) != null)
            {
                rawLines.Add(fileLine.Trim());
            }

            subFile.Close();

            // Get the regex to use with the dialog lines
            string assDialogRegex = getAssDialogRegex(rawLines);

            // Extract info from each dialog line
            foreach (string rawLine in rawLines)
            {
                Match lineMatch = Regex.Match(rawLine,
                                              assDialogRegex, RegexOptions.IgnoreCase | RegexOptions.Compiled);

                if (!lineMatch.Success)
                {
                    continue;
                }

                string rawStartTime = lineMatch.Groups["StartTime"].ToString().Trim();
                string rawEndTime   = lineMatch.Groups["EndTime"].ToString().Trim();
                string actor        = lineMatch.Groups["Name"].ToString().Trim();
                string text         = lineMatch.Groups["Text"].ToString().Trim();

                // Don't parse styled lines
                if (Settings.Instance.Subs[SubsNum - 1].RemoveStyledLines && text.StartsWith("{"))
                {
                    continue;
                }

                if ((this.WorkerVars != null) && (this.WorkerVars.ProcessingType != WorkerVars.SubsProcessingType.Dueling))
                {
                    // Remove ass-style newlines ("\N")
                    text = text.Replace("\\N", " ");
                    text = text.Replace("\\n", " ");
                }

                // Remove styling embedded within lines
                text = Regex.Replace(text, "{.*?}", "");

                // Remove tabs
                text = Regex.Replace(text, "\t", " ").Trim();

                if (text == "")
                {
                    // No text - try next line
                    continue;
                }

                DateTime startTime = parseTime(rawStartTime);
                DateTime endTime   = parseTime(rawEndTime);
                InfoLine info      = new InfoLine(startTime, endTime, text, actor);
                lineInfos.Add(info);
            }

            // Since the dialog lines don't have to be in chronological order, sort by the start time
            lineInfos.Sort();

            return(lineInfos);
        }
Example #9
0
        /// <summary>
        /// Parse the subtitle file and return a list of lines.
        /// </summary>
        override public List <InfoLine> parse()
        {
            List <string>   rawLines  = new List <string>(100);
            List <InfoLine> lineInfos = new List <InfoLine>(100);
            StreamReader    subFile   = new StreamReader(this.File, this.SubsEncoding);
            string          fileLine;

            // Store all of the file's lines in a list
            while ((fileLine = subFile.ReadLine()) != null)
            {
                rawLines.Add(fileLine.Trim());
            }

            subFile.Close();

            // Extract info from each dialog line
            foreach (string rawLine in rawLines)
            {
                string curLine = rawLine;

                MatchCollection timestampMatches = Regex.Matches(curLine,
                                                                 @"\[(?<Min>\d\d):(?<Sec>\d\d)\.(?<HSec>\d\d)\]",
                                                                 RegexOptions.IgnoreCase | RegexOptions.Compiled);

                string text = Regex.Replace(curLine, @"\[(?<Min>\d\d):(?<Sec>\d\d)\.(?<HSec>\d\d)\]",
                                            "", RegexOptions.Compiled).Trim();

                foreach (Match timestampMatch in timestampMatches)
                {
                    if (!timestampMatch.Success)
                    {
                        continue;
                    }

                    int startTimeMin  = Int32.Parse(timestampMatch.Groups["Min"].ToString().Trim());
                    int startTimeSec  = Int32.Parse(timestampMatch.Groups["Sec"].ToString().Trim());
                    int startTimeHSec = Int32.Parse(timestampMatch.Groups["HSec"].ToString().Trim());

                    DateTime startTime = new DateTime();
                    startTime = startTime.AddMinutes(startTimeMin);
                    startTime = startTime.AddSeconds(startTimeSec);
                    startTime = startTime.AddMilliseconds(startTimeHSec * 10);
                    DateTime endTime = new DateTime();

                    text = text.Replace("\t", " ").Trim();

                    InfoLine info = new InfoLine(startTime, endTime, text);
                    lineInfos.Add(info);
                }
            }

            // Since the dialog lines don't have to be in chronological order, sort by the start time
            lineInfos.Sort();

            // Fill-in the endtimes
            for (int lineIdx = 0; lineIdx < lineInfos.Count; lineIdx++)
            {
                InfoLine infoLineCur  = lineInfos[lineIdx];
                InfoLine infoLineNext = lineInfos[Math.Min(lineInfos.Count - 1, lineIdx + 1)];

                infoLineCur.EndTime = infoLineNext.StartTime;
            }

            // Make the endtime of the final lyric an arbitrary 10 seconds long
            lineInfos[lineInfos.Count - 1].EndTime = new DateTime().AddSeconds(lineInfos[lineInfos.Count - 1].StartTime.TimeOfDay.TotalSeconds + 10);

            // Remove lines that don't contains lyrics
            for (int lineIdx = lineInfos.Count - 1; lineIdx >= 0; lineIdx--)
            {
                InfoLine infoLineCur = lineInfos[lineIdx];

                // Remove blank lines
                // Remove lines with the same start and end time because it is probably non-lyric meta information
                // Remove line with a colon because it is probably non-lyric meta information
                // remove lines with a website because it is probably just an advertisement
                if ((infoLineCur.Text.Trim().Length == 0) ||
                    (infoLineCur.StartTime.TimeOfDay.TotalMilliseconds == infoLineCur.EndTime.TimeOfDay.TotalMilliseconds) ||
                    (infoLineCur.Text.Contains(":")) ||
                    (infoLineCur.Text.Contains(":")) ||
                    (infoLineCur.Text.Contains("www.")))
                {
                    lineInfos.RemoveAt(lineIdx);
                }
            }

            return(lineInfos);
        }