/// <summary>
        /// Format a single line of .ass dialog text.
        /// </summary>
        private string formatDialogSingle(bool isSubs1, InfoCombined comb)
        {
            string name   = "";
            string text   = "";
            string single = "";

            if (isSubs1)
            {
                name = "Subs1";
                text = comb.Subs1.Text;
            }
            else
            {
                name = "Subs2";
                text = comb.Subs2.Text;
            }

            // Example:
            // Dialogue: 0,0:00:31.14,0:00:36.16,Subs1,NA,0000,0000,0000,,This is the first line from Subs1
            single = String.Format("Dialogue: 0,{0},{1},{2},NA,0000,0000,0000,,{3}",
                                   UtilsSubs.formatAssTime(comb.Subs1.StartTime),
                                   UtilsSubs.formatAssTime(comb.Subs1.EndTime),
                                   name,
                                   text);

            return(single);
        }
        private void textBoxSubs2File_Validating(object sender, CancelEventArgs e)
        {
            string error       = null;
            string filePattern = ((TextBox)sender).Text.Trim();

            string[] files = UtilsCommon.getNonHiddenFiles(filePattern);

            if ((error == null) && (UtilsSubs.getNumSubsFiles(filePattern) == 0))
            {
                error = "Please provide a valid subtitle file. \nOnly .srt, .ass and .ssa are allowed.";
                invalidCount++;
            }

            if ((error == null))
            {
                foreach (string f in files)
                {
                    if (!isSupportedSubtitleFormat(f))
                    {
                        error = "Please provide a valid subtitle file. \nOnly .srt, .ass and .ssa are allowed.";
                        invalidCount++;
                        break;
                    }
                }
            }

            if ((error == null) && (UtilsSubs.getNumSubsFiles(filePattern) != UtilsSubs.getNumSubsFiles(textBoxSubs1File.Text.Trim())))
            {
                error = "The number of files here must match\nthe number of subtitle files in Subs1.";
                invalidCount++;
            }

            errorProvider1.SetError((Control)sender, error);
        }
示例#3
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);
        }
示例#4
0
        /// <summary>
        /// Experimental video preview on the selected line.
        /// </summary>
        private void buttonPreviewVideo_Click(object sender, EventArgs e)
        {
            string videoConfigPlayer = "";

            if (previewWorkerVars == null || currentInfoComb == null || Settings.Instance.VideoClips.Files.Length == 0)
            {
                return;
            }

            videoConfigPlayer = ConstantSettings.VideoPlayer;

            // Check if the player exists
            if (!File.Exists(videoConfigPlayer))
            {
                UtilsMsg.showErrMsg(
                    $"The video player \"{ConstantSettings.VideoPlayer}\" \nprovided in {ConstantSettings.SettingsFilename} does not exist!");

                return;
            }

            // Kill the player before running it again.
            // For some reason the players that I tested (MPC-HC, ZoomPlayer, VLC) don't
            // read the start time arg correctly unless they are killed first.
            if (videoPlayerProcess != null)
            {
                if (!videoPlayerProcess.HasExited)
                {
                    videoPlayerProcess.Kill();
                }
            }

            DateTime startTime = currentInfoComb.Subs1.StartTime;
            DateTime endTime   = currentInfoComb.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);
            }

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

            string videoConfigArgs = name.createName(ConstantSettings.VideoPlayerArgs,
                                                     comboBoxEpisode.SelectedIndex + Settings.Instance.EpisodeStartNumber - 1, 0, startTime, endTime, "",
                                                     "");

            string videoFileName = Settings.Instance.VideoClips.Files[comboBoxEpisode.SelectedIndex];
            string procArgs      = $"{videoConfigArgs} \"{videoFileName}\"";

            // Play the video
            videoPlayerProcess = new Process();
            videoPlayerProcess.StartInfo.FileName        = videoConfigPlayer;
            videoPlayerProcess.StartInfo.Arguments       = procArgs;
            videoPlayerProcess.StartInfo.UseShellExecute = false;
            videoPlayerProcess.StartInfo.CreateNoWindow  = true;
            videoPlayerProcess.Start();
        }
