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);
            }
        }
Example #3
0
        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();
            }
        }
Example #4
0
        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);
            }
        }
Example #5
0
        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);
                }
            }
        }