public async Task DoJob(Job job, Action <IParallelProgress> progressUpdate, CancellationToken cancellation) { tasksLimit = new SemaphoreSlim(2); var groups = job.FileGroups.ToList(); var error = groups.Join(job.Files, g => g.FilePath, f => f.FilePath, (g, f) => g.FilePath).ToList(); if (error.Any()) { throw new ArgumentException("Some output file names are the same as one of inputs:\r\n" + string.Join("\r\n", error.Select(s => " " + s))); } var tasks = new List <Task>(); var progress = new ParallelProgressContainer(progressUpdate); foreach (var step in groups) { Task task; var subprogress = new ParallelProgressContainer(); progress.Add(subprogress); task = ConcatMultipleFiles(step, subprogress, cancellation); tasks.Add(task); } await Task.WhenAll(tasks.ToArray()); }
private async Task ConcatMultipleFiles(FilesGroup step, ParallelProgressContainer progress, CancellationToken cancellation) { var outputFormat = step.OutputEncoding ?? "-c copy"; var concatFile = await CreateConcatFile(step.Files); try { var subProgress = new ParallelProgressChild(); progress.Add(subProgress); try { await tasksLimit.WaitAsync(cancellation); string arguments = $"-f concat -safe 0 -i \"{concatFile}\" {outputFormat} -y \"{step.FilePath}\""; using (var proc = StartProcess( FFMpegPath, str => UpdateProgress(str, subProgress), cancellation, arguments)) { await proc; } } finally { tasksLimit.Release(); } } finally { File.Delete(concatFile); } }
private async Task ConcatFilesComplex(FilesGroup step, ParallelProgressContainer progress, List <string> concatFiles, CancellationToken cancellation) { var subProgress = new ParallelProgressChild(); progress.Add(subProgress); try { await tasksLimit.WaitAsync(cancellation); var inputFiles = string.Join(" ", concatFiles.Select(f => $"-i \"{f}\"")); var filterParts = string.Join(string.Empty, concatFiles.Select((s, i) => step.ComplexFilter.Replace("%i", i.ToString()))); var streamParts = string.Join(string.Empty, concatFiles.Select((s, i) => $"[v{i}][{i}:a]")); var filter = $"-filter_complex \"{filterParts} {streamParts}concat=n={concatFiles.Count}:v=1:a=1[v][a]\" -map \"[v]\" -map \"[a]\""; var argument = $"{inputFiles} {filter} {step.OutputEncoding} -y \"{step.FilePath}\""; using (var proc = StartProcess( FFMpegPath, str => UpdateProgress(str, subProgress, 0.5), cancellation, argument)) { await proc; } } finally { tasksLimit.Release(); } }
private async Task ConcatFilesSimple(FilesGroup step, ParallelProgressContainer progress, List <string> concatFiles, string outputFormat, CancellationToken cancellation) { var concatFile = await CreateConcatFile(concatFiles); try { var subProgress = new ParallelProgressChild(); progress.Add(subProgress); try { await tasksLimit.WaitAsync(cancellation); using (var proc = StartProcess( FFMpegPath, str => UpdateProgress(str, subProgress, 0.5), cancellation, $"-f concat -safe 0 -i \"{concatFile}\" {outputFormat} -y \"{step.FilePath}\"")) { await proc; } } finally { tasksLimit.Release(); } } finally { File.Delete(concatFile); } }
private async Task ConcatMultipleFiles(FilesGroup step, ParallelProgressContainer progress, CancellationToken cancellation) { var outputFormat = step.OutputEncoding ?? "-c copy"; var concatFiles = new List <string>(); var tasks = new List <Task>(); var filesToDelete = new List <string>(); var doneLock = new object(); try { foreach (var file in step.Files) { cancellation.ThrowIfCancellationRequested(); if (Math.Abs(file.CutDuration - file.Duration) < 0.001) { concatFiles.Add(file.FilePath); } else { var newfile = Path.GetTempFileName() + Path.GetExtension(step.FilePath); var tempargs = $"-i \"{file.FilePath}\" -ss {file.Start} -t {file.CutDuration} -c copy -y \"{newfile}\""; Debug.WriteLine(tempargs); var cutprogress = new ParallelProgressChild(); progress.Add(cutprogress); await tasksLimit.WaitAsync(cancellation); var tempproc = StartProcess(FFMpegPath, str => UpdateProgress(str, cutprogress, 0.5), cancellation, tempargs); var fileCutDuration = file.CutDuration; var task = tempproc.ContinueWith( t => { t.Result.Dispose(); tasksLimit.Release(); }, cancellation); filesToDelete.Add(newfile); concatFiles.Add(newfile); tasks.Add(task); } } await Task.WhenAll(tasks.ToArray()); if (string.IsNullOrWhiteSpace(step.ComplexFilter)) { await ConcatFilesSimple(step, progress, concatFiles, outputFormat, cancellation); } else { await ConcatFilesComplex(step, progress, concatFiles, cancellation); } } finally { foreach (var file in filesToDelete) { File.Delete(file); } } }