예제 #1
0
        /// <summary>
        /// Returns the version information from FFmpeg.
        /// </summary>
        /// <param name="options">The options for starting the process.</param>
        /// <param name="callback">A method that will be called after the process has been started.</param>
        /// <returns>A IFFmpegProcess object containing the version information.</returns>
        public string GetVersion(ProcessOptionsEncoder options = null, ProcessStartedEventHandler callback = null)
        {
            IProcessWorkerEncoder Worker = factory.CreateEncoder(options, callback);

            Worker.OutputType = ProcessOutput.Output;
            Worker.RunEncoder("-version", EncoderApp.FFmpeg);
            return(Worker.Output);
        }
        /// <summary>
        /// Creates a new process worker to run an encoder with specified options.
        /// </summary>
        /// <param name="options">The options for starting the process.</param>
        /// <param name="callback">A method that will be called after the process has been started.</param>
        /// <returns>The newly created encoder process manager.</returns>
        public virtual IProcessWorkerEncoder CreateEncoder(ProcessOptionsEncoder options = null, ProcessStartedEventHandler callback = null)
        {
            var Result = new ProcessWorkerEncoder(Config, ProcessFactory, FileSystemService, ParserFactory, options);

            if (callback != null)
            {
                Result.ProcessStarted += callback;
            }
            return(Result);
        }
 /// <summary>
 /// Parses the output of X264 or X265 to return the info of all input streams.
 /// </summary>
 /// <param name="outputText">The text containing the file information to parse.</param>
 public void ParseFileInfo(string outputText, ProcessOptionsEncoder options)
 {
     IsParsed = true;
     if (options?.FrameCount > 0)
     {
         FrameCount = options.FrameCount;
     }
     else
     {
         FrameCount = ParseFrameCount(outputText);
     }
 }
예제 #4
0
        /// <summary>
        /// Returns the exact frame count of specified video file.
        /// </summary>
        /// <param name="source">The file to get information about.</param>
        /// <param name="options">The options for starting the process.</param>
        /// <param name="callback">A method that will be called after the process has been started.</param>
        /// <returns>The number of frames in the video.</returns>
        public long GetFrameCount(string source, ProcessOptionsEncoder options = null, ProcessStartedEventHandler callback = null)
        {
            if (string.IsNullOrEmpty(source))
            {
                throw new ArgumentException("Source cannot be null or empty.", nameof(source));
            }
            long Result = 0;
            IProcessWorkerEncoder Worker = factory.CreateEncoder(options, callback);

            Worker.ProgressReceived += (sender, e) => {
                // Read all status lines and keep the last one.
                Result = (e.Progress as ProgressStatusFFmpeg).Frame;
            };
            Worker.RunEncoder($@"-i ""{source}"" -f null /dev/null", EncoderApp.FFmpeg);
            return(Result);
        }
예제 #5
0
        /// <summary>
        /// Runs vspipe with specified source file. The output will be discarded.
        /// </summary>
        /// <param name="path">The path to the script to run.</param>
        /// <param name="options">The options for starting the process.</param>
        /// <param name="callback">A method that will be called after the process has been started.</param>
        /// <returns>The process completion status.</returns>
        public CompletionStatus RunVapourSynth(string path, ProcessOptionsEncoder options = null, ProcessStartedEventHandler callback = null)
        {
            if (string.IsNullOrEmpty(path))
            {
                throw new ArgumentException("Path cannot be null or empty.", nameof(path));
            }
            if (!fileSystem.Exists(factory.Config.VsPipePath))
            {
                throw new System.IO.FileNotFoundException($@"File ""{factory.Config.VsPipePath}"" specified by Config.VsPipePath is not found.");
            }
            string           Args    = $@"""{path}"" .";
            IProcessWorker   Manager = factory.Create(options, callback);
            CompletionStatus Result  = Manager.Run(factory.Config.VsPipePath, Args);

            return(Result);
        }
예제 #6
0
        /// <summary>
        /// Gets file streams information of specified file via FFmpeg.
        /// </summary>
        /// <param name="source">The file to get information about.</param>
        /// <param name="options">The options for starting the process.</param>
        /// <param name="callback">A method that will be called after the process has been started.</param>
        /// <returns>A IFFmpegProcess object containing the file information.</returns>
        public IFileInfoFFmpeg GetFileInfo(string source, ProcessOptionsEncoder options = null, ProcessStartedEventHandler callback = null)
        {
            if (string.IsNullOrEmpty(source))
            {
                throw new ArgumentException("Source cannot be null or empty.", nameof(source));
            }
            IProcessWorkerEncoder Worker = factory.CreateEncoder(options, callback);

            Worker.ProcessCompleted += (s, e) => {
                if (e.Status == CompletionStatus.Failed && (Worker.FileInfo as IFileInfoFFmpeg)?.FileStreams != null)
                {
                    e.Status = CompletionStatus.Success;
                }
            };
            Worker.RunEncoder($@"-i ""{source}""", EncoderApp.FFmpeg);
            return(Worker.FileInfo as IFileInfoFFmpeg);
        }