示例#5
0
        /// <summary>
        /// Generate snapshots for all episodes.
        /// </summary>
        public bool genSnapshots(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);

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

                // For each line in episode, generate a snapshot
                foreach (InfoCombined t in combArray)
                {
                    progessCount++;

                    string progressText = $"Generating snapshot: {progessCount.ToString()} of {totalLines.ToString()}";

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

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

                    InfoCombined comb      = t;
                    DateTime     startTime = comb.Subs1.StartTime;
                    DateTime     endTime   = comb.Subs1.EndTime;
                    DateTime     midTime   = UtilsSubs.getMidpointTime(startTime, endTime);

                    string videoFileName = Settings.Instance.VideoClips.Files[episodeCount - 1];

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

                    string outFile = $"{workerVars.MediaDir}{Path.DirectorySeparatorChar}{nameStr}"; // {2}

                    // Generate snapshot
                    UtilsSnapshot.takeSnapshotFromVideo(videoFileName, midTime, Settings.Instance.Snapshots.Size,
                                                        Settings.Instance.Snapshots.Crop, outFile);

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

            return(true);
        }
示例#6
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);
        }
        /// <summary>
        /// Update the global settings based on GUI.
        /// </summary>
        private void updateSettings()
        {
            mediaFiles         = UtilsCommon.getNonHiddenFiles(textBoxMediaFile.Text.Trim());
            audioStream        = (InfoStream)comboBoxStreamAudioFromVideo.SelectedItem;
            outputDir          = textBoxOutputDir.Text.Trim();
            deckName           = textBoxName.Text.Trim().Replace(" ", "_");
            episodeStartNumber = Convert.ToInt32(numericUpDownEpisodeStartNumber.Text.Trim());
            isSingleFile       = radioButtonSingle.Checked;

            if (groupBoxCheckLyrics.Checked)
            {
                Settings.Instance.Subs[0].FilePattern         = textBoxSubs1File.Text.Trim();
                Settings.Instance.Subs[0].TimingsEnabled      = radioButtonTimingSubs1.Checked;
                Settings.Instance.Subs[0].TimeShift           = (int)numericUpDownTimeShiftSubs1.Value;
                Settings.Instance.Subs[0].Files               = UtilsSubs.getSubsFiles(Settings.Instance.Subs[0].FilePattern).ToArray();
                Settings.Instance.Subs[0].Encoding            = InfoEncoding.longToShort(this.comboBoxEncodingSubs1.Text);
                Settings.Instance.Subs[0].RemoveNoCounterpart = this.checkBoxRemoveLinesWithoutCounterpartSubs1.Checked;
                Settings.Instance.Subs[0].RemoveStyledLines   = this.checkBoxRemoveStyledLinesSubs1.Checked;

                Settings.Instance.Subs[1].FilePattern         = textBoxSubs2File.Text.Trim();
                Settings.Instance.Subs[1].TimingsEnabled      = radioButtonTimingSubs2.Checked;
                Settings.Instance.Subs[1].TimeShift           = (int)numericUpDownTimeShiftSubs2.Value;
                Settings.Instance.Subs[1].Encoding            = InfoEncoding.longToShort(this.comboBoxEncodingSubs2.Text);
                Settings.Instance.Subs[1].RemoveNoCounterpart = this.checkBoxRemoveLinesWithoutCounterpartSubs2.Checked;
                Settings.Instance.Subs[1].RemoveStyledLines   = this.checkBoxRemoveStyledLinesSubs2.Checked;

                if (Settings.Instance.Subs[1].FilePattern.Trim().Length > 0)
                {
                    Settings.Instance.Subs[1].Files = UtilsSubs.getSubsFiles(Settings.Instance.Subs[1].FilePattern).ToArray();
                }
                else
                {
                    Settings.Instance.Subs[1].Files = new string[0];
                }

                Settings.Instance.TimeShiftEnabled = groupBoxCheckTimeShift.Checked;
            }

            if (!isSingleFile)
            {
                clipLength = UtilsSubs.stringToTime(maskedTextBoxClipLength.Text.Trim());
            }

            useSpan = this.groupBoxCheckSpan.Checked;

            if (useSpan)
            {
                spanStart = UtilsSubs.stringToTime(maskedTextBoxSpanStart.Text.Trim());
                spanEnd   = UtilsSubs.stringToTime(maskedTextBoxSpanEnd.Text.Trim());
            }

            bitrate = Convert.ToInt32(comboBoxBitrate.Text.Trim());
        }
