/// <summary> /// /// </summary> /// <param name="fileName"></param> /// <param name="completedCallback">抽取的轨道,不包含重复轨道;重复轨道文件名带有.bak</param> public MediaFile Extract(Action <double, EACProgressType> progressCallback) { if (!new FileInfo(sourceFile).Exists) { return(null); } _progressCallback = progressCallback; state = ProcessState.FetchStream; StartEac($"\"{sourceFile}\"", false); var args = new List <string>(); var extractResult = new List <TrackInfo>(); List <TrackInfo> srcAudio = new List <TrackInfo>(); List <TrackInfo> srcSub = new List <TrackInfo>(); foreach (TrackInfo track in tracks) { switch (track.Type) { case TrackType.Audio: srcAudio.Add(track); break; case TrackType.Subtitle: srcSub.Add(track); break; default: break; } } if (srcAudio.Count != JobAudio.Count) { OKETaskException ex = new OKETaskException(Constants.audioNumMismatchSmr); ex.progress = 0.0; ex.Data["SRC_TRACK"] = srcAudio.Count; ex.Data["DST_TRACK"] = JobAudio.Count; throw ex; } if (srcSub.Count != JobSub.Count) { OKETaskException ex = new OKETaskException(Constants.subNumMismatchSmr); ex.progress = 0.0; ex.Data["SRC_TRACK"] = srcSub.Count; ex.Data["DST_TRACK"] = JobSub.Count; throw ex; } int audioId = 0, subId = 0; foreach (TrackInfo track in tracks) { EacOutputTrackType trackType = s_eacOutputs.Find(val => val.Codec == track.Codec); if (!(trackType.Extract || trackType.Type == TrackType.Video && extractVideo)) { continue; } ; if (track.Type == TrackType.Audio) { AudioInfo jobAudioInfo = JobAudio[audioId++]; if (jobAudioInfo.MuxOption == MuxOption.Skip) { continue; } } if (track.Type == TrackType.Subtitle) { Info jobSubInfo = JobSub[subId++]; if (jobSubInfo.MuxOption == MuxOption.Skip) { continue; } } args.Add($"{track.Index}:\"{track.OutFileName}\""); extractResult.Add(track); } JobAudio.RemoveAll(info => info.MuxOption == MuxOption.Skip); JobSub.RemoveAll(info => info.MuxOption == MuxOption.Skip); state = ProcessState.ExtractStream; StartEac($"\"{sourceFile}\" {string.Join(" ", args)}", true); foreach (TrackInfo track in extractResult) { FileInfo finfo = new FileInfo(track.OutFileName); if (!finfo.Exists || finfo.Length == 0) { throw new Exception("文件输出失败: " + track.OutFileName); } else { track.FileSize = finfo.Length; } if (track.Type == TrackType.Audio) { FFmpegVolumeChecker checker = new FFmpegVolumeChecker(track.OutFileName); checker.start(); checker.waitForFinish(); track.MaxVolume = checker.MaxVolume; track.MeanVolume = checker.MeanVolume; } } List <int> removeList = new List <int>(); for (int i = 0; i < extractResult.Count; i++) { TrackInfo track = extractResult[i]; if (removeList.Contains(track.Index)) { continue; } if (track.IsEmpty()) { Logger.Warn(track.OutFileName + "被检测为空轨道。"); removeList.Add(track.Index); track.MarkSkipping(); continue; } for (int j = i + 1; j < extractResult.Count; j++) { TrackInfo other = extractResult[j]; if (track.IsDuplicate(other)) { Logger.Warn(track.OutFileName + "被检测为与" + other.OutFileName + "重复。"); removeList.Add(other.Index); other.MarkSkipping(); } } } MediaFile mf = new MediaFile(); audioId = 0; subId = 0; foreach (var item in extractResult) { OKEFile file = new OKEFile(item.OutFileName); switch (item.Type) { case TrackType.Audio: AudioInfo audioInfo = JobAudio[audioId++]; audioInfo.DupOrEmpty = item.DupOrEmpty; mf.AddTrack(new AudioTrack(file, audioInfo)); break; case TrackType.Subtitle: Info subInfo = JobSub[subId++]; subInfo.DupOrEmpty = item.DupOrEmpty; mf.AddTrack(new SubtitleTrack(file, subInfo)); break; case TrackType.Chapter: FileInfo txtChapter = new FileInfo(Path.ChangeExtension(sourceFile, ".txt")); if (txtChapter.Exists) { Logger.Info("检测到单独准备的章节,不予添加"); } else { file.Rename(txtChapter.FullName); } break; case TrackType.Video: mf.AddTrack(new VideoTrack(file, new VideoInfo())); break; default: System.Windows.MessageBox.Show(item.OutFileName, "不认识的轨道呢"); break; } } return(mf); }