예제 #7
0
        /// <summary>
        /// Runs avs2pipemod with specified source file. The output will be discarded.
        /// </summary>
        /// <param name="path">The path to the script to run.</param>
        /// <param name="options">The options for starting the process.</param>
        /// <param name="callback">A method that will be called after the process has been started.</param>
        /// <returns>The process completion status.</returns>
        public CompletionStatus RunAvisynth(string path, ProcessOptionsEncoder options = null, ProcessStartedEventHandler callback = null)
        {
            if (string.IsNullOrEmpty(path))
            {
                throw new ArgumentException("Path cannot be null or empty.", nameof(path));
            }
            if (!fileSystem.Exists(factory.Config.Avs2PipeMod))
            {
                throw new System.IO.FileNotFoundException($@"File ""{factory.Config.Avs2PipeMod}"" specified by Config.Avs2PipeModPath is not found.");
            }
            string         Args    = $@"""{path}"" -rawvideo > NUL";
            IProcessWorker Manager = factory.Create(options, callback);

            Manager.OutputType = ProcessOutput.Error;
            string           Cmd    = $@"""{factory.Config.Avs2PipeMod}"" {Args}";
            CompletionStatus Result = Manager.RunAsCommand(Cmd);

            return(Result);
        }
        /// <summary>
        /// Returns stream information as FFmpegStream about specified media file that can be used to call a muxing operation.
        /// </summary>
        /// <param name="path">The path of the media file to query.</param>
        /// <param name="streamType">The type of media stream to query.</param>
        /// <param name="options">The options for starting the process.</param>
        /// <returns>A FFmpegStream object.</returns>
        private MediaStream GetStreamInfo(string path, FFmpegStreamType streamType, ProcessOptionsEncoder options)
        {
            IFileInfoFFmpeg FileInfo   = infoReader.GetFileInfo(path, options);
            MediaStreamInfo StreamInfo = FileInfo.FileStreams?.FirstOrDefault(x => x.StreamType == streamType);

            if (StreamInfo != null)
            {
                return(new MediaStream()
                {
                    Path = path,
                    Index = StreamInfo.Index,
                    Format = StreamInfo.Format,
                    Type = streamType
                });
            }
            else
            {
                return(null);
            }
        }
예제 #9
0
 /// <summary>
 /// Converts specified file into AVI UT Video format.
 /// </summary>
 /// <param name="source">The file to convert.</param>
 /// <param name="destination">The destination file, ending with .AVI</param>
 /// <param name="audio">Whether to encode audio.</param>
 /// <param name="options">The options for starting the process.</param>
 /// <param name="callback">A method that will be called after the process has been started.</param>
 /// <returns>The process completion status.</returns>
 public CompletionStatus ConvertToAviUtVideo(string source, string destination, bool audio, ProcessOptionsEncoder options = null, ProcessStartedEventHandler callback = null)
 {
     // -vcodec huffyuv or utvideo, -acodec pcm_s16le
     return(EncodeFFmpeg(source, destination, "utvideo", audio ? "pcm_s16le" : null, null, options, callback));
 }
예제 #10
0
        /// <summary>
        /// Merges specified audio and video files.
        /// </summary>
        /// <param name="videoFile">The file containing the video.</param>
        /// <param name="audioFile">The file containing the audio.</param>
        /// <param name="destination">The destination file.</param>
        /// <param name="options">The options for starting the process.</param>
        /// <param name="callback">A method that will be called after the process has been started.</param>
        /// <returns>The process completion status.</returns>
        public CompletionStatus Muxe(string videoFile, string audioFile, string destination, ProcessOptionsEncoder options = null, ProcessStartedEventHandler callback = null)
        {
            if (string.IsNullOrEmpty(videoFile) && string.IsNullOrEmpty(audioFile))
            {
                throw new ArgumentException("You must specifiy either videoFile or audioFile.", nameof(videoFile));
            }
            if (string.IsNullOrEmpty(destination))
            {
                throw new ArgumentException("Destination cannot be null or empty.", nameof(destination));
            }

            List <MediaStream> InputStreamList = new List <MediaStream>();
            MediaStream        InputStream;

            if (!string.IsNullOrEmpty(videoFile))
            {
                InputStream = GetStreamInfo(videoFile, FFmpegStreamType.Video, options);
                if (InputStream != null)
                {
                    InputStreamList.Add(InputStream);
                }
            }
            if (!string.IsNullOrEmpty(audioFile))
            {
                InputStream = GetStreamInfo(audioFile, FFmpegStreamType.Audio, options);
                if (InputStream != null)
                {
                    InputStreamList.Add(InputStream);
                }
            }

            if (InputStreamList.Any())
            {
                return(Muxe(InputStreamList, destination, options, callback));
            }
            else
            {
                return(CompletionStatus.Failed);
            }
        }
