Exemplo n.º 1
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>
        /// <returns>A FFmpegProcess object containing the file information.</returns>
        public static FFmpegProcess GetFileInfo(string source, ProcessStartOptions options)
        {
            FFmpegProcess Worker = new FFmpeg.FFmpegProcess(options);

            Worker.RunFFmpeg(string.Format(@"-i ""{0}""", source));
            return(Worker);
        }
Exemplo n.º 2
0
        /// <summary>
        /// Returns the version information from FFmpeg.
        /// </summary>
        /// <param name="options">The options for starting the process.</param>
        /// <returns>A FFmpegProcess object containing the version information.</returns>
        public static FFmpegProcess GetVersion(ProcessStartOptions options)
        {
            FFmpegProcess Worker = new FFmpeg.FFmpegProcess(options);

            Worker.RunFFmpeg("-version", ProcessOutput.Standard);
            return(Worker);
        }
Exemplo n.º 3
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>
        /// <returns>The number of frames in the video.</returns>
        public static long GetFrameCount(string source, ProcessStartOptions options)
        {
            long          Result = 0;
            FFmpegProcess Worker = new FFmpeg.FFmpegProcess(options);

            Worker.StatusUpdated += (sender, e) => {
                Result = e.Status.Frame;
            };
            Worker.RunFFmpeg(string.Format(@"-i ""{0}"" -f null /dev/null", source));
            return(Result);
        }
Exemplo n.º 4
0
        /// <summary>
        /// Encodes a media file with specified arguments.
        /// </summary>
        /// <param name="source">The file to convert.</param>
        /// <param name="videoCodec">The codec(s) to use to encode the video stream(s).</param>
        /// <param name="audioCodec">The codec(s) to use to encode the audio stream(s).</param>
        /// <param name="encodeArgs">Additional arguments to pass to FFmpeg.</param>
        /// <param name="destination">The destination file.</param>
        /// <param name="options">The options for starting the process.</param>
        /// <returns>The process completion status.</returns>
        public static CompletionStatus Encode(string source, string[] videoCodec, string[] audioCodec, string encodeArgs, string destination, ProcessStartOptions options)
        {
            File.Delete(destination);
            StringBuilder Query = new StringBuilder();

            Query.Append("-y -i ");
            // AviSynth source will pipe through Avs2Yuv into FFmpeg.
            bool SourceAvisynth = source.ToLower().EndsWith(".avs");

            if (SourceAvisynth)
            {
                Query.Append("-"); // Pipe source
            }
            else
            {
                Query.Append("\"");
                Query.Append(source);
                Query.Append("\"");
            }

            // Add video codec.
            if (videoCodec == null || videoCodec.Length == 0)
            {
                Query.Append(" -vn");
            }
            else if (videoCodec.Length == 1)
            {
                Query.Append(" -vcodec ");
                Query.Append(videoCodec[0]);
            }
            else
            {
                for (int i = 0; i < videoCodec.Length; i++)
                {
                    Query.Append(" -vcodec:");
                    Query.Append(i);
                    Query.Append(" ");
                    Query.Append(videoCodec[i]);
                }
            }

            // Add audio codec.
            if (audioCodec == null || audioCodec.Length == 0)
            {
                Query.Append(" -an");
            }
            else if (audioCodec.Length == 1)
            {
                Query.Append(" -acodec ");
                Query.Append(audioCodec[0]);
            }
            else
            {
                for (int i = 0; i < audioCodec.Length; i++)
                {
                    Query.Append(" -acodec:");
                    Query.Append(i);
                    Query.Append(" ");
                    Query.Append(audioCodec[i]);
                }
            }

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

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

            // Run FFmpeg with query.
            FFmpegProcess    Worker = new FFmpeg.FFmpegProcess(options);
            CompletionStatus Result = SourceAvisynth ?
                                      Worker.RunAvisynthToFFmpeg(source, Query.ToString()) :
                                      Worker.RunFFmpeg(Query.ToString());

            return(Result);
        }
Exemplo n.º 5
0
 /// <summary>
 /// Encodes a media file with specified arguments.
 /// </summary>
 /// <param name="source">The file to convert.</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="destination">The destination file.</param>
 /// <param name="options">The options for starting the process.</param>
 /// <returns>The process completion status.</returns>
 public static CompletionStatus Encode(string source, string videoCodec, string audioCodec, string encodeArgs, string destination, ProcessStartOptions options)
 {
     string[] VideoCodecList = string.IsNullOrEmpty(videoCodec) ? null : new string[] { videoCodec };
     string[] AudioCodecList = string.IsNullOrEmpty(audioCodec) ? null : new string[] { audioCodec };
     return(Encode(source, VideoCodecList, AudioCodecList, encodeArgs, destination, options));
 }