示例#8
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);
        }
示例#9
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);
        }
示例#10
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);
        }
示例#11
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);
                }
            }
        }
        private void textBoxSubs2File_Validating(object sender, CancelEventArgs e)
        {
            string error       = null;
            string filePattern = ((TextBox)sender).Text.Trim();

            string[] files = UtilsCommon.getNonHiddenFiles(filePattern);

            if (groupBoxCheckLyrics.Checked)
            {
                if ((radioButtonTimingSubs2.Checked) && (filePattern == ""))
                {
                    error = "Since you want to use subs2 timings,\nplease enter a valid Subs2 subtitle file here";
                    invalidCount++;
                }

                if ((error == null) && (filePattern != ""))
                {
                    if ((error == null) && (UtilsSubs.getNumSubsFiles(filePattern) == 0))
                    {
                        error = "Please provide a valid subtitle file. \nOnly .srt, .ass, .ssa, .lrc and .trs are allowed.";
                        invalidCount++;
                    }

                    if ((error == null))
                    {
                        foreach (string f in files)
                        {
                            if (!isSupportedSubtitleFormat(f))
                            {
                                error = "Please provide a valid subtitle file. \nOnly .srt, .ass, .ssa, .lrc and .trs are allowed.";
                                invalidCount++;
                                break;
                            }
                        }
                    }

                    if ((error == null) && (UtilsSubs.getNumSubsFiles(filePattern) != UtilsCommon.getNonHiddenFiles(textBoxMediaFile.Text.Trim()).Length))
                    {
                        error = "The number of files here must match\nthe number of files in Media";
                        invalidCount++;
                    }
                }
            }

            errorProvider1.SetError((Control)sender, error);
        }
示例#13
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));
        }
示例#14
0
        private void updateSettings()
        {
            try
            {
                Settings.Instance.Subs[0].FilePattern         = textBoxSubs1File.Text.Trim();
                Settings.Instance.Subs[0].TimingsEnabled      = radioButtonTimingSubs1.Checked;
                Settings.Instance.Subs[0].TimeShift           = (int)numericUpDownTimeShiftSubs1.Value;
                Settings.Instance.Subs[0].Files               = UtilsSubs.getSubsFiles(Settings.Instance.Subs[0].FilePattern).ToArray();
                Settings.Instance.Subs[0].Encoding            = InfoEncoding.longToShort(this.comboBoxEncodingSubs1.Text);
                Settings.Instance.Subs[0].RemoveNoCounterpart = this.checkBoxRemoveLinesWithoutCounterpartSubs1.Checked;
                Settings.Instance.Subs[0].RemoveStyledLines   = this.checkBoxRemoveStyledLinesSubs1.Checked;

                Settings.Instance.Subs[1].FilePattern         = textBoxSubs2File.Text.Trim();
                Settings.Instance.Subs[1].TimingsEnabled      = radioButtonTimingSubs2.Checked;
                Settings.Instance.Subs[1].TimeShift           = (int)numericUpDownTimeShiftSubs2.Value;
                Settings.Instance.Subs[1].Files               = UtilsSubs.getSubsFiles(Settings.Instance.Subs[1].FilePattern).ToArray();
                Settings.Instance.Subs[1].Encoding            = InfoEncoding.longToShort(this.comboBoxEncodingSubs2.Text);
                Settings.Instance.Subs[1].RemoveNoCounterpart = this.checkBoxRemoveLinesWithoutCounterpartSubs2.Checked;
                Settings.Instance.Subs[1].RemoveStyledLines   = this.checkBoxRemoveStyledLinesSubs2.Checked;

                Settings.Instance.OutputDir = textBoxOutputDir.Text.Trim();

                Settings.Instance.TimeShiftEnabled = groupBoxTimeShift.Checked;

                Settings.Instance.DeckName           = textBoxName.Text.Trim();
                Settings.Instance.EpisodeStartNumber = (int)numericUpDownEpisodeStartNumber.Value;

                duelPattern = (int)this.numericUpDownPattern.Value;

                isSubs1First = (this.comboBoxPriority.SelectedIndex == 0);

                quickReference = this.checkBoxQuickReference.Checked;
            }
            catch (Exception e1)
            {
                UtilsMsg.showErrMsg("Something went wrong while gathering interface data:\n" + e1);
                return;
            }
        }