예제 #11
0
        /// <summary>
        /// Merges the specified list of file streams.
        /// </summary>
        /// <param name="fileStreams">The list of file streams to include in the output.</param>
        /// <param name="destination">The destination file.</param>
        /// <param name="options">The options for starting the process.</param>
        /// <param name="callback">A method that will be called after the process has been started.</param>
        /// <returns>The process completion status.</returns>
        public CompletionStatus Muxe(IEnumerable <MediaStream> fileStreams, string destination, ProcessOptionsEncoder options = null, ProcessStartedEventHandler callback = null)
        {
            if (fileStreams == null || !fileStreams.Any())
            {
                throw new ArgumentException("FileStreams cannot be null or empty.", nameof(fileStreams));
            }
            if (string.IsNullOrEmpty(destination))
            {
                throw new ArgumentException("Destination cannot be null or empty.", nameof(destination));
            }

            CompletionStatus Result    = CompletionStatus.Success;
            List <string>    TempFiles = new List <string>();

            fileSystem.Delete(destination);

            // FFMPEG fails to muxe H264 into MKV container. Converting to MP4 and then muxing with the audio, however, works.
            foreach (MediaStream item in fileStreams)
            {
                if (string.IsNullOrEmpty(item.Path) && item.Type != FFmpegStreamType.None)
                {
                    throw new ArgumentException("FFmpegStream.Path cannot be null or empty.", nameof(item.Path));
                }
                if (item.Type == FFmpegStreamType.Video && (item.Format == "h264" || item.Format == "h265") && destination.EndsWith(".mkv"))
                {
                    string NewFile = item.Path.Substring(0, item.Path.LastIndexOf('.')) + ".mp4";
                    Result = Muxe(new List <MediaStream>()
                    {
                        item
                    }, NewFile, options);
                    TempFiles.Add(NewFile);
                    if (Result != CompletionStatus.Success)
                    {
                        break;
                    }
                }
            }

            if (Result == CompletionStatus.Success)
            {
                // Join audio and video files.
                StringBuilder Query = new StringBuilder();
                StringBuilder Map   = new StringBuilder();
                Query.Append("-y ");
                int           StreamIndex = 0;
                bool          HasVideo = false, HasAudio = false, HasPcmDvdAudio = false;
                StringBuilder AacFix             = new StringBuilder();
                var           FileStreamsOrdered = fileStreams.OrderBy(f => f.Type);
                foreach (MediaStream item in FileStreamsOrdered)
                {
                    if (item.Type == FFmpegStreamType.Video)
                    {
                        HasVideo = true;
                    }
                    if (item.Type == FFmpegStreamType.Audio)
                    {
                        HasAudio = true;
                        if (item.Format == "aac")
                        {
                            AacFix.AppendFormat("-bsf:{0} aac_adtstoasc ", StreamIndex);
                        }
                        if (item.Format == "pcm_dvd")
                        {
                            HasPcmDvdAudio = true;
                        }
                    }
                    Query.Append("-i \"");
                    Query.Append(item.Path);
                    Query.Append("\" ");
                    Map.Append("-map ");
                    Map.Append(StreamIndex++);
                    Map.Append(":");
                    Map.Append(item.Index);
                    Map.Append(" ");
                }
                if (!HasVideo && !HasAudio)
                {
                    throw new ArgumentException("FileStreams cannot be empty.", nameof(fileStreams));
                }
                if (HasVideo)
                {
                    Query.Append("-vcodec copy ");
                }
                if (HasAudio)
                {
                    Query.Append(HasPcmDvdAudio ? "-acodec pcm_s16le " : "-acodec copy ");
                }
                Query.Append(Map);
                // FFMPEG-encoded AAC streams are invalid and require an extra flag to join.
                if (AacFix.Length > 0 && HasVideo)
                {
                    Query.Append(AacFix);
                }
                Query.Append("\"");
                Query.Append(destination);
                Query.Append("\"");
                IProcessWorkerEncoder Worker = factory.CreateEncoder(options, callback);
                Result = Worker.RunEncoder(Query.ToString(), EncoderApp.FFmpeg);
            }

            // Delete temp file.
            foreach (string item in TempFiles)
            {
                fileSystem.Delete(item);
            }
            return(Result);
        }
        /// <summary>
        /// Parses the output of FFmpeg to return the info of all input streams.
        /// </summary>
        /// <param name="outputText">The text containing the file information to parse.</param>
        public void ParseFileInfo(string outputText, ProcessOptionsEncoder options)
        {
            IsParsed     = true;
            FileDuration = new TimeSpan();
            FileStreams  = new List <MediaStreamInfo>();

            if (string.IsNullOrEmpty(outputText))
            {
                return;
            }
            string[] OutLines = outputText.Split(new string[] { Environment.NewLine }, StringSplitOptions.None);

            // Find duration line.
            int DurationIndex = -1;

            for (int i = 0; i < OutLines.Length; i++)
            {
                if (OutLines[i].StartsWith("  Duration: "))
                {
                    DurationIndex = i;
                    // Parse duration line.
                    string[] DurationInfo   = OutLines[i].Trim().Split(new string[] { ", " }, StringSplitOptions.None);
                    string   DurationString = DurationInfo[0].Split(' ')[1];
                    if (DurationString == "N/A")
                    {
                        FileDuration = new TimeSpan(0);
                    }
                    else
                    {
                        try {
                            FileDuration = TimeSpan.Parse(DurationString, CultureInfo.InvariantCulture);
                        } catch { }
                    }
                    break;
                }
            }

            // Find input streams.
            MediaStreamInfo ItemInfo;

            for (int i = DurationIndex + 1; i < OutLines.Length; i++)
            {
                if (OutLines[i].StartsWith("    Stream #0:"))
                {
                    // Parse input stream.
                    ItemInfo = ParseStreamInfo(OutLines[i]);
                    if (ItemInfo != null)
                    {
                        FileStreams.Add(ItemInfo);
                    }
                }
                else if (OutLines[i].StartsWith("Output "))
                {
                    break;
                }
            }

            // Calculate FrameCount.
            if (options?.FrameCount > 0)
            {
                FrameCount = options.FrameCount;
            }
            else if (VideoStream != null)
            {
                FrameCount = (long)(FileDuration.TotalSeconds * VideoStream.FrameRate);
            }
        }
