public static void Extract (string filereal, Queue item) { if (item.Data.IsFileMkv || (item.Data.IsFileAvs && Properties.Settings.Default.AvsMkvCopy)) { int sc = 0; foreach (var subs in GetStream.Media(filereal, StreamType.Subtitle)) TaskManager.Run($"\"{Plugin.LIBAV}\" -i \"{filereal}\" -map {subs.ID} -y sub{sc++:0000}_{subs.Lang}.{subs.Format}"); foreach (var font in GetStream.MediaMkv(filereal, StreamType.Attachment)) TaskManager.Run($"\"{Plugin.MKVEX}\" attachments \"{filereal}\" {font.ID}:\"{font.File}\""); TaskManager.Run($"\"{Plugin.MKVEX}\" chapters \"{filereal}\" > chapters.xml"); } }
public static void Audio (string filereal, Queue item) { if (string.Equals(item.Audio.Encoder, "No Audio", IC)) { // Do noting } else if (string.Equals(item.Audio.Encoder, "Passthrough (Extract all audio)", IC)) { int counter = 0; foreach (var audio in GetStream.Media(filereal, StreamType.Audio)) { TaskManager.Run($"\"{Plugin.LIBAV}\" -i \"{filereal}\" -map {audio.ID} -acodec copy -y audio{counter++:0000}_{audio.Lang}.{audio.Format}"); } } else { string frequency; if (string.Equals(item.Audio.Frequency, "auto", IC)) frequency = ""; else frequency = "-ar " + item.Audio.Frequency; string channel; if (string.Equals(item.Audio.Channel, "auto", IC)) channel = ""; else if (string.Equals(item.Audio.Channel, "mono", IC)) channel = "-ac 1"; else channel = "-ac 2"; int counter = 0; foreach (var codec in Plugin.List) { if (string.Equals(codec.Profile.Name, item.Audio.Encoder, IC)) { foreach (var audio in GetStream.Media(filereal, StreamType.Audio)) { string outfile = $"audio{counter++:0000}_{audio.Lang}"; TaskManager.Run($"\"{Plugin.LIBAV}\" -i \"{filereal}\" -map {audio.ID} {frequency} {channel} -y {outfile}.wav"); TaskManager.Run($"\"{codec.App.Bin}\" {codec.Arg.Bitrate} {item.Audio.BitRate} {item.Audio.Command} {codec.Arg.Input} {outfile}.wav {codec.Arg.Output} {outfile}.{codec.App.Ext}"); File.Delete(Path.Combine(Default.DirTemp, outfile + ".wav")); } break; } } } }
public static void Extract(Queue item) { if (string.IsNullOrEmpty(item.Data.File)) return; string realfile = GetStream.AviSynthGetFile(item.Data.File); if (item.Data.IsFileMkv || (item.Data.IsFileAvs && Default.AvsMkvCopy)) { int sc = 0; foreach (var subs in GetStream.Subtitle(realfile)) TaskManager.Run($"\"{Plugin.FFMPEG}\" -i \"{realfile}\" -map {subs.Id} -y subtitle{sc++:0000}_{subs.Lang}.{subs.Format}"); TaskManager.Run($"\"{Plugin.FFMPEG}\" -dump_attachment:t \"\" -i \"{realfile}\" -y"); TaskManager.Run($"\"{Plugin.MKVEXT}\" chapters \"{realfile}\" > chapters.xml"); } }
public static void Extract(string file, Queue item) { if (item.Data.IsFileAvs) file = GetStream.AviSynthGetFile(file); if (string.IsNullOrEmpty(file)) return; if (item.Data.IsFileMkv || (item.Data.IsFileAvs && Default.AvsMkvCopy)) { int sc = 0; foreach (var subs in GetStream.Media(file, StreamType.Subtitle)) TaskManager.Run($"\"{Plugin.LIBAV}\" -i \"{file}\" -map {subs.ID} -y sub{sc++:0000}_{subs.Lang}.{subs.Format}"); foreach (var font in GetStream.MediaMkv(file, StreamType.Attachment)) TaskManager.Run($"\"{Plugin.MKVEX}\" attachments \"{file}\" {font.ID}:\"{font.File}\""); TaskManager.Run($"\"{Plugin.MKVEX}\" chapters \"{file}\" > chapters.xml"); } }
void QueueAdd(string file) { if (Get.IsPathNetwork(file)) { InvokeLog($"This file from Network, please mount, rejected: {file}"); return; } FFmpeg.Bin = Plugin.FFMPEG; FFmpeg.Probe = Plugin.FFPROBE; var Info = new Queue(); var i = cboProfile.SelectedIndex; // Profiles var p = Profile.List[i == 0 ? 0 : i - 1]; // When profiles at <new> mean auto detect // todo var ff = new FFmpeg.Stream(file); Info.FilePath = file; Info.General.IsOutputMKV = i == 0 ? true : string.Equals(p.Info.Format, "mkv", IC); Info.General.IsAviSynth = string.Equals(ff.FormatName, "avisynth", IC); Info.General.Duration = ff.Duration; if (ff.Video.Count > 0) { // Picture section Info.Picture.FrameCount = ff.Video[0].FrameCount; Info.Picture.Resolution = i == 0 ? "auto" : p.Picture.Resolution; Info.Picture.FrameRate = i == 0 ? "auto" : p.Picture.FrameRate; Info.Picture.BitDepth = i == 0 ? ff.Video[0].BitPerColour : p.Picture.BitDepth; Info.Picture.Chroma = i == 0 ? 420 : p.Picture.Chroma; } else { InvokeLog($"This file has no video, rejected: {file}"); return; } // Video section Info.Video.Preset = i == 0 ? "medium" : p.Video.Preset; Info.Video.Tune = i == 0 ? "off" : p.Video.Tune; Info.Video.Type = i == 0 ? 0 : p.Video.Type; Info.Video.Value = i == 0 ? "26" : p.Video.Value; Info.Video.Command = i == 0 ? "--dither" : p.Video.Command; // Audio section Plugin dummy; bool exist = Plugin.List.TryGetValue(p.Audio.Encoder, out dummy); Guid encoder = i == 0 || !exist ? new Guid("ffffffff-ffff-ffff-ffff-ffffffffffff") : p.Audio.Encoder; string bitRate = i == 0 || !exist ? "256" : p.Audio.BitRate; string frequency = i == 0 || !exist ? "auto" : p.Audio.Freq; string channel = i == 0 || !exist ? "auto" : p.Audio.Chan; string command = i == 0 || !exist ? null : p.Audio.Args; foreach (var item in ff.Audio) Info.Audio.Add(new Queue.audio { Enable = true, File = file, Embedded = true, Id = item.Id, Lang = item.Language, Codec = item.Codec, Format = Get.MediaContainer(item.Codec), RawBit = item.BitDepth, RawFreq = item.SampleRate, RawChan = item.Channel, Encoder = encoder, BitRate = bitRate, Freq = frequency, Chan = channel, Args = command }); // Subtitle Info.SubtitleEnable = ff.Subtitle.Count > 0; foreach (var item in ff.Subtitle) { Info.Subtitle.Add(new Queue.subtitle { File = file, Id = item.Id, Lang = item.Language, Codec = item.Codec, Format = Get.MediaContainer(item.Codec), }); } // Add to queue list ListViewItem qItem = new ListViewItem(new[] { Get.FileName(file), Get.FileSize(file), ff.FormatNameFull, Info.General.IsOutputMKV ? "Matroska" : "MPEG-4", "Ready" }); qItem.Tag = Info; qItem.Checked = true; lstQueue.Items.Add(qItem); // Print to log InvokeLog($"File added {Info.FilePath}"); }
public static void Audio(string filereal, Queue item) { if (string.IsNullOrEmpty(filereal)) return; string frequency; if (string.Equals(item.Audio.Frequency, "auto", IC)) frequency = ""; else frequency = "-ar " + item.Audio.Frequency; string channel; if (string.Equals(item.Audio.Channel, "auto", IC)) channel = ""; else if (string.Equals(item.Audio.Channel, "mono", IC)) channel = "-ac 1"; else channel = "-ac 2"; string ffcmd = item.Picture.Command; if (string.Equals(item.Audio.Encoder, "No Audio", IC)) { // Do noting } else if (string.Equals(item.Audio.Encoder, "Passthrough (Extract all audio)", IC)) { // Extract all int counter = 0; foreach (var audio in GetStream.Media(filereal, StreamType.Audio)) { // Drop current tracks if set if (DropCurrentAudio(audio.ID, item)) continue; TaskManager.Run($"\"{Plugin.LIBAV}\" -i \"{filereal}\" -dn -vn -sn -map {audio.ID} -acodec copy {ffcmd} -y audio{counter++:0000}_{audio.Lang}.{audio.Format}"); } // check if got any unsupported codec if (!item.Data.SaveAsMkv) { foreach (var audio in Directory.GetFiles(Default.DirTemp, "audio*")) { if (!string.Equals(Path.GetExtension(audio), ".mp4", IC)) { TaskManager.Run($"\"{Plugin.LIBAV}\" -i \"{audio}\" -strict -2 -c:a aac -b:a {item.Audio.BitRate}k {frequency} {channel} -y {Path.GetFileNameWithoutExtension(audio)}.mp4"); File.Delete(audio); // delete unwanted } } } } else { int counter = 0; foreach (var codec in Plugin.List) { if (string.Equals(codec.Profile.Name, item.Audio.Encoder, IC)) { if (item.Audio.Merge) { int count = 0; string map = string.Empty; foreach (var audio in GetStream.Media(filereal, StreamType.Audio)) { // Drop current tracks if set if (DropCurrentAudio(audio.ID, item)) continue; count++; map += $"-map {audio.ID} "; } TaskManager.Run($"\"{Plugin.LIBAV}\" -i \"{filereal}\" {map} -filter_complex amix=inputs={count}:duration=first:dropout_transition=0 {frequency} {channel} {ffcmd} -y audio0000_und.wav"); TaskManager.Run($"\"{codec.App.Bin}\" {codec.Arg.Bitrate} {item.Audio.BitRate} {item.Audio.Command} {codec.Arg.Input} audio0000_und.wav {codec.Arg.Output} audio0000_und.{codec.App.Ext}"); File.Delete(Path.Combine(Default.DirTemp, "audio0000_und.wav")); } else { foreach (var audio in GetStream.Media(filereal, StreamType.Audio)) { // Drop current tracks if set if (DropCurrentAudio(audio.ID, item)) continue; string outfile = $"audio{counter++:0000}_{audio.Lang}"; TaskManager.Run($"\"{Plugin.LIBAV}\" -i \"{filereal}\" -map {audio.ID} {frequency} {channel} {ffcmd} -y {outfile}.wav"); TaskManager.Run($"\"{codec.App.Bin}\" {codec.Arg.Bitrate} {item.Audio.BitRate} {item.Audio.Command} {codec.Arg.Input} {outfile}.wav {codec.Arg.Output} {outfile}.{codec.App.Ext}"); File.Delete(Path.Combine(Default.DirTemp, outfile + ".wav")); } } break; } } } }
void QueueAdd(string file) { string FileType; var Info = new Queue(); var i = cboProfile.SelectedIndex; // Profiles var p = Profile.List[i == 0 ? 0 : i - 1]; // When profiles at <new> mean auto detect Info.Data.File = file; Info.Data.SaveAsMkv = i == 0 ? true : string.Equals(p.Info.Format, "mkv", IC); MediaFile AVI = new MediaFile(file); Info.Data.IsFileMkv = string.Equals(AVI.format, "Matroska", IC); Info.Data.IsFileAvs = GetInfo.IsAviSynth(file); if (!Plugin.AviSynthInstalled) { if (Info.Data.IsFileAvs) { InvokeLog($"AviSynth not installed, skipping this file: {file}"); return; } } // Picture section if (AVI.Video.Count > 0) { var Video = AVI.Video[0]; Info.Picture.Resolution = i == 0 ? $"{Video.width}x{Video.height}" : p.Picture.Resolution; Info.Picture.FrameRate = i == 0 ? $"{Video.frameRateGet}" : p.Picture.FrameRate; Info.Picture.BitDepth = i == 0 ? $"{Video.bitDepth}" : p.Picture.BitDepth; Info.Picture.Chroma = i == 0 ? "420" : p.Picture.Chroma; Info.Prop.Duration = Video.duration; Info.Prop.FrameCount = Video.frameCount; Info.Picture.IsCopy = false; Info.Picture.IsHevc = string.Equals(Video.format, "HEVC", IC); FileType = $"{Path.GetExtension(file).ToUpper()} ({Video.format})"; if (string.Equals(Video.frameRateMode, "vfr", IC)) Info.Prop.IsVFR = true; if (Video.isInterlace) { Info.Picture.YadifEnable = true; Info.Picture.YadifMode = 0; Info.Picture.YadifField = (Video.isTopFieldFirst ? 0 : 1); Info.Picture.YadifFlag = 0; } } else { if (Info.Data.IsFileAvs) { Info.Picture.Resolution = "auto"; Info.Picture.FrameRate = "auto"; Info.Picture.BitDepth = "8"; Info.Picture.Chroma = "420"; FileType = "AviSynth Script"; } else { FileType = "Unknown"; } } // Video section Info.Video.Preset = i == 0 ? "medium" : p.Video.Preset; Info.Video.Tune = i == 0 ? "off" : p.Video.Tune; Info.Video.Type = i == 0 ? 0 : p.Video.Type; Info.Video.Value = i == 0 ? "26" : p.Video.Value; Info.Video.Command = i == 0 ? "--dither" : p.Video.Command; // Audio section bool exist = Plugin.IsExist(p.Audio.Encoder); Info.Audio.Encoder = i == 0 || !exist ? Plugin.Default.Audio.Name : p.Audio.Encoder; Info.Audio.BitRate = i == 0 || !exist ? Plugin.Default.Audio.BitRate : p.Audio.BitRate; Info.Audio.Frequency = i == 0 || !exist ? Plugin.Default.Audio.Frequency : p.Audio.Frequency; Info.Audio.Channel = i == 0 || !exist ? Plugin.Default.Audio.Channel : p.Audio.Channel; Info.Audio.Command = i == 0 || !exist ? Plugin.Default.Audio.Command : p.Audio.Command; // Drop audio tracks support foreach (var item in GetStream.Media(file, StreamType.Audio)) Info.DropAudioId.Add(new DropAudio { Id = item.ID, Text = $"{item.ID}, {item.Lang}, {item.OtherInfo}", Checked = false }); // Add to queue list ListViewItem qItem = new ListViewItem(new[] { GetInfo.FileName(file), GetInfo.FileSize(file), FileType, $".{(Info.Data.SaveAsMkv ? "MKV" : "MP4")} (HEVC)", "Ready" }); qItem.Tag = Info; qItem.Checked = true; lstQueue.Items.Add(qItem); // Print to log InvokeLog($"File added {Info.Data.File}"); }
public static void Video(string file, Queue item) { foreach (var video in GetStream.Media(file, StreamType.Video)) { // Copy if (item.Picture.IsHevc) { if (item.Picture.IsCopy) { TaskManager.Run($"\"{Plugin.LIBAV}\" -i \"{file}\" -map {video.ID} -c:v copy -bsf hevc_mp4toannexb -y video0000_{video.Lang}.hevc"); return; } } // ffmpeg settings string resolution = string.Equals(item.Picture.Resolution, "auto", IC) ? "" : $"-s {item.Picture.Resolution}"; string framerate = string.Equals(item.Picture.FrameRate, "auto", IC) ? "" : $"-r {item.Picture.FrameRate}"; int bitdepth = item.Picture.BitDepth; string chroma = $"yuv{item.Picture.Chroma}p{(bitdepth > 8 ? $"{bitdepth}le" : "")}"; string yadif = item.Picture.YadifEnable ? $"-vf \"yadif={item.Picture.YadifMode}:{item.Picture.YadifField}:{item.Picture.YadifFlag}\"" : ""; int framecount = item.Prop.FrameCount; string vsync = "cfr"; string ffcmd = item.Picture.Command; if (string.IsNullOrEmpty(framerate)) { if (item.Prop.IsVFR) { TaskManager.Run($"\"{Plugin.FFMS2}\" -f -c \"{file}\" timecode"); vsync = "vfr"; } } else // when fps is set, generate new framecount { framecount = (int)Math.Ceiling(((float)item.Prop.Duration / 1000.0) * Convert.ToDouble(item.Picture.FrameRate, CultureInfo.InvariantCulture)); } if (item.Picture.YadifEnable) { if (item.Picture.YadifMode == 1) { framecount *= 2; // make each fields as new frame } } if (item.Data.IsFileAvs) // get new framecount for avisynth framecount = GetStream.AviSynthFrameCount(file); // x265 settings string decbin = Plugin.LIBAV; string encbin = Plugin.HEVC08; string preset = item.Video.Preset; string tune = string.Equals(item.Video.Tune, "off", IC) ? "" : $"--tune {item.Video.Tune}"; int type = item.Video.Type; int pass; string value = item.Video.Value; string command = item.Video.Command; if (item.Data.IsFileAvs) decbin = Plugin.AVS4P; string decoder = item.Data.IsFileAvs ? $"\"{decbin}\" video \"{file}\"" : $"\"{decbin}\" -i \"{file}\" -vsync {vsync} -f yuv4mpegpipe -pix_fmt {chroma} -strict -1 {resolution} {framerate} {yadif} {ffcmd} -"; if (bitdepth == 10) encbin = Plugin.HEVC10; else if (bitdepth == 12) encbin = Plugin.HEVC12; string encoder = $"\"{encbin}\" --y4m - -p {preset} {(type == 0 ? "--crf" : type == 1 ? "--qp" : "--bitrate")} {value} {command} -o video0000_{video.Lang}.hevc"; // Encoding start if (type-- >= 3) // multi pass { for (int i = 0; i < type; i++) { if (i == 0) pass = 1; else if (i == type) pass = 2; else pass = 3; if (i == 1) // get actual frame count framecount = GetStream.FrameCount(Path.Combine(Default.DirTemp, $"video0000_{video.Lang}.hevc")); Console.WriteLine($"Pass {i + 1} of {type + 1}"); // human read no index TaskManager.Run($"{decoder} 2> {NULL} | {encoder} -f {framecount} --pass {pass}"); } } else { TaskManager.Run($"{decoder} 2> {NULL} | {encoder} -f {framecount}"); } break; } }
public static void Mux(Queue item) { // Final output, a file name without extension string savedir = Default.IsDirOutput ? Default.DirOutput : Path.GetDirectoryName(item.Data.File); string newfile = Path.GetFileNameWithoutExtension(item.Data.File); string prefix = Default.IsDirOutput ? Default.NamePrefix : string.IsNullOrEmpty(Default.NamePrefix) ? "[encoded] " : Default.NamePrefix + " "; string fileout = Path.Combine(savedir, $"{prefix}{newfile}"); // Destinantion folder check if (!Directory.Exists(Default.DirOutput)) Directory.CreateDirectory(Default.DirOutput); if (item.Data.SaveAsMkv) { fileout += ".mkv"; string tags = string.Format(Properties.Resources.Tags, Global.App.NameFull, Global.App.VersionCompiled); string cmdvideo = null; string cmdaudio = null; string cmdsubs = null; string cmdattach = null; string cmdchapter = null; foreach (var tc in Directory.GetFiles(Default.DirTemp, "timecode_*")) { cmdvideo += $"--timecodes 0:\"{tc}\" "; break; } foreach (var video in Directory.GetFiles(Default.DirTemp, "video*")) { cmdvideo += $"--language 0:{GetInfo.FileLang(video)} \"{video}\" "; } foreach (var audio in Directory.GetFiles(Default.DirTemp, "audio*")) { cmdaudio += $"--language 0:{GetInfo.FileLang(audio)} \"{audio}\" "; } if (item.SubtitleEnable) { foreach (var subs in item.Subtitle) { cmdsubs += $"--sub-charset 0:UTF-8 --language 0:{subs.Lang.Substring(0, 3)} \"{subs.File}\" "; } } else { foreach (var subs in Directory.GetFiles(Default.DirTemp, "sub*")) { cmdsubs += $"--sub-charset 0:UTF-8 --language 0:{GetInfo.FileLang(subs)} \"{subs}\" "; } } if (item.AttachEnable) { foreach (var attach in item.Attach) { cmdattach += $"--attachment-mime-type {attach.MIME} --attachment-description {attach.Comment} --attach-file \"{attach.File}\" "; } } else { foreach (var attach in Directory.GetFiles(Default.DirTemp, "*.ttf")) { cmdattach += $"--attach-file \"{attach}\" "; } foreach (var attach in Directory.GetFiles(Default.DirTemp, "*.otf")) { cmdattach += $"--attach-file \"{attach}\" "; } foreach (var attach in Directory.GetFiles(Default.DirTemp, "*.woff")) { cmdattach += $"--attach-file \"{attach}\" "; } foreach (var attach in Directory.GetFiles(Default.DirTemp, "*.pfb")) { cmdattach += $"--attachment-mime-type application/x-font --attach-file \"{attach}\" "; } } if (File.Exists(Path.Combine(Default.DirTemp, "chapters.xml"))) { FileInfo ChapLen = new FileInfo(Path.Combine(Default.DirTemp, "chapters.xml")); if (ChapLen.Length > 256) cmdchapter = $"--chapters \"{Path.Combine(Default.DirTemp, "chapters.xml")}\""; } File.WriteAllText(Path.Combine(Default.DirTemp, "tags.xml"), tags); TaskManager.Run($"\"{Plugin.MKVME}\" -o \"{fileout}\" -t 0:tags.xml --disable-track-statistics-tags {cmdvideo} {cmdaudio} {cmdsubs} {cmdattach} {cmdchapter}"); } else { fileout += ".mp4"; string timecode = null; string cmdvideo = null; string cmdaudio = null; foreach (var tc in Directory.GetFiles(Default.DirTemp, "timecode_*")) { timecode = tc; break; } int cntv = 0; foreach (var video in Directory.GetFiles(Default.DirTemp, "video*")) { cmdvideo += $"-add \"{video}#video:name=Video {++cntv}:lang={GetInfo.FileLang(video)}:fmt=HEVC\" "; } int cnta = 0; foreach (var audio in Directory.GetFiles(Default.DirTemp, "audio*")) { cmdaudio += $"-add \"{audio}#audio:name=Audio {++cnta}:lang={GetInfo.FileLang(audio)}\" "; } if (string.IsNullOrEmpty(timecode)) { TaskManager.Run($"\"{Plugin.MP4BX}\" {cmdvideo} {cmdaudio} -itags tool=\"{Global.App.NameFull}\" -new \"{fileout}\""); } else { TaskManager.Run($"\"{Plugin.MP4BX}\" {cmdvideo} {cmdaudio} -itags tool=\"{Global.App.NameFull}\" -new _desu.mp4"); TaskManager.Run($"\"{Plugin.MP4FP}\" -t \"{timecode}\" _desu.mp4 -o \"{fileout}\""); } } }
void QueueAdd(string file) { string FileType; var Info = new Queue(); Info.Data.File = file; Info.Data.SaveAsMkv = true; MediaFile AVI = new MediaFile(file); Info.Data.IsFileMkv = string.Equals(AVI.format, "Matroska", IC); Info.Data.IsFileAvs = GetInfo.IsAviSynth(file); if (!Plugin.AviSynthInstalled) { if (Info.Data.IsFileAvs) { InvokeLog($"AviSynth not installed, skipping this file: {file}"); return; } } if (AVI.Video.Count > 0) { var Video = AVI.Video[0]; Info.Picture.Resolution = $"{Video.width}x{Video.height}"; Info.Picture.FrameRate = $"{Video.frameRateGet}"; Info.Picture.BitDepth = $"{Video.bitDepth}"; Info.Picture.Chroma = "420"; Info.Prop.Duration = Video.duration; Info.Prop.FrameCount = Video.frameCount; FileType = $"{Path.GetExtension(file).ToUpper()} ({Video.format})"; if (string.Equals(Video.frameRateMode, "vfr", IC)) Info.Prop.IsVFR = true; if (Video.isInterlace) { Info.Picture.YadifEnable = true; Info.Picture.YadifMode = 0; Info.Picture.YadifField = (Video.isTopFieldFirst ? 0 : 1); Info.Picture.YadifFlag = 0; } } else { if (Info.Data.IsFileAvs) { Info.Picture.Resolution = "auto"; Info.Picture.FrameRate = "auto"; Info.Picture.BitDepth = "8"; Info.Picture.Chroma = "420"; FileType = "AviSynth Script"; } else { FileType = "Unknown"; } } Info.Video.Preset = "medium"; Info.Video.Tune = "off"; Info.Video.Type = 0; Info.Video.Value = "26"; Info.Video.Command = "--dither"; Info.Audio.Encoder = "Passthrough (Extract all audio)"; Info.Audio.BitRate = "128"; Info.Audio.Frequency = "auto"; Info.Audio.Channel = "stereo"; Info.Audio.Command = ""; // Add to queue list ListViewItem qItem = new ListViewItem(new[] { GetInfo.FileName(file), GetInfo.FileSize(file), FileType, ".MKV (HEVC)", "Ready" }); qItem.Tag = Info; qItem.Checked = true; lstQueue.Items.Add(qItem); // Print to log InvokeLog($"File added {Info.Data.File}"); }
private static bool DropCurrentAudio(string currentId, Queue currentAudio) { if (currentAudio.DropAudioTracks) foreach (var item in currentAudio.DropAudioId) if (string.Equals(currentId, item.Id, IC)) if (item.Checked) return true; return false; }
public static void Audio(string file, Queue item) { if (item.Data.IsFileAvs) file = GetStream.AviSynthGetFile(file); if (string.IsNullOrEmpty(file)) return; string ffmap = ""; string ffcmd = item.Picture.Command; int counter = 0; foreach (var track in item.Audio) { string bit = $"{track.RawBit}"; string frequency = string.Equals(track.Freq, "auto", IC) ? $"{track.RawFreq}" : $"{track.Freq}"; string channel = string.Equals(track.Chan, "auto", IC) ? $"{track.RawChan}" : string.Equals(track.Chan, "stereo", IC) ? "2" : "1"; if (item.AudioMerge) { counter++; ffmap += $"-map {track.Id} "; if (item.Audio.Count == counter) { foreach (var codec in Plugin.List) { if (string.Equals(item.Audio[0].Encoder, codec.Profile.Name, IC)) { TaskManager.Run($"\"{Plugin.LIBAV}\" -i \"{file}\" {ffmap} -filter_complex amix=inputs={counter}:duration=first:dropout_transition=0 -acodec pcm_s{bit}le -ar {frequency} -ac {channel} -f wav {ffcmd} - 2> {NULL} | \"{codec.App.Bin}\" {(string.IsNullOrEmpty(codec.Arg.Raw) ? string.Empty : string.Format(codec.Arg.Raw, frequency, bit, channel))} {codec.Arg.Input} {codec.Arg.Bitrate} {track.BitRate} {track.Args} {codec.Arg.Output} audio0000_und.{codec.App.Ext}"); } } } } else { if (!track.Enable) continue; if (string.Equals(track.Encoder, "No Audio", IC)) { // Do noting } else if (string.Equals(track.Encoder, "Passthrough (Extract all audio)", IC)) { if (item.Data.SaveAsMkv) { if (string.Equals("wma", track.Format, IC)) { TaskManager.Run($"\"{Plugin.LIBAV}\" -i \"{file}\" -map {track.Id} -dn -vn -sn -strict -2 -c:a aac -b:a {track.BitRate}k -ar {frequency} -ac {channel} -y audio{counter++:0000}_{track.Lang}.mp4"); } else { TaskManager.Run($"\"{Plugin.LIBAV}\" -i \"{file}\" -map {track.Id} -dn -vn -sn -acodec copy {ffcmd} -y audio{counter++:0000}_{track.Lang}.{track.Format}"); } } else { if (string.Equals("mp4", track.Format, IC)) { TaskManager.Run($"\"{Plugin.LIBAV}\" -i \"{file}\" -map {track.Id} -dn -vn -sn -acodec copy {ffcmd} -y audio{counter++:0000}_{track.Lang}.{track.Format}"); } else { TaskManager.Run($"\"{Plugin.LIBAV}\" -i \"{file}\" -map {track.Id} -dn -vn -sn -strict -2 -c:a aac -b:a {track.BitRate}k -ar {frequency} -ac {channel} -y audio{counter++:0000}_{track.Lang}.mp4"); } } } else { foreach (var codec in Plugin.List) { if (string.Equals(codec.Profile.Name, track.Encoder, IC)) { TaskManager.Run($"\"{Plugin.LIBAV}\" -i \"{file}\" -map {track.Id} -acodec pcm_s{bit}le -ar {frequency} -ac {channel} -f wav {ffcmd} - 2> {NULL} | \"{codec.App.Bin}\" {(string.IsNullOrEmpty(codec.Arg.Raw) ? string.Empty : string.Format(codec.Arg.Raw, frequency, bit, channel))} {codec.Arg.Input} {codec.Arg.Bitrate} {track.BitRate} {track.Args} {codec.Arg.Output} audio{counter++:0000}_{track.Lang}.{codec.App.Ext}"); break; } } } } } }
public static void Mux(string fileout, Queue item) { if (item.Data.SaveAsMkv) { fileout += ".mkv"; string tags = string.Format(Properties.Resources.Tags, Global.App.NameFull, "Nemu System 5.1.1"); string cmdvideo = null; string cmdaudio = null; string cmdsubs = null; string cmdattach = null; string cmdchapter = null; foreach (var tc in Directory.GetFiles(Default.DirTemp, "timecode_*")) { cmdvideo += $"--timecodes 0:\"{tc}\" "; break; } foreach (var video in Directory.GetFiles(Default.DirTemp, "video*")) { cmdvideo += $"--language 0:{GetInfo.FileLang(video)} \"{video}\" "; } foreach (var audio in Directory.GetFiles(Default.DirTemp, "audio*")) { cmdaudio += $"--language 0:{GetInfo.FileLang(audio)} \"{audio}\" "; } if (item.SubtitleEnable) { foreach (var subs in item.Subtitle) { cmdsubs += $"--compression 0:zlib --sub-charset 0:UTF-8 --language 0:{subs.Lang} \"{subs.File}\" "; } } else { foreach (var subs in Directory.GetFiles(Default.DirTemp, "sub*")) { cmdsubs += $"--compression 0:zlib --sub-charset 0:UTF-8 --language 0:{GetInfo.FileLang(subs)} \"{subs}\" "; } } if (item.AttachEnable) { foreach (var attach in item.Attach) { cmdattach += $"--attachment-mime-type {attach.MIME} --attachment-description {attach.Comment} --attach-file \"{attach.File}\" "; } } else { foreach (var attach in Directory.GetFiles(Default.DirTemp, "font*.*f")) { cmdattach += $"--attachment-description No --attach-file \"{attach}\" "; } } if (File.Exists(Path.Combine(Default.DirTemp, "chapters.xml"))) { FileInfo ChapLen = new FileInfo(Path.Combine(Default.DirTemp, "chapters.xml")); if (ChapLen.Length > 256) cmdchapter = $"--chapters \"{Path.Combine(Default.DirTemp, "chapters.xml")}\""; } File.WriteAllText(Path.Combine(Default.DirTemp, "tags.xml"), tags); TaskManager.Run($"\"{Plugin.MKVME}\" -o \"{fileout}\" -t 0:tags.xml --disable-track-statistics-tags {cmdvideo} {cmdaudio} {cmdsubs} {cmdattach} {cmdchapter}"); } else { fileout += ".mp4"; string timecode = null; string cmdvideo = null; string cmdaudio = null; foreach (var tc in Directory.GetFiles(Default.DirTemp, "timecode_*")) { timecode = tc; break; } foreach (var video in Directory.GetFiles(Default.DirTemp, "video*")) { cmdvideo += $"-add \"{video}#video:name=IFME:lang={GetInfo.FileLang(video)}:fmt=HEVC\" "; } foreach (var audio in Directory.GetFiles(Default.DirTemp, "audio*")) { cmdaudio += $"-add \"{audio}#audio:name=IFME:lang={GetInfo.FileLang(audio)}\" "; } if (string.IsNullOrEmpty(timecode)) { TaskManager.Run($"\"{Plugin.MP4BX}\" {cmdvideo} {cmdaudio} -itags tool=\"{Global.App.NameFull}\" -new \"{fileout}\""); } else { TaskManager.Run($"\"{Plugin.MP4BX}\" {cmdvideo} {cmdaudio} -itags tool=\"{Global.App.NameFull}\" -new _desu.mp4"); TaskManager.Run($"\"{Plugin.MP4FP}\" -t \"{timecode}\" _desu.mp4 -o \"{fileout}\""); } } }
void QueueAdd(string file) { if (GetInfo.IsPathNetwork(file)) { InvokeLog($"Rejected! Please mount as \"Network Drive\" like \"Z:\\\""); return; } string FileType = string.Empty; string FileOut = string.Empty; var Info = new Queue(); var i = cboProfile.SelectedIndex; // Profiles var p = Profile.List[i == 0 ? 0 : i - 1]; // When profiles at <new> mean auto detect Info.Data.File = file; Info.Data.SaveAsMkv = i == 0 ? true : string.Equals(p.Info.Format, "mkv", IC); // todo MediaFile AVI = new MediaFile(file); Info.Data.IsFileMkv = string.Equals(AVI.format, "Matroska", IC); Info.Data.IsFileAvs = GetStream.IsAviSynth(file); // Check if user want to force AviSynth script added to queue if (!Plugin.IsExistAviSynth) { if (Info.Data.IsFileAvs) { if (Plugin.IsForceAviSynth) { InvokeLog($"Forcing AviSynth added to queue: {file}"); } else { InvokeLog($"AviSynth not installed, skipping this file: {file}"); return; } } } // Picture section if (AVI.Video.Count > 0) { var Video = AVI.Video[0]; Info.Picture.Resolution = i == 0 ? "auto" : p.Picture.Resolution; Info.Picture.FrameRate = i == 0 ? "auto" : p.Picture.FrameRate; Info.Picture.BitDepth = i == 0 ? Video.bitDepth : p.Picture.BitDepth; Info.Picture.Chroma = i == 0 ? 420 : p.Picture.Chroma; Info.Prop.Duration = Video.duration; Info.Prop.FrameCount = Video.frameCount; Info.Picture.IsCopy = false; Info.Picture.IsHevc = string.Equals(Video.format, "HEVC", IC); FileType = $"{Path.GetExtension(file).ToUpper()} ({Video.format})"; FileOut = $".{(Info.Data.SaveAsMkv ? "MKV" : "MP4")} (HEVC)"; if (string.Equals(Video.frameRateMode, "vfr", IC)) Info.Prop.IsVFR = true; if (Video.isInterlace) { Info.Picture.YadifEnable = true; Info.Picture.YadifMode = 0; Info.Picture.YadifField = (Video.isTopFieldFirst ? 0 : 1); Info.Picture.YadifFlag = 0; } } else if (Info.Data.IsFileAvs) { Info.Picture.Resolution = "auto"; Info.Picture.FrameRate = "auto"; Info.Picture.BitDepth = 8; Info.Picture.Chroma = 420; FileType = "AviSynth Script"; FileOut = $".{(Info.Data.SaveAsMkv ? "MKV" : "MP4")} (HEVC)"; } else { Info.Picture.Resolution = "auto"; Info.Picture.FrameRate = "auto"; Info.Picture.BitDepth = 8; Info.Picture.Chroma = 420; Info.Picture.IsCopy = true; var Audio = AVI.Audio[0]; FileType = $"{Path.GetExtension(file).ToUpper()} ({Audio.format})"; FileOut = $".{(Info.Data.SaveAsMkv ? "MKV" : "MP4")}"; } // Video section Info.Video.Preset = i == 0 ? "medium" : p.Video.Preset; Info.Video.Tune = i == 0 ? "off" : p.Video.Tune; Info.Video.Type = i == 0 ? 0 : p.Video.Type; Info.Video.Value = i == 0 ? "26" : p.Video.Value; Info.Video.Command = i == 0 ? "--dither" : p.Video.Command; // Audio section Plugin dummy; bool exist = Plugin.List.TryGetValue(p.Audio.Encoder, out dummy); Guid encoder = i == 0 || !exist ? new Guid("ffffffff-ffff-ffff-ffff-ffffffffffff") : p.Audio.Encoder; string bitRate = i == 0 || !exist ? "256" : p.Audio.BitRate; string frequency = i == 0 || !exist ? "auto" : p.Audio.Freq; string channel = i == 0 || !exist ? "auto" : p.Audio.Chan; string command = i == 0 || !exist ? null : p.Audio.Args; foreach (var item in GetStream.Audio(file)) Info.Audio.Add(new Queue.audio { Enable = true, File = file, Embedded = true, Id = item.Basic.Id, Lang = item.Basic.Lang, Codec = item.Basic.Codec, Format = item.Basic.Format, RawBit = item.RawBit, RawFreq = item.RawFreq, RawChan = item.RawChan, Encoder = encoder, BitRate = bitRate, Freq = frequency, Chan = channel, Args = command }); // Add to queue list ListViewItem qItem = new ListViewItem(new[] { GetInfo.FileName(file), GetInfo.FileSize(file), FileType, FileOut, "Ready" }); qItem.Tag = Info; qItem.Checked = true; lstQueue.Items.Add(qItem); // Print to log InvokeLog($"File added {Info.Data.File}"); }
public static void Audio(Queue item) { string ffile = string.Empty; string ffmap = string.Empty; string ffcmd = item.Picture.Command; int counter = 0; foreach (var track in item.Audio) { string file = track.File; if (string.IsNullOrEmpty(file)) continue; string freq = string.Equals(track.Freq, "auto", IC) ? $"{track.RawFreq}" : $"{track.Freq}"; string bit = $"{track.RawBit}"; string chan = string.Equals(track.Chan, "auto", IC) ? $"{track.RawChan}" : string.Equals(track.Chan, "stereo", IC) ? "2" : "1"; if (item.AudioMerge) { counter++; ffile += $"-i \"{file}\""; ffmap += $"-map {track.Id} "; if (item.Audio.Count == counter) { Plugin codec; if (Plugin.List.TryGetValue(item.Audio[0].Encoder, out codec)) { TaskManager.Run($"\"{Plugin.FFMPEG}\" {ffile} {ffmap} -filter_complex amix=inputs={counter}:duration=first:dropout_transition=0 -acodec pcm_s{bit}le -ar {freq} -ac {chan} -f wav {ffcmd} - | \"{codec.App.Bin}\" {(string.IsNullOrEmpty(codec.Arg.Raw) ? string.Empty : string.Format(codec.Arg.Raw, freq, bit, chan))} {codec.Arg.Input} {codec.Arg.Bitrate} {track.BitRate} {track.Args} {codec.Arg.Output} audio0000_und.{codec.App.Ext}"); } } } else { if (!track.Enable) continue; if (Equals(new Guid("00000000-0000-0000-0000-000000000000"), track.Encoder)) { continue; } Plugin codec; if (Plugin.List.TryGetValue(track.Encoder, out codec) && !Equals(new Guid("ffffffff-ffff-ffff-ffff-ffffffffffff"), track.Encoder)) { if (Convert.ToInt32(bit) >= 32) bit = "24"; // force to 24bit max string rawArgs = string.Empty; try { if (!string.IsNullOrEmpty(codec.Arg.Raw)) rawArgs = string.Format(codec.Arg.Raw, freq, bit, chan); } catch (Exception e) { Console.ForegroundColor = ConsoleColor.Red; Console.Error.WriteLine($"Raw arguments incomplete, ignored!\n{e}"); Console.ResetColor(); } string encArgs = $"\"{codec.App.Bin}\" {rawArgs} {codec.Arg.Input} {codec.Arg.Bitrate} {track.BitRate} {track.Args} {codec.Arg.Output} audio{counter++:0000}_{track.Lang}.{codec.App.Ext}"; if (item.Data.IsFileAvs) { TaskManager.Run($"\"{Plugin.AVSPIPE}\" audio \"{file}\" | \"{Plugin.FFMPEG}\" -loglevel panic -i - -acodec pcm_s{bit}le -f wav - | {encArgs}"); // double pipe due some encoder didn't read avs2pipe properly, example: opusenc.exe } else { TaskManager.Run($"\"{Plugin.FFMPEG}\" -loglevel panic -i \"{file}\" -map {track.Id} -acodec pcm_s{bit}le -ar {freq} -ac {chan} -f wav {ffcmd} - | {encArgs}"); } } else { if (item.Data.IsFileAvs) { TaskManager.Run($"{Plugin.AVSPIPE} audio \"{file}\" | {Plugin.FFMPEG} -i - -dn -vn -sn -strict -2 -c:a aac -b:a {track.BitRate}k -ar {freq} -ac {chan} -y audio{counter++:0000}_{track.Lang}.mp4"); } else if (item.Data.SaveAsMkv) { if (string.Equals("wma", track.Format, IC)) { TaskManager.Run($"\"{Plugin.FFMPEG}\" -i \"{file}\" -map {track.Id} -dn -vn -sn -strict -2 -c:a aac -b:a {track.BitRate}k -ar {freq} -ac {chan} -y audio{counter++:0000}_{track.Lang}.mp4"); } else { TaskManager.Run($"\"{Plugin.FFMPEG}\" -i \"{file}\" -map {track.Id} -dn -vn -sn -acodec copy {ffcmd} -y audio{counter++:0000}_{track.Lang}.{track.Format}"); } } else { if (string.Equals("mp4", track.Format, IC)) { TaskManager.Run($"\"{Plugin.FFMPEG}\" -i \"{file}\" -map {track.Id} -dn -vn -sn -acodec copy {ffcmd} -y audio{counter++:0000}_{track.Lang}.{track.Format}"); } else { TaskManager.Run($"\"{Plugin.FFMPEG}\" -i \"{file}\" -map {track.Id} -dn -vn -sn -strict -2 -c:a aac -b:a {track.BitRate}k -ar {freq} -ac {chan} -y audio{counter++:0000}_{track.Lang}.mp4"); } } } } } }
public static void Video(Queue item) { string file = item.FilePath; foreach (var video in GetStream.Video(file)) { // FFmpeg args string resolution = string.Equals(item.Picture.Resolution, "auto", IC) ? string.Empty : $"-s {item.Picture.Resolution}"; string framerate = string.Equals(item.Picture.FrameRate, "auto", IC) ? string.Empty : $"-r {item.Picture.FrameRate}"; int bitdepth = item.Picture.BitDepth; string chroma = $"yuv{item.Picture.Chroma}p{(bitdepth > 8 ? $"{bitdepth}le" : "")}"; string yadif = item.Picture.YadifEnable ? $"-vf \"yadif={item.Picture.YadifMode}:{item.Picture.YadifField}:{item.Picture.YadifFlag}\"" : ""; int framecount = item.Picture.FrameCount; string ffcmd = item.Picture.Command; // Indexing if (!item.General.IsAviSynth) { if (framecount <= 0) { if (Default.UseFrameAccurate) { Console.WriteLine("Indexing... This may take very long time."); new FFmpeg().FrameCountAccurate(file); } else { Console.WriteLine("Indexing... Please Wait."); new FFmpeg().FrameCount(file); } } Console.WriteLine("Indexing... Make sure in sync :)"); TaskManager.Run($"\"{Plugin.FFMS2}\" -f -c \"{file}\" timecode"); } if (!string.IsNullOrEmpty(framerate)) framecount = (int)Math.Ceiling((item.General.Duration * Convert.ToDouble(item.Picture.FrameRate, CultureInfo.InvariantCulture))); if (item.Picture.YadifEnable) if (item.Picture.YadifMode == 1) framecount *= 2; // make each fields as new frame // x265 settings string decbin = Plugin.FFMPEG; string encbin = Plugin.HEVC08; string preset = item.Video.Preset; string tune = string.Equals(item.Video.Tune, "off", IC) ? "" : $"--tune {item.Video.Tune}"; int type = item.Video.Type; int pass; string value = item.Video.Value; string command = item.Video.Command; if (bitdepth == 10) encbin = Plugin.HEVC10; else if (bitdepth == 12) encbin = Plugin.HEVC12; string decoder = $"\"{decbin}\" -loglevel panic -i \"{file}\" -f yuv4mpegpipe -pix_fmt {chroma} -strict -1 {resolution} {framerate} {yadif} {ffcmd} -"; string encoder = $"\"{encbin}\" --y4m - -p {preset} {(type == 0 ? "--crf" : type == 1 ? "--qp" : "--bitrate")} {value} {command} -o video0000_{video.Lang}.hevc"; // Encoding start if (type >= 3) // multi pass { type--; // re-use for (int i = 0; i < type; i++) { if (i == 0) pass = 1; else if (i == type) pass = 2; else pass = 3; if (i == 1) // get actual frame count { Console.WriteLine("Re-indexing encoded file, make sure no damage."); framecount = new FFmpeg().FrameCount(Path.Combine(Default.DirTemp, $"video0000_{video.Lang}.hevc")); } Console.WriteLine($"Pass {i + 1} of {type}"); // human read no index TaskManager.Run($"{decoder} | {encoder} -f {framecount} --pass {pass}"); } } else { TaskManager.Run($"{decoder} | {encoder} -f {framecount}"); } break; } }
public static void Mux(Queue item) { // Final output, a file name without extension string savedir = Default.IsDirOutput ? Default.DirOutput : Path.GetDirectoryName(item.FilePath); string prefix = string.IsNullOrEmpty(Default.NamePrefix) ? string.Empty : Default.NamePrefix + " "; string newfile = Path.GetFileNameWithoutExtension(item.FilePath); string fileout = Path.Combine(savedir, $"{prefix}{newfile}"); // Destinantion folder check if (!Directory.Exists(Default.DirOutput)) Directory.CreateDirectory(Default.DirOutput); // File exist check if (File.Exists($"{fileout}.mp4") || File.Exists($"{fileout}.mkv")) fileout += $"_encoded-{DateTime.Now:yyyyMMdd_HHmmss}"; if (item.General.IsOutputMKV) { fileout += ".mkv"; string tags = string.Format(Properties.Resources.Tags, Global.App.NameFull, Global.App.VersionCompiled); string cmdvideo = string.Empty; string cmdaudio = string.Empty; string cmdsubs = string.Empty; string cmdattach = string.Empty; string cmdchapter = string.Empty; foreach (var tc in Directory.GetFiles(Default.DirTemp, "timecode_*")) { cmdvideo += $"--timecodes 0:\"{tc}\" "; break; } foreach (var video in Directory.GetFiles(Default.DirTemp, "video*")) { cmdvideo += $"--language 0:{Get.FileLang(video)} \"{video}\" "; } foreach (var audio in Directory.GetFiles(Default.DirTemp, "audio*")) { cmdaudio += $"--language 0:{Get.FileLang(audio)} \"{audio}\" "; } foreach (var subs in Directory.GetFiles(Default.DirTemp, "subtitle*")) { cmdsubs += $"--sub-charset 0:UTF-8 --language 0:{Get.FileLang(subs)} \"{subs}\" "; } foreach (var attach in Directory.GetFiles(Default.DirTemp, "*.*") .Where( s => s.EndsWith(".ttf", IC) || s.EndsWith(".otf", IC) || s.EndsWith(".ttc", IC) || s.EndsWith(".woff", IC))) { cmdattach += $"--attach-file \"{attach}\" "; } if (File.Exists(Path.Combine(Default.DirTemp, "chapters.xml"))) { FileInfo ChapLen = new FileInfo(Path.Combine(Default.DirTemp, "chapters.xml")); if (ChapLen.Length > 256) cmdchapter = $"--chapters \"{Path.Combine(Default.DirTemp, "chapters.xml")}\""; } File.WriteAllText(Path.Combine(Default.DirTemp, "tags.xml"), tags); TaskManager.Run($"\"{Plugin.MKVMER}\" -o \"{fileout}\" --disable-track-statistics-tags -t 0:tags.xml {cmdvideo} {cmdaudio} {cmdsubs} {cmdattach} {cmdchapter}"); } else { fileout += ".mp4"; string timecode = string.Empty; string cmdvideo = string.Empty; string cmdaudio = string.Empty; foreach (var tc in Directory.GetFiles(Default.DirTemp, "timecode_*")) { timecode = tc; break; } int cntv = 0; foreach (var video in Directory.GetFiles(Default.DirTemp, "video*")) { cmdvideo += $"-add \"{video}#video:name=Video {++cntv}:lang={Get.FileLang(video)}:fmt=HEVC\" "; } int cnta = 0; foreach (var audio in Directory.GetFiles(Default.DirTemp, "audio*")) { cmdaudio += $"-add \"{audio}#audio:name=Audio {++cnta}:lang={Get.FileLang(audio)}\" "; } if (string.IsNullOrEmpty(timecode)) { TaskManager.Run($"\"{Plugin.MP4BOX}\" {cmdvideo} {cmdaudio} -itags tool=\"{Global.App.NameFull}\" -new \"{fileout}\""); } else { TaskManager.Run($"\"{Plugin.MP4BOX}\" {cmdvideo} {cmdaudio} -itags tool=\"{Global.App.NameFull}\" -new _desu.mp4"); TaskManager.Run($"\"{Plugin.MP4FPS}\" -t \"{timecode}\" _desu.mp4 -o \"{fileout}\""); } } }
public static void Extract(Queue item) { if (string.IsNullOrEmpty(item.FilePath)) return; int count = 0; if (item.General.IsAviSynth) { if (Default.AvsMkvCopy) { var file = GetStream.AviSynthGetFile(item.FilePath); var ff = new FFmpeg.Stream(file); foreach (var subs in ff.Subtitle) TaskManager.Run($"\"{Plugin.FFMPEG}\" -i \"{file}\" -map 0:{subs.Id} -y subtitle{count++:D4}_{subs.Language}.{Get.MediaContainer(subs.Codec)}"); TaskManager.Run($"\"{Plugin.FFMPEG}\" -dump_attachment:t \"\" -i \"{file}\" -y"); TaskManager.Run($"\"{Plugin.MKVEXT}\" chapters \"{file}\" > chapters.xml"); } if (item.SubtitleEnable) { foreach (var subs in item.Subtitle) { if (File.Exists(subs.File)) { if (subs.Id < 0) { File.Copy(subs.File, Path.Combine(Default.DirTemp, $"subtitle{count++:D4}_{subs.Lang}.{subs.Format}"), true); } } } } if (item.AttachEnable) { foreach (var font in item.Attach) { if (File.Exists(font.File)) { File.Copy(font.File, Path.Combine(Default.DirTemp, Get.FileName(font.File)), true); } } } } else { if (item.SubtitleEnable) { foreach (var subs in item.Subtitle) { if (File.Exists(subs.File)) { if (subs.Id > -1) { TaskManager.Run($"\"{Plugin.FFMPEG}\" -i \"{subs.File}\" -map 0:{subs.Id} -y subtitle{count++:D4}_{subs.Lang}.{subs.Format}"); } else { File.Copy(subs.File, Path.Combine(Default.DirTemp, $"subtitle{count++:D4}_{subs.Lang}.{subs.Format}"), true); } } } } if (item.AttachEnable) { foreach (var font in item.Attach) { if (File.Exists(font.File)) { File.Copy(font.File, Path.Combine(Default.DirTemp, Get.FileName(font.File)), true); } } } else { TaskManager.Run($"\"{Plugin.FFMPEG}\" -dump_attachment:t \"\" -i \"{item.FilePath}\" -y"); } TaskManager.Run($"\"{Plugin.MKVEXT}\" chapters \"{item.FilePath}\" > chapters.xml"); } }