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