Exemplo n.º 6
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="options">The options for starting the process.</param>
 /// <returns>The process completion status.</returns>
 public static CompletionStatus ConvertToAvi(string source, string destination, ProcessStartOptions options)
 {
     // -vcodec huffyuv or utvideo, -acodec pcm_s16le
     return(Encode(source, "utvideo", "pcm_s16le", null, destination, options));
 }
Exemplo n.º 7
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>
        /// <returns>The process completion status.</returns>
        public static CompletionStatus Muxe(IEnumerable <FFmpegStream> fileStreams, string destination, ProcessStartOptions options)
        {
            CompletionStatus Result    = CompletionStatus.Success;
            List <string>    TempFiles = new List <string>();

            File.Delete(destination);

            // FFMPEG fails to muxe H264 into MKV container. Converting to MP4 and then muxing with the audio, however, works.
            foreach (FFmpegStream item in fileStreams)
            {
                if (item.Type == FFmpegStreamType.Video && (item.Path.EndsWith(".264") || item.Path.EndsWith(".265")) && destination.EndsWith(".mkv"))
                {
                    string NewFile = item.Path.Substring(0, item.Path.Length - 4) + ".mp4";
                    Result = Muxe(item.Path, null, 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;
                foreach (FFmpegStream item in fileStreams.OrderBy(f => f.Type))
                {
                    if (item.Type == FFmpegStreamType.Video)
                    {
                        HasVideo = true;
                    }
                    if (item.Type == FFmpegStreamType.Audio)
                    {
                        HasAudio = true;
                        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)
                {
                    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 (fileStreams.Any(f => f.Path.ToLower().EndsWith(".aac")))
                {
                    Query.Append(" -bsf:a aac_adtstoasc");
                }
                Query.Append("\"");
                Query.Append(destination);
                Query.Append("\"");
                FFmpegProcess Worker = new FFmpegProcess(options);
                Worker.RunFFmpeg(Query.ToString());
            }

            // Delete temp file.
            foreach (string item in TempFiles)
            {
                File.Delete(item);
            }
            return(Result);
        }
Exemplo n.º 8
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>
        /// <returns>The process completion status.</returns>
        public static CompletionStatus Muxe(string videoFile, string audioFile, string destination, ProcessStartOptions options)
        {
            CompletionStatus Result = CompletionStatus.Success;

            File.Delete(destination);

            // FFMPEG fails to muxe H264 into MKV container. Converting to MP4 and then muxing with the audio, however, works.
            string OriginalVideoFile = videoFile;

            if ((videoFile.EndsWith(".264") || videoFile.EndsWith(".265")) && destination.ToLower().EndsWith(".mkv"))
            {
                videoFile = videoFile.Substring(0, videoFile.Length - 4) + ".mp4";
                Result    = Muxe(OriginalVideoFile, null, videoFile, options);
            }

            if (Result == CompletionStatus.Success)
            {
                // Join audio and video files.
                FFmpegProcess Worker = new FFmpegProcess(options);
                // FFMPEG-encoded AAC streams are invalid and require an extra flag to join.
                bool FixAac = audioFile != null?audioFile.ToLower().EndsWith(".aac") : false;

                string Query;
                if (string.IsNullOrEmpty(audioFile))
                {
                    Query = string.Format(@"-y -i ""{0}"" -vcodec copy -an ""{1}""", videoFile, destination);
                }
                else if (string.IsNullOrEmpty(videoFile))
                {
                    Query = string.Format(@"-y -i ""{0}"" -acodec copy -vn ""{1}""", videoFile, destination);
                }
                else
                {
                    Query = string.Format(@"-y -i ""{0}"" -i ""{1}"" -acodec copy -vcodec copy -map 0:v -map 1:a{2} ""{3}""", videoFile, audioFile, FixAac ? " -bsf:a aac_adtstoasc" : "", destination);
                }
                Result = Worker.RunFFmpeg(Query);
            }

            // Delete temp file.
            if (OriginalVideoFile != videoFile)
            {
                File.Delete(videoFile);
            }
            return(Result);
        }
Exemplo n.º 9
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>
        /// <returns>The process completion status.</returns>
        public static CompletionStatus ExtractAudio(string source, string destination, ProcessStartOptions options)
        {
            File.Delete(destination);
            FFmpegProcess Worker = new FFmpeg.FFmpegProcess(options);

            return(Worker.RunFFmpeg(string.Format(@"-y -i ""{0}"" -vn -acodec copy ""{1}""", source, destination)));
        }
Exemplo n.º 10
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>
        /// <returns>The process completion status.</returns>
        public static CompletionStatus Concatenate(IEnumerable <string> files, string destination, ProcessStartOptions options)
        {
            CompletionStatus Result = CompletionStatus.None;

            // Write temp file.
            string        TempFile    = Path.Combine(Path.GetDirectoryName(destination), "MergeList.txt");
            StringBuilder TempContent = new StringBuilder();

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

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

            FFmpegProcess Worker = new FFmpegProcess(options);

            Result = Worker.RunFFmpeg(Query.ToString());

            File.Delete(TempFile);
            return(Result);
        }
Exemplo n.º 11
0
 /// <summary>
 /// Initializes a new instances of the FFmpegProcess class with specified options.
 /// </summary>
 /// <param name="options">The options for starting the process.</param>
 public FFmpegProcess(ProcessStartOptions options)
 {
     Options = options ?? new ProcessStartOptions();
 }
Exemplo n.º 12
0
        /// <summary>
        /// Runs specified application with specified arguments.
        /// </summary>
        /// <param name="fileName">The application to start.</param>
        /// <param name="arguments">The set of arguments to use when starting the application.</param>
        /// <param name="isFFmpeg">Whether to parse the output as FFmpeg.</param>
        /// <param name="nestedProcess">If true, killing the process with kill all sub-processes.</param>
        /// <returns>The process completion status.</returns>
        public CompletionStatus Run(string fileName, string arguments, bool isFFmpeg, bool nestedProcess)
        {
            if (!File.Exists(FFmpegConfig.FFmpegPath))
            {
                throw new FileNotFoundException(string.Format(@"File ""{0}"" specified by FFmpegConfig.FFmpegPath is not found.", FFmpegConfig.FFmpegPath));
            }
            if (WorkProcess != null)
            {
                throw new InvalidOperationException("This instance of FFmpeg is busy. You can run concurrent commands by creating other class instances.");
            }

            Process P = new Process();

            this.isFFmpeg = isFFmpeg;
            WorkProcess   = P;
            output        = new StringBuilder();
            isStarted     = false;
            FileStreams   = null;
            FrameCount    = 0;
            FileDuration  = TimeSpan.Zero;
            cancelWork    = new CancellationTokenSource();
            if (Options == null)
            {
                Options = new ProcessStartOptions();
            }

            P.StartInfo.FileName  = fileName;
            P.StartInfo.Arguments = arguments;
            P.OutputDataReceived += FFmpeg_DataReceived;
            P.ErrorDataReceived  += FFmpeg_DataReceived;

            if (Options.DisplayMode != FFmpegDisplayMode.Native)
            {
                if (Options.DisplayMode == FFmpegDisplayMode.Interface && FFmpegConfig.UserInterfaceManager != null)
                {
                    FFmpegConfig.UserInterfaceManager.Display(this);
                }
                P.StartInfo.CreateNoWindow        = true;
                P.StartInfo.WindowStyle           = ProcessWindowStyle.Hidden;
                P.StartInfo.RedirectStandardError = true;
                P.StartInfo.UseShellExecute       = false;
            }

            Options.RaiseStarted(this);

            P.Start();
            try {
                if (!P.HasExited)
                {
                    P.PriorityClass = Options.Priority;
                }
            }
            catch { }
            P.BeginErrorReadLine();

            bool Timeout = Wait();

            // ExitCode is 0 for normal exit. Different value when closing the console.
            CompletionStatus Result = Timeout ? CompletionStatus.Timeout : cancelWork.IsCancellationRequested ? CompletionStatus.Cancelled : P.ExitCode == 0 ? CompletionStatus.Success : CompletionStatus.Error;

            isStarted            = false;
            cancelWork           = null;
            LastCompletionStatus = Result;
            Completed?.Invoke(this, new CompletedEventArgs(Result));
            if ((Result == CompletionStatus.Error || Result == CompletionStatus.Timeout) && Options.DisplayMode == FFmpegDisplayMode.ErrorOnly)
            {
                FFmpegConfig.UserInterfaceManager?.DisplayError(this);
            }
            return(Result);
        }