Example #1
0
        /// <summary>
        /// Convert audio or video to mp3 and display progress dialog.
        /// </summary>
        private bool convertToMp3(string file, string stream, string progressText, DialogProgress dialogProgress,
                                  DateTime entireClipStartTime, DateTime entireClipEndTime, string tempMp3Filename)
        {
            bool status = true;

            DateTime entireClipDuration = UtilsSubs.getDurationTime(entireClipStartTime, entireClipEndTime);

            DialogProgress.updateProgressInvoke(dialogProgress, progressText);

            // Enable detail mode in progress dialog
            DialogProgress.enableDetailInvoke(dialogProgress, true);

            // Set the duration of the clip in the progress dialog  (for detail mode)
            DialogProgress.setDuration(dialogProgress, entireClipDuration);

            // Rip the audio to a temporary mp3 file
            UtilsAudio.ripAudioFromVideo(file,
                                         stream,
                                         entireClipStartTime, entireClipEndTime,
                                         Settings.Instance.AudioClips.Bitrate, tempMp3Filename, dialogProgress);

            DialogProgress.enableDetailInvoke(dialogProgress, false);

            FileInfo fileInfo = new FileInfo(tempMp3Filename);

            // Error if the temporary mp3 file doesn't exist or is zero bytes
            if (!File.Exists(tempMp3Filename) || fileInfo.Length == 0)
            {
                status = false;
            }

            return(status);
        }
Example #2
0
        /// <summary>
        /// Format a duration argument for ffmpeg.
        /// </summary>
        public static string formatDurationArg(DateTime startTime, DateTime endTime)
        {
            DateTime diffTime = UtilsSubs.getDurationTime(startTime, endTime);

            // Example: -ss 00:00:07.920 -t 00:24:35.120
            string durationArg =
                $"-t {(int) diffTime.TimeOfDay.TotalHours:00.}:{(int) diffTime.TimeOfDay.Minutes:00.}:{(int) diffTime.TimeOfDay.Seconds:00.}.{(int) diffTime.TimeOfDay.Milliseconds:000.}"; // {3}

            return(durationArg);
        }
Example #3
0
        /// <summary>
        /// Is the specified line too long as determined by the "Long Clip Warning" preference?
        /// </summary>
        private bool isLineTooLong(InfoCombined comb)
        {
            DateTime durationTime = UtilsSubs.getDurationTime(comb.Subs1.StartTime, comb.Subs1.EndTime);

            if ((ConstantSettings.LongClipWarningSeconds > 0) &&
                (durationTime.TimeOfDay.TotalMilliseconds > (ConstantSettings.LongClipWarningSeconds * 1000)))
            {
                return(true);
            }

            return(false);
        }
Example #4
0
        /// <summary>
        /// Format a start time and duration argument for ffmpeg.
        /// </summary>
        public static string formatStartTimeAndDurationArg(DateTime startTime, DateTime endTime)
        {
            string startTimeArg = formatStartTimeArg(startTime);
            string durationArg  = formatDurationArg(startTime, endTime);

            DateTime diffTime = UtilsSubs.getDurationTime(startTime, endTime);

            // Example: -ss 00:00:07.920 -t 00:24:35.120
            string timeArg = $"{startTimeArg} {durationArg}"; // {1}

            return(timeArg);
        }
Example #5
0
        /// <summary>
        /// Format a duration argument for ffmpeg.
        /// </summary>
        public static string formatDurationArg(DateTime startTime, DateTime endTime)
        {
            DateTime diffTime = UtilsSubs.getDurationTime(startTime, endTime);

            // Example: -ss 00:00:07.920 -t 00:24:35.120
            string durationArg = String.Format("-t {0:00.}:{1:00.}:{2:00.}.{3:000.}",
                                               (int)diffTime.TimeOfDay.TotalHours,    // {0}
                                               (int)diffTime.TimeOfDay.Minutes,       // {1}
                                               (int)diffTime.TimeOfDay.Seconds,       // {2}
                                               (int)diffTime.TimeOfDay.Milliseconds); // {3}

            return(durationArg);
        }
Example #6
0
        /// <summary>
        /// Format a start time and duration argument for ffmpeg.
        /// </summary>
        public static string formatStartTimeAndDurationArg(DateTime startTime, DateTime endTime)
        {
            string startTimeArg = UtilsVideo.formatStartTimeArg(startTime);
            string durationArg  = UtilsVideo.formatDurationArg(startTime, endTime);

            DateTime diffTime = UtilsSubs.getDurationTime(startTime, endTime);

            // Example: -ss 00:00:07.920 -t 00:24:35.120
            string timeArg = String.Format("{0} {1}",
                                           startTimeArg, // {0}
                                           durationArg); // {1}

            return(timeArg);
        }