예제 #13
0
        private CompletionStatus EncodeX264Internal(SourceType sourceType, EncoderApp encoderApp, string source, string destination, string encodeArgs, ProcessOptionsEncoder options, ProcessStartedEventHandler callback)
        {
            if (string.IsNullOrEmpty(source))
            {
                throw new ArgumentException("Source cannot be null or empty.", nameof(source));
            }
            if (string.IsNullOrEmpty(destination))
            {
                throw new ArgumentException("Destination cannot be null or empty.", nameof(destination));
            }
            File.Delete(destination);

            StringBuilder Query = new StringBuilder();

            if (sourceType != SourceType.Direct)
            {
                Query.AppendFormat("--{0}y4m ", encoderApp == EncoderApp.x264 ? "demuxer " : "");
            }
            if (!string.IsNullOrEmpty(encodeArgs))
            {
                Query.Append($"{encodeArgs} ");
            }
            Query.Append($@"-o ""{destination}"" ");
            if (sourceType == SourceType.Direct)
            {
                Query.Append($@"""{source}""");
            }
            else
            {
                Query.Append("-");
            }

            // Run X264 or X265 with query.
            IProcessWorkerEncoder Worker = factory.CreateEncoder(options, callback);
            CompletionStatus      Result = RunEncoderInternal(source, Query.ToString(), Worker, sourceType, encoderApp);

            return(Result);
        }
예제 #14
0
 public ProcessWorkerEncoder(IMediaConfig config, IProcessFactory processFactory, IFileSystemService fileSystemService, IFileInfoParserFactory parserFactory, ProcessOptionsEncoder options = null)
     : base(config, processFactory, fileSystemService, options ?? new ProcessOptionsEncoder())
 {
     this.parserFactory = parserFactory ?? throw new ArgumentNullException(nameof(parserFactory));
     OutputType         = ProcessOutput.Error;
 }
