Example #1
0
        /// <summary>
        /// Adjust the Subtitle file to compensate for the cut segments represented in a EDL file
        /// </summary>
        /// <param name="edlFile">EDL file containing segment information</param>
        /// <param name="srtFile">Subtitle file</param>
        /// <param name="ccOffset">Offset to shift the timebase for all subtitles (+ve or -ve)</param>
        /// <param name="segmentOffset">Incremental offset to shift the timebase for subtitles AFTER each segment is cut (+ve or -ve). Used to compensate for progressive shifting in EDL cutting due to GOP boundary issues</param>
        /// <param name="ignoreMinimumCut">Ignore the mininum segment size for cutting (true when not cutting for an encoder, e.g. trimming)</param>
        /// <returns>True if successful</returns>
        public bool CutWithEDL(string edlFile, string srtFile, double ccOffset, double segmentOffset, bool ignoreMinimumCut = false)
        {
            _jobLog.WriteEntry(this, ("Syncing SRT file with EDL file"), Log.LogEntryType.Information);
            _jobLog.WriteEntry(this, "EDL File " + edlFile, Log.LogEntryType.Debug);
            _jobLog.WriteEntry(this, "SRT File " + srtFile, Log.LogEntryType.Debug);
            _jobLog.WriteEntry(this, "Offset : " + ccOffset.ToString(CultureInfo.InvariantCulture), Log.LogEntryType.Debug);
            _jobLog.WriteEntry(this, "Progressive Segment Cut Correction : " + segmentOffset.ToString(CultureInfo.InvariantCulture), Log.LogEntryType.Debug);

            if (String.IsNullOrEmpty(srtFile) || String.IsNullOrEmpty(edlFile))
            {
                return(true); // nothing to do
            }
            if (!File.Exists(srtFile) || !File.Exists(edlFile) || FileIO.FileSize(srtFile) == 0 || FileIO.FileSize(edlFile) == 0)
            {
                _jobLog.WriteEntry(this, ("SRT/EDL file does not exist or is 0 bytes in size"), Log.LogEntryType.Warning);
                return(true); // nothing to do
            }

            // Taken from MACHYY1's srt_edl_cutter.ps1 (translated and enhanced from PS1 to C#)
            List <List <string> > srt_array = new List <List <string> >();

            // Read the EDL File
            List <KeyValuePair <float, float> > edlKeepList = new List <KeyValuePair <float, float> >();
            EDL edl = new EDL(_profile, "", GlobalDefs.MAX_VIDEO_DURATION, edlFile, 0, _jobStatus, _jobLog, ignoreMinimumCut); // assume infinite duration, Ignore minimum segment since we are trimming subtitles

            if (!edl.ParseEDLFile(ref edlKeepList))
            {
                _jobLog.WriteEntry(this, ("Error processing EDL file"), Log.LogEntryType.Error);
                return(false);
            }

            if (edlKeepList.Count == 0)
            {
                return(true); // All done, nothing to adjust
            }
            // Read the SRT File
            try
            {
                System.IO.StreamReader srtS = new System.IO.StreamReader(srtFile);
                string        line;
                int           sequence = 1, temp;
                List <string> line_text = new List <string>();
                double        srt_start_time = 0, srt_end_time = 0;
                List <string> srt_line;
                string[]      fields;

                while ((line = srtS.ReadLine()) != null)
                {
                    if (line == "") //blank line - so write the info to an array (end of current entry)
                    {
                        if (sequence > 0)
                        {
                            int    edl_segment    = 0;        // If the keep doesn't start at 0 then we have 1 segment already cut
                            double total_time_cut = ccOffset; // Set to offset
                            double last_keep      = 0;
                            foreach (KeyValuePair <float, float> keep in edlKeepList)
                            {
                                total_time_cut += keep.Key - last_keep;                                                                          // Track how much time has been cut so far

                                if (srt_start_time >= keep.Key && srt_start_time <= keep.Value)                                                  // record to keep
                                {
                                    srt_line = new List <string>();                                                                              // Build the SRT entry
                                    string startTimeCode = (seconds_to_hhmmss(srt_start_time - total_time_cut + (edl_segment * segmentOffset))); // Compensate progressively for each segment
                                    if (srt_end_time > keep.Value)                                                                               // SANITY CHECK: end time should not exceed the end of keep video/srt time (otherwise it looks like a burned in video with previous subtitle overlapping the next at the cut boundary)
                                    {
                                        srt_end_time = keep.Value;
                                    }
                                    string endTimeCode = (seconds_to_hhmmss(srt_end_time - total_time_cut + (edl_segment * segmentOffset))); // Compensate progressively for each segment.

                                    /* SRT FORMAT:
                                     * SubRip (SubRip Text) files are named with the extension .srt, and contain formatted plain text.
                                     * The time format used is hours:minutes:seconds,milliseconds. The decimal separator used is the comma, since the program was written in France.
                                     * The line break used is often the CR+LF pair.
                                     * Subtitles are numbered sequentially, starting at 1.
                                     *  Subtitle number
                                     *  Start time --> End time
                                     *  Text of subtitle (one or more lines)
                                     *  Blank line
                                     */
                                    srt_line.Add(sequence.ToString());                   // Subtitle No
                                    srt_line.Add(startTimeCode + " --> " + endTimeCode); // Start time --> End time
                                    foreach (string text in line_text)                   // Text of subtitle (one or more lines)
                                    {
                                        srt_line.Add(text);
                                    }
                                    srt_line.Add("");        // Blank line

                                    srt_array.Add(srt_line); // Build the SRT file
                                    sequence++;
                                    break;
                                }

                                edl_segment++;
                                last_keep = keep.Value;
                            }

                            srt_start_time = srt_end_time = 0;
                            line_text.Clear(); // Reset the content
                        }
                    }
                    else if (int.TryParse(line, out temp)) // Line number
                    {
                        continue;                          // do nothing here
                    }
                    else if (line.Contains(" --> "))       // Timecodes
                    {
                        line           = line.Replace(" --> ", "\t");
                        fields         = line.Split('\t');
                        srt_start_time = hhmmss_to_seconds(fields[0]);
                        srt_end_time   = hhmmss_to_seconds(fields[1]);
                    }
                    else if (line != "")                      // Text Content
                    {
                        if (!String.IsNullOrWhiteSpace(line)) // don't add blank lines, it causes programs like MP4Box to choke
                        {
                            line_text.Add(line);
                        }
                    }
                    else
                    {
                        throw new System.ArgumentException("Invalid SRT file format");
                    }
                }

                srtS.Close();
                srtS.Dispose();
            }
            catch (Exception e)
            {
                _jobLog.WriteEntry(this, ("Error processing SRT file") + " " + e.ToString(), Log.LogEntryType.Error);
                return(false);
            }

            // Delete the original SRT file
            FileIO.TryFileDelete(srtFile);

            try
            {
                // Write the new SRT file
                StreamWriter srtWrite = new System.IO.StreamWriter(srtFile);
                foreach (List <string> srt_line in srt_array)
                {
                    foreach (string entry in srt_line)
                    {
                        srtWrite.WriteLine(entry); // Format is already prebuilt above, just dump into the file
                    }
                }
                srtWrite.Flush();
                srtWrite.Close();
                srtWrite.Dispose();
            }
            catch (Exception e)
            {
                _jobLog.WriteEntry(this, ("Error writing to SRT file") + " " + e.ToString(), Log.LogEntryType.Error);
                return(false);
            }

            return(true);
        }