Example #7
0
        /// <summary>
        /// Based on timings, determine if this line is within the context range.
        /// So if someone says a line, then it cuts to the OP theme, there shouldn't be
        /// anything for it's trailing line (assuming the credits have been removed from the subs).
        /// </summary>
        private bool isLineInContextRange(List <InfoCombined> combArray, int baseLineIndex, int curContextIdx)
        {
            bool inRange = true;

            // If leading context line
            if (curContextIdx < baseLineIndex)
            {
                // If context range feature is disabled
                if (Settings.Instance.ContextLeadingRange == 0)
                {
                    return(true);
                }

                for (int i = baseLineIndex; i > curContextIdx; i--)
                {
                    int durationMs = (int)UtilsSubs.getDurationTime(combArray[i - 1].Subs1.EndTime,
                                                                    combArray[i].Subs1.StartTime).TimeOfDay.TotalMilliseconds;

                    if (durationMs > Settings.Instance.ContextLeadingRange * 1000)
                    {
                        inRange = false;
                        break;
                    }
                }
            }
            else // Trailing context line
            {
                // If context range feature is disabled
                if (Settings.Instance.ContextTrailingRange == 0)
                {
                    return(true);
                }

                for (int i = baseLineIndex; i < curContextIdx; i++)
                {
                    int durationMs = (int)UtilsSubs.getDurationTime(combArray[i].Subs1.EndTime,
                                                                    combArray[i + 1].Subs1.StartTime).TimeOfDay.TotalMilliseconds;

                    if (durationMs > Settings.Instance.ContextTrailingRange * 1000)
                    {
                        inRange = false;
                        break;
                    }
                }
            }

            return(inRange);
        }
Example #8
0
        public void updateDetailedProgress(int progress, InfoFFmpegProgress ffmpegProgress)
        {
            this.progressBarDetailed.Value = Math.Min(100, progress);
            this.progressBarDetailed.Style = ProgressBarStyle.Marquee;

            if (progress > 0)
            {
                this.progressBarDetailed.Style = ProgressBarStyle.Blocks;
                DateTime timeRemaining = UtilsSubs.getDurationTime(ffmpegProgress.Time, duration);

                this.labelStatsTimeProcessed.Visible      = true;
                this.labelStatsTimeProcessedValue.Visible = true;
                this.labelStatsTimeRemaining.Visible      = true;
                this.labelStatsTimeRemainingValue.Visible = true;

                if (ffmpegProgress.VideoProgress)
                {
                    this.labelStatsFps.Visible        = true;
                    this.labelStatsFpsValue.Visible   = true;
                    this.labelStatsFrame.Visible      = true;
                    this.labelStatsFrameValue.Visible = true;
                }
                else
                {
                    this.labelStatsFps.Visible        = false;
                    this.labelStatsFpsValue.Visible   = false;
                    this.labelStatsFrame.Visible      = false;
                    this.labelStatsFrameValue.Visible = false;
                }

                this.labelStatsTimeProcessedValue.Text = string.Format("{0:00}:{1:00}:{2:00}",
                                                                       ffmpegProgress.Time.TimeOfDay.Hours,
                                                                       ffmpegProgress.Time.TimeOfDay.Minutes,
                                                                       ffmpegProgress.Time.TimeOfDay.Seconds);


                this.labelStatsTimeRemainingValue.Text = string.Format("{0:00}:{1:00}:{2:00}",
                                                                       timeRemaining.TimeOfDay.Hours,
                                                                       timeRemaining.TimeOfDay.Minutes,
                                                                       timeRemaining.TimeOfDay.Seconds);

                if (ffmpegProgress.VideoProgress)
                {
                    this.labelStatsFpsValue.Text   = string.Format("{0}", ffmpegProgress.FPS);
                    this.labelStatsFrameValue.Text = string.Format("{0}", ffmpegProgress.Frame);
                }
            }
        }