示例#15
0
        /// <summary>
        /// Update the image preview.
        /// </summary>
        private void updateImagePreview(InfoCombined selectedComb)
        {
            if (selectedComb == null)
            {
                return;
            }

            // Update the snapshot
            if (Settings.Instance.VideoClips.Files.Length > 0 && checkBoxSnapshotPreview.Checked)
            {
                string   videoFileName = Settings.Instance.VideoClips.Files[comboBoxEpisode.SelectedIndex];
                DateTime midTime       = UtilsSubs.getMidpointTime(selectedComb.Subs1.StartTime, selectedComb.Subs1.EndTime);
                string   outFile       = previewWorkerVars.MediaDir + Path.DirectorySeparatorChar +
                                         ConstantSettings.TempImageFilename;

                try
                {
                    File.Delete(outFile);
                }
                catch
                {
                    // File is locked
                    return;
                }

                UtilsSnapshot.takeSnapshotFromVideo(videoFileName, midTime, Settings.Instance.Snapshots.Size,
                                                    Settings.Instance.Snapshots.Crop, outFile);

                if (File.Exists(outFile))
                {
                    Image image = UtilsSnapshot.getImageFromFile(outFile);

                    image = UtilsSnapshot.fitImageToSize(image,
                                                         new Size(pictureBoxImage.Width, pictureBoxImage.Height));

                    pictureBoxImage.Image = image;
                }
            }
        }
示例#16
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);
        }
示例#17
0
        /// <summary>
        /// Get a list with the inactive lines removed from each episode.
        /// </summary>
        public List <List <InfoCombined> > removeInactiveLines(WorkerVars workerVars, DialogProgress dialogProgress,
                                                               bool dontRemoveContextLines)
        {
            int totalLines   = 0;
            int progessCount = 0;
            List <List <InfoCombined> > activeLines = new List <List <InfoCombined> >();

            bool subs1ContainsVobsubs = UtilsSubs.filePatternContainsVobsubs(Settings.Instance.Subs[0].FilePattern);
            bool subs2ContainsVobsubs = UtilsSubs.filePatternContainsVobsubs(Settings.Instance.Subs[1].FilePattern);

            foreach (List <InfoCombined> combArray in workerVars.CombinedAll)
            {
                totalLines += combArray.Count;
            }

            // For each episode
            foreach (List <InfoCombined> combArray in workerVars.CombinedAll)
            {
                List <InfoCombined> currentEpisodeActiveLines = new List <InfoCombined>();

                // For each line in episode
                foreach (InfoCombined comb in combArray)
                {
                    progessCount++;

                    if (comb.Active || dontRemoveContextLines && comb.OnlyNeededForContext)
                    {
                        currentEpisodeActiveLines.Add(comb);
                    }
                    else
                    {
                        if (subs1ContainsVobsubs)
                        {
                            try
                            {
                                // Multiple vobsub images can be shown in a single line, so extract each image and delete it
                                List <string> vobsubImages = UtilsSubs.extractVobsubFilesFromText(comb.Subs1.Text);

                                foreach (string vobsubImage in vobsubImages)
                                {
                                    File.Delete(workerVars.MediaDir + Path.DirectorySeparatorChar + vobsubImage);
                                }
                            }
                            catch
                            {
                                // Don't care
                            }
                        }

                        if (subs2ContainsVobsubs)
                        {
                            try
                            {
                                // Multiple vobsub image can be shown in a single line, so extract each image and delete it
                                List <string> vobsubImages = UtilsSubs.extractVobsubFilesFromText(comb.Subs2.Text);

                                foreach (string vobsubImage in vobsubImages)
                                {
                                    File.Delete(workerVars.MediaDir + Path.DirectorySeparatorChar + vobsubImage);
                                }
                            }
                            catch
                            {
                                // Don't care
                            }
                        }
                    }

                    string progressText =
                        $"Remove inactive lines: {Convert.ToInt32(progessCount * (100.0 / totalLines))}%";

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

                    DialogProgress.updateProgressInvoke(dialogProgress, progress, progressText);

                    if (dialogProgress.Cancel)
                    {
                        return(null);
                    }
                }

                activeLines.Add(currentEpisodeActiveLines);
            }

            return(activeLines);
        }