/// <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); }
/// <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); }
/// <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(); }
/// <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); }
/// <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()); }
/// <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); }
/// <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); }
/// <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); }
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); }
/// <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)); }
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; } }
/// <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; } } }
/// <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> /// 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); }