Example #9
0
        /// <summary>
        /// Set the list to the lines of the provided episode.
        /// </summary>
        private void populateLinesListView(int episodeIndex)
        {
            if (previewWorkerVars == null)
            {
                return;
            }

            this.listViewLines.BeginUpdate();

            this.listViewLines.Items.Clear();

            // Create a new row for each comb
            foreach (InfoCombined comb in previewWorkerVars.CombinedAll[episodeIndex])
            {
                // Create the text for both columns
                string[] entryToAdd = new String[5];
                entryToAdd[0] = comb.Subs1.Text;

                if (Settings.Instance.Subs[1].Files.Length != 0)
                {
                    entryToAdd[1] = comb.Subs2.Text;
                }

                entryToAdd[2] = this.formatTimeForDisplay(comb.Subs1.StartTime);
                entryToAdd[3] = this.formatTimeForDisplay(comb.Subs1.EndTime);

                if (this.isLineTooLong(comb))
                {
                    entryToAdd[4] = this.formatTimeForDisplay(UtilsSubs.getDurationTime(comb.Subs1.StartTime, comb.Subs1.EndTime)) + " (Long!)";
                }
                else
                {
                    entryToAdd[4] = this.formatTimeForDisplay(UtilsSubs.getDurationTime(comb.Subs1.StartTime, comb.Subs1.EndTime));
                }

                ListViewItem item = new ListViewItem(entryToAdd);

                // Embed a comb into each item
                item.Tag = comb;
                this.listViewLines.Items.Add(item);
            }

            for (int i = 0; i < this.listViewLines.Items.Count; i++)
            {
                InfoCombined comb = (InfoCombined)this.listViewLines.Items[i].Tag;

                if (comb.Active)
                {
                    this.listViewLines.Items[i].BackColor = activeColor;
                }
                else
                {
                    this.listViewLines.Items[i].BackColor = inactiveColor;
                }

                if (this.isLineTooLong(comb))
                {
                    this.listViewLines.Items[i].ForeColor = longLineWarningColor;
                }
                else
                {
                    this.listViewLines.Items[i].ForeColor = Color.Black;
                }
            }

            this.listViewLines.EndUpdate();
        }