예제 #15
0
 /// <summary>
 /// Encodes a VapourSynth script file using X265 with specified arguments.
 /// </summary>
 /// <param name="source">The file to convert.</param>
 /// <param name="destination">The destination file.</param>
 /// <param name="encodeArgs">Additional arguments to pass to X265.</param>
 /// <param name="options">The options for starting the process.</param>
 /// <param name="callback">A method that will be called after the process has been started.</param>
 /// <returns>The process completion status.</returns>
 public CompletionStatus EncodeVapourSynthToX265(string source, string destination, string encodeArgs, ProcessOptionsEncoder options = null, ProcessStartedEventHandler callback = null)
 {
     return(EncodeX264Internal(SourceType.VapourSynth, EncoderApp.x265, source, destination, encodeArgs, options, callback));
 }
예제 #16
0
        private CompletionStatus EncodeFFmpegInternal(SourceType sourceType, string source, string destination, string videoCodec, string audioCodec, string encodeArgs, ProcessOptionsEncoder options, ProcessStartedEventHandler callback)
        {
            if (string.IsNullOrEmpty(source))
            {
                throw new ArgumentException("Source cannot be null or empty.", nameof(source));
            }
            if (string.IsNullOrEmpty(destination))
            {
                throw new ArgumentException("Destination cannot be null or empty.", nameof(destination));
            }
            if (string.IsNullOrEmpty(videoCodec) && string.IsNullOrEmpty(audioCodec))
            {
                throw new ArgumentException("You must specify at least one video or audio codec.");
            }

            File.Delete(destination);
            StringBuilder Query = new StringBuilder();

            Query.Append("-y -i ");
            if (sourceType == SourceType.Direct)
            {
                Query.Append("\"");
                Query.Append(source);
                Query.Append("\"");
            }
            else
            {
                Query.Append("-"); // Pipe source
            }
            // Add video codec.
            if (string.IsNullOrEmpty(videoCodec))
            {
                Query.Append(" -vn");
            }
            else
            {
                Query.Append($" -vcodec {videoCodec}");
            }
            // Add audio codec.
            if (string.IsNullOrEmpty(audioCodec))
            {
                Query.Append(" -an");
            }
            else
            {
                Query.Append($" -acodec {audioCodec}");
            }

            if (!string.IsNullOrEmpty(encodeArgs))
            {
                Query.Append(" ");
                Query.Append(encodeArgs);
            }

            Query.Append(" \"");
            Query.Append(destination);
            Query.Append("\"");

            // Run FFmpeg with query.
            IProcessWorkerEncoder Worker = factory.CreateEncoder(options, callback);
            CompletionStatus      Result = RunEncoderInternal(source, Query.ToString(), Worker, sourceType, EncoderApp.FFmpeg);

            return(Result);
        }
예제 #17
0
 /// <summary>
 /// Encodes a VapourSynth script file using FFmpeg with specified arguments.
 /// </summary>
 /// <param name="source">The file to convert.</param>
 /// <param name="destination">The destination file.</param>
 /// <param name="videoCodec">The codec to use to encode the video stream.</param>
 /// <param name="audioCodec">The codec( to use to encode the audio stream.</param>
 /// <param name="encodeArgs">Additional arguments to pass to FFmpeg.</param>
 /// <param name="options">The options for starting the process.</param>
 /// <param name="callback">A method that will be called after the process has been started.</param>
 /// <returns>The process completion status.</returns>
 public CompletionStatus EncodeVapourSynthToFFmpeg(string source, string destination, string videoCodec, string audioCodec, string encodeArgs, ProcessOptionsEncoder options = null, ProcessStartedEventHandler callback = null)
 {
     return(EncodeFFmpegInternal(SourceType.VapourSynth, source, destination, videoCodec, audioCodec, encodeArgs, options, callback));
 }
예제 #18
0
 /// <summary>
 /// Extracts the audio stream from specified file.
 /// </summary>
 /// <param name="source">The media file to extract from.</param>
 /// <param name="destination">The destination file.</param>
 /// <param name="options">The options for starting the process.</param>
 /// <param name="callback">A method that will be called after the process has been started.</param>
 /// <returns>The process completion status.</returns>
 public CompletionStatus ExtractAudio(string source, string destination, ProcessOptionsEncoder options = null, ProcessStartedEventHandler callback = null)
 {
     return(ExtractStream(@"-y -i ""{0}"" -vn -acodec copy ""{1}""", source, destination, options, callback));
 }
