/// <summary> /// Get the available audio streams from a video file /// </summary> /// <param name="file">The video file</param> public static List <InfoStream> getAvailableAudioStreams(string file) { string videoInfo = ""; List <InfoStream> streamInfos = new List <InfoStream>(); videoInfo = getVideoInfoStr(file); MatchCollection lineMatches = Regex.Matches(videoInfo, @".*Stream #(?<AudioStreamNum>\d\:\d)\(?(?<AudioStreamLang>\w*)\)?: Audio: (?<AudioStreamType>.*)", RegexOptions.Compiled); if (lineMatches.Count != 0) { int count = 0; foreach (Match match in lineMatches) { string streamNum = match.Groups["AudioStreamNum"].ToString().Trim(); streamNum = streamNum.Replace(".", ":"); string streamLang = UtilsLang.LangThreeLetter2Full(match.Groups["AudioStreamLang"].ToString().Trim()); string streamType = match.Groups["AudioStreamType"].ToString().Trim(); streamInfos.Add(new InfoStream(streamNum, count.ToString(), streamLang, streamType)); count++; } } return(streamInfos); }
private void backgroundWorkerMain_DoWork(object sender, DoWorkEventArgs e) { BackgroundWorker worker = sender as BackgroundWorker; MkvExtractProgress progress = new MkvExtractProgress(); progress.MaxEpisode = selectedMkvFiles.Count; foreach (string file in selectedMkvFiles) { progress.CurEpisode++; List <MkvTrack> tracks = null; if (trackTypeToExtract == "All subtitle tracks") { tracks = UtilsMkv.getSubtitleTrackList(file); } else if (trackTypeToExtract == "All audio tracks") { tracks = UtilsMkv.getAudioTrackList(file); } else { tracks = UtilsMkv.getTrackList(file); } progress.CurTrack = 0; progress.MaxTrack = tracks.Count; foreach (MkvTrack track in tracks) { if (worker.CancellationPending) { e.Cancel = true; return; } progress.CurTrack++; worker.ReportProgress(0, progress); string displayLang = UtilsLang.LangThreeLetter2Full(track.Lang); if (displayLang == "") { displayLang = "Unknown"; } string fileName = $"{outDir}{Path.DirectorySeparatorChar}{Path.GetFileNameWithoutExtension(file)} - Track {Convert.ToInt32(track.TrackID):00} - {displayLang}.{track.Extension}"; UtilsMkv.extractTrack(file, track.TrackID, fileName); } } }
/// <summary> /// Read a float setting. /// </summary> public static float getFloat(string key, float def) { string defString = def.ToString(); string valString = ""; float value = 0; valString = getString(key, defString); try { value = (float)UtilsLang.toDouble(valString); } catch { value = def; } return(value); }
public override string ToString() { string displayLang = UtilsLang.LangThreeLetter2Full(Lang); string displayedExtension = Extension.ToUpper(); if (Lang == "und" || Lang == "" || displayLang == "") { displayLang = "Unknown Language"; } if (TrackType == UtilsMkv.TrackType.SUBTITLES) { if (displayedExtension == "SUB") { displayedExtension = "VOBSUB"; } } return($"{TrackID} - {displayedExtension} ({displayLang})"); }
public override string ToString() { string displayLang = UtilsLang.LangThreeLetter2Full(this.Lang); string displayedExtension = this.Extension.ToUpper(); if ((this.Lang == "und") || (this.Lang == "") || (displayLang == "")) { displayLang = "Unknown Language"; } if (this.TrackType == UtilsMkv.TrackType.SUBTITLES) { if (displayedExtension == "SUB") { displayedExtension = "VOBSUB"; } } return(String.Format("{0} - {1} ({2})", this.TrackID, displayedExtension, displayLang)); }
/// <summary> /// Parse the subtitle file and return a list of lines. /// </summary> override public List <InfoLine> parse() { List <InfoLine> lineInfos = new List <InfoLine>(); StreamReader subFile = new StreamReader(this.File, this.SubsEncoding); XmlTextReader xmlReader = new XmlTextReader(subFile); xmlReader.XmlResolver = null; // Ignore dtd DateTime startTime = new DateTime(); DateTime endTime = new DateTime(); DateTime curTime = new DateTime(); DateTime turnEndTime = new DateTime(); string dialogText = ""; int syncCount = 0; while (xmlReader.Read()) { if (xmlReader.NodeType == XmlNodeType.Element) { if (xmlReader.Name.ToLower() == "sync") { // Example sync: <Sync time="1.027"/> syncCount++; string timeStr = xmlReader.GetAttribute("time"); try { curTime = new DateTime(); curTime = curTime.AddSeconds(UtilsLang.toDouble(timeStr)); } catch (Exception e1) { throw new Exception(String.Format("Incorrect time format detected: {0}\n\n{1}", timeStr, e1)); } if (syncCount == 1) { startTime = curTime; } else if (syncCount == 2) { endTime = curTime; } else { startTime = endTime; endTime = curTime; } // If this is not the first time and the length isn't blank if ((syncCount > 1) && (dialogText.Length != 0)) { lineInfos.Add(this.createLineInfo(dialogText, startTime, endTime)); dialogText = ""; } } else if (xmlReader.Name.ToLower() == "turn") { // Example turn: <Turn speaker="spk1" startTime="2.263" endTime="25.566"> string timeStr = xmlReader.GetAttribute("endTime"); turnEndTime = new DateTime(); turnEndTime = curTime.AddSeconds(UtilsLang.toDouble(timeStr)); } } else if (xmlReader.NodeType == XmlNodeType.Text) { dialogText += xmlReader.Value; } else if (xmlReader.NodeType == XmlNodeType.EndElement) { // This section handles the final line before the </turn>. // We need to do this because there isn't a Sync tag after the final line. if (xmlReader.Name.ToLower() == "turn") // </Turn> { const double MAX_FINAL_LINE_DURATION = 10.0; startTime = endTime; endTime = turnEndTime; // Calculate the difference between the startTime and turnEndTime and make sure that // it is a reasonable length. We do this because the turn end time isn't necessarily // the end of the line. If it is not a reasonable length, set it to MAX_FINAL_LINE_DURATION. double diffTime = endTime.TimeOfDay.TotalSeconds - startTime.TimeOfDay.TotalSeconds; if (diffTime > MAX_FINAL_LINE_DURATION) { endTime = startTime; endTime = endTime.AddSeconds(MAX_FINAL_LINE_DURATION); } if ((syncCount >= 1) && (dialogText.Length != 0)) { lineInfos.Add(this.createLineInfo(dialogText, startTime, endTime)); dialogText = ""; } // If needed, restore endtime to the turnEndTime if (diffTime >= MAX_FINAL_LINE_DURATION) { endTime = turnEndTime; } } } } subFile.Close(); // Since the dialog lines don't have to be in chronological order, sort by the start time lineInfos.Sort(); return(lineInfos); }
/// <summary> /// Inactivate lines from episodes based on include/exclude lists, duplicate lines, etc. /// Does not remove lines, only modifies their active flag. /// </summary> public List <List <InfoCombined> > inactivateLines(WorkerVars workerVars, DialogProgress dialogProgress) { int totalLines = 0; int progessCount = 0; foreach (List <InfoCombined> combArray in workerVars.CombinedAll) { totalLines += combArray.Count; } bool checkIncludesExludes = Settings.Instance.Subs[0].IncludedWords.Length != 0 || Settings.Instance.Subs[1].IncludedWords.Length != 0 || Settings.Instance.Subs[0].ExcludedWords.Length != 0 || Settings.Instance.Subs[1].ExcludedWords.Length != 0; Hashtable allLinesSoFarSubs1 = new Hashtable(); Hashtable allLinesSoFarSubs2 = new Hashtable(); bool removeDupsSubs1 = Settings.Instance.Subs[0].ExcludeDuplicateLinesEnabled; bool removeDupsSubs2 = Settings.Instance.Subs[1].ExcludeDuplicateLinesEnabled && Settings.Instance.Subs[1].FilePattern != ""; bool checkDups = removeDupsSubs1 || removeDupsSubs2; // For each episode foreach (List <InfoCombined> combArray in workerVars.CombinedAll) { List <InfoCombined> compArrayRemoved = new List <InfoCombined>(); // For each line in episode foreach (InfoCombined comb in combArray) { bool isExcluded = false; progessCount++; // Don't process if subtitles are vobsub bool isSubs1Vobsub = UtilsSubs.filePatternContainsVobsubs(Settings.Instance.Subs[0].FilePattern); bool isSubs2Vobsub = UtilsSubs.filePatternContainsVobsubs(Settings.Instance.Subs[1].FilePattern); // Remove lines not in the span if (Settings.Instance.SpanEnabled && !isExcluded) { DateTime spanStart = Settings.Instance.SpanStart; DateTime spanEnd = Settings.Instance.SpanEnd; if (comb.Subs1.StartTime < spanStart || comb.Subs1.StartTime > spanEnd) { isExcluded = true; } } bool passedIgnoreShorterThanTime = true; // Make sure that line is at least the min amount of milliseconds as specified by user if (Settings.Instance.Subs[0].ExcludeShorterThanTimeEnabled && Settings.Instance.Subs[0].TimingsEnabled) { passedIgnoreShorterThanTime = Math.Abs((int)comb.Subs1.EndTime.TimeOfDay.TotalMilliseconds - (int)comb.Subs1.StartTime.TimeOfDay.TotalMilliseconds) >= Settings.Instance.Subs[0].ExcludeShorterThanTime; } else if (Settings.Instance.Subs[1].ExcludeShorterThanTimeEnabled && Settings.Instance.Subs[1].TimingsEnabled) { // Note: using Subs1 here is not a mistake because Subs2 timings will be placed into Subs1 in combineSubs(). passedIgnoreShorterThanTime = Math.Abs((int)comb.Subs1.EndTime.TimeOfDay.TotalMilliseconds - (int)comb.Subs1.StartTime.TimeOfDay.TotalMilliseconds) >= Settings.Instance.Subs[1].ExcludeShorterThanTime; } if (!passedIgnoreShorterThanTime && !isExcluded) { isExcluded = true; } bool passedIgnoreLongerThanTime = true; // Make sure that line is at least the min amount of milliseconds as specified by user if (Settings.Instance.Subs[0].ExcludeLongerThanTimeEnabled && Settings.Instance.Subs[0].TimingsEnabled) { passedIgnoreLongerThanTime = Math.Abs((int)comb.Subs1.EndTime.TimeOfDay.TotalMilliseconds - (int)comb.Subs1.StartTime.TimeOfDay.TotalMilliseconds) <= Settings.Instance.Subs[0].ExcludeLongerThanTime; } else if (Settings.Instance.Subs[1].ExcludeLongerThanTimeEnabled && Settings.Instance.Subs[1].TimingsEnabled) { // Note: using Subs1 here is not a mistake because Subs2 timings will be placed into Subs1 in combineSubs(). passedIgnoreLongerThanTime = Math.Abs((int)comb.Subs1.EndTime.TimeOfDay.TotalMilliseconds - (int)comb.Subs1.StartTime.TimeOfDay.TotalMilliseconds) <= Settings.Instance.Subs[1].ExcludeLongerThanTime; } if (!passedIgnoreLongerThanTime && !isExcluded) { isExcluded = true; } // Make sure that line is at least the min character length as specified by user bool passedIgnoreFewerTestSubs1 = isSubs1Vobsub || !Settings.Instance.Subs[0].ExcludeFewerEnabled || Settings.Instance.Subs[0].ExcludeFewerEnabled && comb.Subs1.Text.Length >= Settings.Instance.Subs[0].ExcludeFewerCount; bool passedIgnoreFewerTestSubs2 = isSubs2Vobsub || !Settings.Instance.Subs[1].ExcludeFewerEnabled || Settings.Instance.Subs[1].ExcludeFewerEnabled && comb.Subs2.Text.Length >= Settings.Instance.Subs[1].ExcludeFewerCount; if ((!passedIgnoreFewerTestSubs1 || !passedIgnoreFewerTestSubs2) && !isExcluded) { isExcluded = true; } // Remove based on actors if (Settings.Instance.ActorList.Count > 0 && !isExcluded) { bool actorFound = false; foreach (string actor in Settings.Instance.ActorList) { if (Settings.Instance.Subs[0].ActorsEnabled) { if (comb.Subs1.Actor.Trim().ToLower() == actor.Trim().ToLower()) { actorFound = true; break; } } else { if (comb.Subs2.Actor.Trim().ToLower() == actor.Trim().ToLower()) { actorFound = true; break; } } } isExcluded = !actorFound; } // Remove based on include/exclude lists if (checkIncludesExludes && !isExcluded) { if (!isSubs1Vobsub && Settings.Instance.Subs[0].ExcludedWords.Length != 0) { foreach (string word in Settings.Instance.Subs[0].ExcludedWords) { if (comb.Subs1.Text.ToLower().Contains(word.ToLower())) { isExcluded = true; } } } if (!isSubs2Vobsub && Settings.Instance.Subs[1].ExcludedWords.Length != 0 && !isExcluded) { foreach (string word in Settings.Instance.Subs[1].ExcludedWords) { if (comb.Subs2.Text.ToLower().Contains(word.ToLower())) { isExcluded = true; } } } if (!isSubs1Vobsub && Settings.Instance.Subs[0].IncludedWords.Length != 0 && !isExcluded) { bool wordFound = false; foreach (string word in Settings.Instance.Subs[0].IncludedWords) { if (comb.Subs1.Text.ToLower().Contains(word.ToLower())) { wordFound = true; break; } } isExcluded = !wordFound; } if (!isSubs2Vobsub && Settings.Instance.Subs[1].IncludedWords.Length != 0 && !isExcluded) { bool wordFound = false; foreach (string word in Settings.Instance.Subs[1].IncludedWords) { if (comb.Subs2.Text.ToLower().Contains(word.ToLower())) { wordFound = true; break; } } isExcluded = !wordFound; } } // Remove Duplicates if (checkDups && !isExcluded) { if (!isSubs1Vobsub && removeDupsSubs1) { if (allLinesSoFarSubs1.Contains(comb.Subs1.Text.ToLower())) { isExcluded = true; } else { allLinesSoFarSubs1.Add(comb.Subs1.Text.ToLower(), comb); } } if (!isSubs2Vobsub && removeDupsSubs2) { if (allLinesSoFarSubs2.Contains(comb.Subs2.Text.ToLower())) { isExcluded = true; } else { allLinesSoFarSubs2.Add(comb.Subs2.Text.ToLower(), comb); } } } // Remove lines without a kanji if (Settings.Instance.LangaugeSpecific.KanjiLinesOnly && !isExcluded) { if (!isSubs1Vobsub && !UtilsLang.containsIdeograph(comb.Subs1.Text) && !isSubs2Vobsub && !UtilsLang.containsIdeograph(comb.Subs2.Text)) { isExcluded = true; } } // Unset the active flag if (isExcluded) { comb.Active = false; } string progressText = $"Setting active lines based on user specified rules: {Convert.ToInt32(progessCount * (100.0 / totalLines))}%"; int progress = Convert.ToInt32(progessCount * (100.0 / totalLines)); DialogProgress.updateProgressInvoke(dialogProgress, progress, progressText); if (dialogProgress.Cancel) { return(null); } } } return(workerVars.CombinedAll); }