Example #10
0
        /// <summary>
        /// Format tokens related to numbers that can have leading zeroes. Takes into account optional leading zeroes.
        /// </summary>
        private string formatNumberTokens(Match match)
        {
            int      numZeroes      = 0;
            bool     numZeroesGiven = false;
            string   token          = "";
            string   zeroString     = "";
            string   formatString   = "";
            string   finalString    = "";
            int      value          = 0;
            DateTime diffTime       = UtilsSubs.getDurationTime(startTime, endTime);
            DateTime midTime        = UtilsSubs.getMidpointTime(startTime, endTime);

            // Get number of leading zeroes (if any)
            if (match.Groups[2].Success)
            {
                numZeroes      = Int32.Parse(match.Groups[2].ToString());
                numZeroesGiven = true;
            }

            // Get the token
            if (match.Groups[3].Success)
            {
                token = match.Groups[3].ToString();
            }

            if (numZeroesGiven)
            {
                // Zero is special, it means use the minimum necassary number of leading zeroes based on some maximum (like the total number of lines)
                if (numZeroes == 0)
                {
                    switch (token)
                    {
                    // Start times (use the end times)
                    case "s_hour":
                        numZeroes = 1;
                        break;

                    case "s_min":
                        numZeroes = getMaxNecassaryLeadingZeroes(lastTime.TimeOfDay.Minutes);     // 2;
                        break;

                    case "s_sec":
                    case "s_hsec":
                        numZeroes = 2;
                        break;

                    case "s_msec":
                        numZeroes = 3;
                        break;

                    case "s_total_hour":
                        numZeroes = getMaxNecassaryLeadingZeroes((int)lastTime.TimeOfDay.TotalHours);      // 1
                        break;

                    case "s_total_min":
                        numZeroes = getMaxNecassaryLeadingZeroes((int)lastTime.TimeOfDay.TotalMinutes);      // 3
                        break;

                    case "s_total_sec":
                        numZeroes = getMaxNecassaryLeadingZeroes((int)lastTime.TimeOfDay.TotalSeconds);      // 4
                        break;

                    case "s_total_hsec":
                        numZeroes = getMaxNecassaryLeadingZeroes(
                            (int)lastTime.TimeOfDay.TotalMilliseconds / 10);      // 6
                        break;

                    // End times
                    case "s_total_msec":
                        numZeroes = getMaxNecassaryLeadingZeroes((int)lastTime.TimeOfDay.TotalMilliseconds);      // 7
                        break;

                    case "e_hour":
                        numZeroes = 1;
                        break;

                    case "e_min":
                        numZeroes = getMaxNecassaryLeadingZeroes(lastTime.TimeOfDay.Minutes);     // 2;
                        break;

                    case "e_sec":
                    case "e_hsec":
                        numZeroes = 2;
                        break;

                    case "e_msec":
                        numZeroes = 3;
                        break;

                    case "e_total_hour":
                        numZeroes = getMaxNecassaryLeadingZeroes((int)lastTime.TimeOfDay.TotalHours);      // 1
                        break;

                    case "e_total_min":
                        numZeroes = getMaxNecassaryLeadingZeroes((int)lastTime.TimeOfDay.TotalMinutes);      // 3
                        break;

                    case "e_total_sec":
                        numZeroes = getMaxNecassaryLeadingZeroes((int)lastTime.TimeOfDay.TotalSeconds);      // 4
                        break;

                    case "e_total_hsec":
                        numZeroes = getMaxNecassaryLeadingZeroes(
                            (int)lastTime.TimeOfDay.TotalMilliseconds / 10);      // 6
                        break;

                    // Duration times (use the end times)
                    case "e_total_msec":
                        numZeroes = getMaxNecassaryLeadingZeroes((int)lastTime.TimeOfDay.TotalMilliseconds);      // 7
                        break;

                    case "d_hour":
                        numZeroes = 1;
                        break;

                    case "d_min":
                        numZeroes = getMaxNecassaryLeadingZeroes(lastTime.TimeOfDay.Minutes);     // 2;
                        break;

                    case "d_sec":
                    case "d_hsec":
                        numZeroes = 2;
                        break;

                    case "d_msec":
                        numZeroes = 3;
                        break;

                    case "d_total_hour":
                        numZeroes = getMaxNecassaryLeadingZeroes((int)lastTime.TimeOfDay.TotalHours);      // 1
                        break;

                    case "d_total_min":
                        numZeroes = getMaxNecassaryLeadingZeroes((int)lastTime.TimeOfDay.TotalMinutes);      // 3
                        break;

                    case "d_total_sec":
                        numZeroes = getMaxNecassaryLeadingZeroes((int)lastTime.TimeOfDay.TotalSeconds);      // 4
                        break;

                    case "d_total_hsec":
                        numZeroes = getMaxNecassaryLeadingZeroes(
                            (int)lastTime.TimeOfDay.TotalMilliseconds / 10);      // 6
                        break;

                    // Middle times (use the end times)
                    case "d_total_msec":
                        numZeroes = getMaxNecassaryLeadingZeroes((int)lastTime.TimeOfDay.TotalMilliseconds);      // 7
                        break;

                    case "m_hour":
                        numZeroes = 1;
                        break;

                    case "m_min":
                        numZeroes = getMaxNecassaryLeadingZeroes(lastTime.TimeOfDay.Minutes);     // 2;
                        break;

                    case "m_sec":
                    case "m_hsec":
                        numZeroes = 2;
                        break;

                    case "m_msec":
                        numZeroes = 3;
                        break;

                    case "m_total_hour":
                        numZeroes = getMaxNecassaryLeadingZeroes((int)lastTime.TimeOfDay.TotalHours);      // 1
                        break;

                    case "m_total_min":
                        numZeroes = getMaxNecassaryLeadingZeroes((int)lastTime.TimeOfDay.TotalMinutes);      // 3
                        break;

                    case "m_total_sec":
                        numZeroes = getMaxNecassaryLeadingZeroes((int)lastTime.TimeOfDay.TotalSeconds);      // 4
                        break;

                    case "m_total_hsec":
                        numZeroes = getMaxNecassaryLeadingZeroes(
                            (int)lastTime.TimeOfDay.TotalMilliseconds / 10);      // 6
                        break;

                    // The rest
                    case "m_total_msec":
                        numZeroes = getMaxNecassaryLeadingZeroes((int)lastTime.TimeOfDay.TotalMilliseconds);      // 7
                        break;

                    case "episode_num":
                        numZeroes = getMaxNecassaryLeadingZeroes(totalNumEpisodes);
                        break;

                    case "sequence_num":
                    case "total_line_num":
                        numZeroes = getMaxNecassaryLeadingZeroes(TotalNumLines);
                        break;

                    case "vobsub_stream_num":
                        numZeroes = 1;
                        break;
                    }
                }

                // Limit the number of zeroes
                if (numZeroes > 9)
                {
                    numZeroes = 9;
                }

                // Create a format string that can include leading zeroes
                if (numZeroes > 0)
                {
                    zeroString += ":";
                }

                for (int i = 0; i < numZeroes; i++)
                {
                    zeroString += "0";
                }
            }

            formatString = "{0" + zeroString + "}";

            switch (token)
            {
            // Start times
            case "s_hour":
                value = startTime.TimeOfDay.Hours;
                break;

            case "s_min":
                value = startTime.TimeOfDay.Minutes;
                break;

            case "s_sec":
                value = startTime.TimeOfDay.Seconds;
                break;

            case "s_hsec":
                value = startTime.TimeOfDay.Milliseconds / 10;
                break;

            case "s_msec":
                value = startTime.TimeOfDay.Milliseconds;
                break;

            case "s_total_hour":
                value = (int)startTime.TimeOfDay.TotalHours;
                break;

            case "s_total_min":
                value = (int)startTime.TimeOfDay.TotalMinutes;
                break;

            case "s_total_sec":
                value = (int)startTime.TimeOfDay.TotalSeconds;
                break;

            case "s_total_hsec":
                value = (int)startTime.TimeOfDay.TotalMilliseconds / 10;
                break;

            // End times
            case "s_total_msec":
                value = (int)startTime.TimeOfDay.TotalMilliseconds;
                break;

            case "e_hour":
                value = endTime.TimeOfDay.Hours;
                break;

            case "e_min":
                value = endTime.TimeOfDay.Minutes;
                break;

            case "e_sec":
                value = endTime.TimeOfDay.Seconds;
                break;

            case "e_hsec":
                value = endTime.TimeOfDay.Milliseconds / 10;
                break;

            case "e_msec":
                value = endTime.TimeOfDay.Milliseconds;
                break;

            case "e_total_hour":
                value = (int)endTime.TimeOfDay.TotalHours;
                break;

            case "e_total_min":
                value = (int)endTime.TimeOfDay.TotalMinutes;
                break;

            case "e_total_sec":
                value = (int)endTime.TimeOfDay.TotalSeconds;
                break;

            case "e_total_hsec":
                value = (int)endTime.TimeOfDay.TotalMilliseconds / 10;
                break;

            // Duration times
            case "e_total_msec":
                value = (int)endTime.TimeOfDay.TotalMilliseconds;
                break;

            case "d_hour":
                value = diffTime.TimeOfDay.Hours;
                break;

            case "d_min":
                value = diffTime.TimeOfDay.Minutes;
                break;

            case "d_sec":
                value = diffTime.TimeOfDay.Seconds;
                break;

            case "d_hsec":
                value = diffTime.TimeOfDay.Milliseconds / 10;
                break;

            case "d_msec":
                value = diffTime.TimeOfDay.Milliseconds;
                break;

            case "d_total_hour":
                value = (int)diffTime.TimeOfDay.TotalHours;
                break;

            case "d_total_min":
                value = (int)diffTime.TimeOfDay.TotalMinutes;
                break;

            case "d_total_sec":
                value = (int)diffTime.TimeOfDay.TotalSeconds;
                break;

            case "d_total_hsec":
                value = (int)diffTime.TimeOfDay.TotalMilliseconds / 10;
                break;

            // Middle times
            case "d_total_msec":
                value = (int)diffTime.TimeOfDay.TotalMilliseconds;
                break;

            case "m_hour":
                value = midTime.TimeOfDay.Hours;
                break;

            case "m_min":
                value = midTime.TimeOfDay.Minutes;
                break;

            case "m_sec":
                value = midTime.TimeOfDay.Seconds;
                break;

            case "m_hsec":
                value = midTime.TimeOfDay.Milliseconds / 10;
                break;

            case "m_msec":
                value = midTime.TimeOfDay.Milliseconds;
                break;

            case "m_total_hour":
                value = (int)midTime.TimeOfDay.TotalHours;
                break;

            case "m_total_min":
                value = (int)midTime.TimeOfDay.TotalMinutes;
                break;

            case "m_total_sec":
                value = (int)midTime.TimeOfDay.TotalSeconds;
                break;

            case "m_total_hsec":
                value = (int)midTime.TimeOfDay.TotalMilliseconds / 10;
                break;

            // The rest
            case "m_total_msec":
                value = (int)midTime.TimeOfDay.TotalMilliseconds;
                break;

            case "episode_num":
                value = episodeNum;
                break;

            case "sequence_num":
                value = sequenceNum;
                break;

            case "total_line_num":
                value = TotalNumLines;
                break;

            case "vobsub_stream_num":
                value = vobsubStreamNum;
                break;
            }

            finalString = String.Format(formatString, value);

            return(finalString);
        }