예제 #19
0
        /// <summary>
        /// Truncates a media file from specified start position with specified duration. This can result in data loss or corruption if not splitting exactly on a framekey.
        /// </summary>
        /// <param name="source">The source file to truncate.</param>
        /// <param name="destination">The output file to write.</param>
        /// <param name="startPos">The position where to start copying. Anything before this position will be ignored. TimeSpan.Zero or null to start from beginning.</param>
        /// <param name="duration">The duration after which to stop copying. Anything after this duration will be ignored. TimeSpan.Zero or null to copy until the end.</param>
        /// <param name="options">The options for starting the process.</param>
        /// <param name="callback">A method that will be called after the process has been started.</param>
        /// <returns>The process completion status.</returns>
        public CompletionStatus Truncate(string source, string destination, TimeSpan?startPos, TimeSpan?duration = null, ProcessOptionsEncoder options = null, ProcessStartedEventHandler callback = null)
        {
            if (string.IsNullOrEmpty(source))
            {
                throw new ArgumentException("Source cannot be empty.", nameof(source));
            }
            if (string.IsNullOrEmpty(destination))
            {
                throw new ArgumentException("Destination cannot be empty.", nameof(destination));
            }
            fileSystem.Delete(destination);
            IProcessWorkerEncoder Worker = factory.CreateEncoder(options, callback);
            string Args = string.Format(@"-i ""{0}"" -vcodec copy -acodec copy {1}{2}""{3}""", source,
                                        startPos.HasValue && startPos > TimeSpan.Zero ? $"-ss {startPos:c} " : "",
                                        duration.HasValue && duration > TimeSpan.Zero ? $"-t {duration:c} " : "",
                                        destination);

            return(Worker.RunEncoder(Args, EncoderApp.FFmpeg));
        }
예제 #20
0
        /// <summary>
        /// Concatenates (merges) all specified files.
        /// </summary>
        /// <param name="files">The files to merge.</param>
        /// <param name="destination">The destination file.</param>
        /// <param name="options">The options for starting the process.</param>
        /// <param name="callback">A method that will be called after the process has been started.</param>
        /// <returns>The process completion status.</returns>
        public CompletionStatus Concatenate(IEnumerable <string> files, string destination, ProcessOptionsEncoder options = null, ProcessStartedEventHandler callback = null)
        {
            if (files == null || !files.Any())
            {
                throw new ArgumentException("Files cannot be null or empty.", nameof(files));
            }
            if (string.IsNullOrEmpty(destination))
            {
                throw new ArgumentException("Destination cannot be null or empty.", nameof(destination));
            }
            CompletionStatus Result = CompletionStatus.None;

            // Write temp file.
            string        TempFile    = fileSystem.GetTempFile();
            StringBuilder TempContent = new StringBuilder();

            foreach (string item in files)
            {
                TempContent.AppendFormat("file '{0}'", item).AppendLine();
            }
            fileSystem.WriteAllText(TempFile, TempContent.ToString());

            string Query = $@"-y -f concat -fflags +genpts -async 1 -safe 0 -i ""{TempFile}"" -c copy ""{destination}""";

            IProcessWorkerEncoder Worker = factory.CreateEncoder(options, callback);

            Result = Worker.RunEncoder(Query.ToString(), EncoderApp.FFmpeg);

            fileSystem.Delete(TempFile);
            return(Result);
        }
예제 #21
0
        /// <summary>
        /// Extracts an audio or video stream from specified file.
        /// </summary>
        /// <param name="args">The arguments string that will be passed to FFmpeg.</param>
        /// <param name="source">The media file to extract from.</param>
        /// <param name="destination">The destination file.</param>
        /// <param name="options">The options for starting the process.</param>
        /// <param name="callback">A method that will be called after the process has been started.</param>
        /// <returns>The process completion status.</returns>
        private CompletionStatus ExtractStream(string args, string source, string destination, ProcessOptionsEncoder options = null, ProcessStartedEventHandler callback = null)
        {
            if (string.IsNullOrEmpty(source))
            {
                throw new ArgumentException("Source cannot be empty.", nameof(source));
            }
            if (string.IsNullOrEmpty(destination))
            {
                throw new ArgumentException("Destination cannot be empty.", nameof(destination));
            }
            fileSystem.Delete(destination);
            IProcessWorkerEncoder Worker = factory.CreateEncoder(options, callback);

            return(Worker.RunEncoder(string.Format(args, source, destination), EncoderApp.FFmpeg));
        }