Example #11
0
        /// <summary>
        /// Generate video clips for all episodes.
        /// </summary>
        public bool genVideoClip(WorkerVars workerVars, DialogProgress dialogProgress)
        {
            int      progessCount  = 0;
            int      episodeCount  = 0;
            int      totalEpisodes = workerVars.CombinedAll.Count;
            int      totalLines    = UtilsSubs.getTotalLineCount(workerVars.CombinedAll);
            DateTime lastTime      = UtilsSubs.getLastTime(workerVars.CombinedAll);

            UtilsName name = new UtilsName(Settings.Instance.DeckName, totalEpisodes,
                                           totalLines, lastTime, Settings.Instance.VideoClips.Size.Width, Settings.Instance.VideoClips.Size.Height);

            DialogProgress.updateProgressInvoke(dialogProgress, 0, "Creating video clips.");

            // For each episode
            foreach (List <InfoCombined> combArray in workerVars.CombinedAll)
            {
                episodeCount++;

                // It is possible for all lines in an episode to be set to inactive
                if (combArray.Count == 0)
                {
                    // Skip this episode
                    continue;
                }

                string progressText = String.Format("Converting video file {0} of {1}",
                                                    episodeCount,
                                                    totalEpisodes);

                DialogProgress.updateProgressInvoke(dialogProgress, progressText);

                DateTime entireClipStartTime = combArray[0].Subs1.StartTime;
                DateTime entireClipEndTime   = combArray[combArray.Count - 1].Subs1.EndTime;

                // Apply pad to entire clip timings  (if requested)
                if (Settings.Instance.VideoClips.PadEnabled)
                {
                    entireClipStartTime = UtilsSubs.applyTimePad(entireClipStartTime, -Settings.Instance.VideoClips.PadStart);
                    entireClipEndTime   = UtilsSubs.applyTimePad(entireClipEndTime, Settings.Instance.VideoClips.PadEnd);
                }

                // Enable detail mode in progress dialog
                DialogProgress.enableDetailInvoke(dialogProgress, true);

                // Set the duration of the clip in the progress dialog  (for detail mode)
                DateTime entireClipDuration = UtilsSubs.getDurationTime(entireClipStartTime, entireClipEndTime);
                DialogProgress.setDuration(dialogProgress, entireClipDuration);

                string tempVideoFilename = Path.GetTempPath() + ConstantSettings.TempVideoFilename;
                string videoExtension    = ".avi";

                // Convert entire video (from first line to last line) based on user settings (size, crop, bitrate, etc).
                // It will be cut into smaller video clips later.
                if (Settings.Instance.VideoClips.IPodSupport)
                {
                    videoExtension     = ".mp4";
                    tempVideoFilename += videoExtension;

                    UtilsVideo.convertVideo(Settings.Instance.VideoClips.Files[episodeCount - 1],
                                            Settings.Instance.VideoClips.AudioStream.Num,
                                            entireClipStartTime, entireClipEndTime,
                                            Settings.Instance.VideoClips.Size, Settings.Instance.VideoClips.Crop,
                                            Settings.Instance.VideoClips.BitrateVideo, Settings.Instance.VideoClips.BitrateAudio,
                                            UtilsVideo.VideoCodec.h264, UtilsVideo.AudioCodec.AAC,
                                            UtilsVideo.Profilex264.IPod640, UtilsVideo.Presetx264.SuperFast,
                                            tempVideoFilename, dialogProgress);
                }
                else
                {
                    tempVideoFilename += videoExtension;

                    UtilsVideo.convertVideo(Settings.Instance.VideoClips.Files[episodeCount - 1],
                                            Settings.Instance.VideoClips.AudioStream.Num,
                                            entireClipStartTime, entireClipEndTime,
                                            Settings.Instance.VideoClips.Size, Settings.Instance.VideoClips.Crop,
                                            Settings.Instance.VideoClips.BitrateVideo, Settings.Instance.VideoClips.BitrateAudio,
                                            UtilsVideo.VideoCodec.MPEG4, UtilsVideo.AudioCodec.MP3,
                                            UtilsVideo.Profilex264.None, UtilsVideo.Presetx264.None,
                                            tempVideoFilename, dialogProgress);
                }

                DialogProgress.enableDetailInvoke(dialogProgress, false);

                // Generate a video clip for each line of the episode
                foreach (InfoCombined comb in combArray)
                {
                    progessCount++;

                    progressText = string.Format("Generating video clip: {0} of {1}",
                                                 progessCount.ToString(),
                                                 totalLines.ToString());

                    int progress = Convert.ToInt32(progessCount * (100.0 / totalLines));

                    // Update the progress dialog
                    DialogProgress.updateProgressInvoke(dialogProgress, progress, progressText);

                    // Did the user press the cancel button?
                    if (dialogProgress.Cancel)
                    {
                        File.Delete(tempVideoFilename);
                        return(false);
                    }

                    // Adjust timing to sync with the start of the converted video (which starts at the episode's first line of dialog)
                    DateTime startTime = UtilsSubs.shiftTiming(comb.Subs1.StartTime, -((int)entireClipStartTime.TimeOfDay.TotalMilliseconds));
                    DateTime endTime   = UtilsSubs.shiftTiming(comb.Subs1.EndTime, -((int)entireClipStartTime.TimeOfDay.TotalMilliseconds));

                    // Times used in the filename
                    DateTime filenameStartTime = comb.Subs1.StartTime;
                    DateTime filenameEndTime   = comb.Subs1.EndTime;

                    // Apply pad (if requested)
                    if (Settings.Instance.VideoClips.PadEnabled)
                    {
                        startTime         = UtilsSubs.applyTimePad(startTime, -Settings.Instance.VideoClips.PadStart);
                        endTime           = UtilsSubs.applyTimePad(endTime, Settings.Instance.VideoClips.PadEnd);
                        filenameStartTime = UtilsSubs.applyTimePad(comb.Subs1.StartTime, -Settings.Instance.VideoClips.PadStart);
                        filenameEndTime   = UtilsSubs.applyTimePad(comb.Subs1.EndTime, Settings.Instance.VideoClips.PadEnd);
                    }

                    // Create output filename
                    string nameStr = name.createName(ConstantSettings.VideoFilenameFormat, (int)episodeCount + Settings.Instance.EpisodeStartNumber - 1,
                                                     progessCount, filenameStartTime, filenameEndTime, comb.Subs1.Text, comb.Subs2.Text);

                    string outFile = string.Format("{0}{1}{2}{3}",
                                                   workerVars.MediaDir,         // {0}
                                                   Path.DirectorySeparatorChar, // {1}
                                                   nameStr,                     // {2}
                                                   videoExtension);             // {3}

                    // Cut video clip for current line
                    UtilsVideo.cutVideo(tempVideoFilename, startTime, endTime, outFile);
                }

                File.Delete(tempVideoFilename);
            }

            return(true);
        }
        /// <summary>
        /// Performs the work of the audio extraction thread.
        /// </summary>
        private void splitAudio(object sender, DoWorkEventArgs e)
        {
            WorkerVars workerVars = e.Argument as WorkerVars;
            List <List <InfoCombined> > combinedAll = new List <List <InfoCombined> >();
            WorkerSubs subsWorker = new WorkerSubs();

            if (groupBoxCheckLyrics.Checked)
            {
                // Parse and combine the subtitles
                try
                {
                    combinedAll = subsWorker.combineAllSubs(workerVars, dialogProgress);

                    if (combinedAll != null)
                    {
                        workerVars.CombinedAll = combinedAll;
                    }
                    else
                    {
                        e.Cancel = true;
                        return;
                    }
                }
                catch (Exception e1)
                {
                    UtilsMsg.showErrMsg("Something went wrong before processing could start.\n" + e1);
                    e.Cancel = true;
                    return;
                }
            }

            DateTime mediaStartime = new DateTime();
            DateTime mediaEndtime  = new DateTime();
            DateTime mediaDuration = new DateTime();

            int episode = 0;

            DialogProgress.updateProgressInvoke(dialogProgress, 0, "Starting...");


            foreach (string file in mediaFiles)
            {
                episode++;

                try
                {
                    mediaEndtime = UtilsVideo.getVideoLength(file);
                }
                catch (Exception e1)
                {
                    UtilsMsg.showErrMsg("Something went wrong while determining duration of the media:\n" + e1);
                    return;
                }

                if (useSpan)
                {
                    mediaStartime = spanStart;

                    // If the span end time if not greater than the actual duration of the media
                    if (spanEnd < mediaEndtime)
                    {
                        mediaEndtime = spanEnd;
                    }
                }

                UtilsName name = new UtilsName(
                    deckName,
                    mediaFiles.Length, // Total number of episodes
                    1,                 // Total number of lines (Note: not filled out here)
                    mediaEndtime,      // Last time
                    0, 0               // Width and height (Note: not filled out anywhere)
                    );

                mediaDuration = UtilsSubs.getDurationTime(mediaStartime, mediaEndtime);

                string progressText = String.Format("Processing audio from media file {0} of {1}",
                                                    episode,
                                                    mediaFiles.Length);

                int progress = Convert.ToInt32((episode - 1) * (100.0 / mediaFiles.Length));

                DialogProgress.updateProgressInvoke(dialogProgress, progress, progressText);

                // Enable detail mode in progress dialog
                DialogProgress.enableDetailInvoke(dialogProgress, true);

                // Set the duration of the clip in the progress dialog  (for detail mode)
                DialogProgress.setDuration(dialogProgress, mediaDuration);


                string tempMp3Filename = Path.GetTempPath() + ConstantSettings.TempAudioFilename;

                UtilsAudio.ripAudioFromVideo(mediaFiles[episode - 1],
                                             audioStream.Num,
                                             mediaStartime, mediaEndtime,
                                             bitrate, tempMp3Filename, dialogProgress);

                DialogProgress.enableDetailInvoke(dialogProgress, false);

                if (dialogProgress.Cancel)
                {
                    e.Cancel = true;
                    File.Delete(tempMp3Filename);
                    return;
                }

                int numClips = 1;

                if (!isSingleFile)
                {
                    numClips = (int)Math.Ceiling((mediaDuration.TimeOfDay.TotalMilliseconds / (clipLength.TimeOfDay.TotalSeconds * 1000.0)));
                }

                for (int clipIdx = 0; clipIdx < numClips; clipIdx++)
                {
                    progressText = String.Format("Splitting segment {0} of {1} from media file {2} of {3}",
                                                 clipIdx + 1,
                                                 numClips,
                                                 episode,
                                                 mediaFiles.Length);

                    progress = Convert.ToInt32((episode - 1) * (100.0 / mediaFiles.Length));

                    DialogProgress.updateProgressInvoke(dialogProgress, progress, progressText);


                    if (dialogProgress.Cancel)
                    {
                        e.Cancel = true;
                        File.Delete(tempMp3Filename);
                        return;
                    }

                    // The start and end times used for processing
                    DateTime startTime = new DateTime();
                    DateTime endTime   = new DateTime();

                    if (isSingleFile)
                    {
                        endTime = mediaDuration;
                    }
                    else
                    {
                        startTime = startTime.AddSeconds((double)(clipLength.TimeOfDay.TotalSeconds * clipIdx));
                        endTime   = endTime.AddSeconds((double)(clipLength.TimeOfDay.TotalSeconds * (clipIdx + 1)));

                        if (endTime.TimeOfDay.TotalMilliseconds >= mediaDuration.TimeOfDay.TotalMilliseconds)
                        {
                            endTime = mediaDuration;
                        }
                    }

                    // The start and end times that will be displayed
                    DateTime startTimeName = startTime.AddMilliseconds(mediaStartime.TimeOfDay.TotalMilliseconds);
                    DateTime endTimeName   = endTime.AddMilliseconds(mediaStartime.TimeOfDay.TotalMilliseconds);

                    // Fill in the total number of lines with the total number of clips
                    name.TotalNumLines = numClips;

                    string nameStr = name.createName(ConstantSettings.ExtractMediaAudioFilenameFormat, episode + episodeStartNumber - 1,
                                                     clipIdx + 1, startTimeName, endTimeName, "", "");


                    string outName = String.Format("{0}{1}{2}",
                                                   outputDir,                   // {0}
                                                   Path.DirectorySeparatorChar, // {1}
                                                   nameStr);                    // {2}

                    UtilsAudio.cutAudio(tempMp3Filename, startTime, endTime, outName);

                    nameStr = name.createName(ConstantSettings.AudioId3Artist, episode + episodeStartNumber - 1,
                                              clipIdx + 1, startTimeName, endTimeName, "", "");

                    string tagArtist = String.Format("{0}",
                                                     nameStr); // {0}

                    nameStr = name.createName(ConstantSettings.AudioId3Album, episode + episodeStartNumber - 1,
                                              clipIdx + 1, startTimeName, endTimeName, "", "");

                    string tagAlbum = String.Format("{0}",
                                                    nameStr); // {0}

                    nameStr = name.createName(ConstantSettings.AudioId3Title, episode + episodeStartNumber - 1,
                                              clipIdx + 1, startTimeName, endTimeName, "", "");

                    string tagTitle = String.Format("{0}",
                                                    nameStr); // {0}

                    nameStr = name.createName(ConstantSettings.AudioId3Genre, episode + episodeStartNumber - 1,
                                              clipIdx + 1, startTimeName, endTimeName, "", "");

                    string tagGenre = String.Format("{0}",
                                                    nameStr); // {0}

                    string tagLyrics = "";

                    if (groupBoxCheckLyrics.Checked)
                    {
                        int totalLyricsLines = 0;
                        int curLyricsNum     = 1;

                        // Precount the number of lyrics lines
                        foreach (InfoCombined comb in combinedAll[episode - 1])
                        {
                            if (comb.Subs1.StartTime.TimeOfDay.TotalMilliseconds >= startTimeName.TimeOfDay.TotalMilliseconds &&
                                comb.Subs1.StartTime.TimeOfDay.TotalMilliseconds <= endTimeName.TimeOfDay.TotalMilliseconds)
                            {
                                totalLyricsLines++;
                            }
                        }

                        // Fill in the total number of lyrics lines
                        name.TotalNumLines = curLyricsNum;

                        // Foreach comb in the current episode, if the comb lies within the
                        // current clip, add it to the lryics tag
                        foreach (InfoCombined comb in combinedAll[episode - 1])
                        {
                            if (comb.Subs1.StartTime.TimeOfDay.TotalMilliseconds >= startTimeName.TimeOfDay.TotalMilliseconds &&
                                comb.Subs1.StartTime.TimeOfDay.TotalMilliseconds <= endTimeName.TimeOfDay.TotalMilliseconds)
                            {
                                tagLyrics += formatLyricsPair(comb, name, startTimeName, episode + episodeStartNumber - 1, curLyricsNum) + "\r\n";
                                curLyricsNum++;
                            }
                        }
                    }

                    UtilsAudio.tagAudio(outName,
                                        tagArtist,
                                        tagAlbum,
                                        tagTitle,
                                        tagGenre,
                                        tagLyrics,
                                        clipIdx + 1,
                                        numClips);
                }
            }

            return;
        }