nLL

Mobile web, .Net, Android, gadgets and some random stuff

Another Simple C# Wrapper For FFmpeg

After reading below article do not forget to checkout Important Update to Another Simple C# Wrapper For FFmpeg

When you want to encode uploaded videos to your website you are in luck if you use PHP, encoding uploaded videos to your web site on the fly quite easy on Linux based servers. Install FFmpeg and get a PHP wrapper for FFmpeg and you are good to go.

Story is a little bit different on Windows servers. There is no support from .Net framework; although there are couple of open source C# .Net wrappers for FFmpeg that encodes video on the fly, they are mostly incomplete. There are also commercial ones such as Mediahandler are not free/open-source.

In short, I couldn't get what i wanted from open-source ones so I've decided to write my own C# wrapper for FFmpeg.

My .Net skills are no where near good but here what i ended up with.

 

 

See usage in the example at the bottom of this post. Download whole project VideoEncoder.rar (48.54 kb) or download changes made by Anders (see comments) VideoEncoderAsync.rar (6.79 kb)

Don't forget to download FFmpeg win32 build and put in to FFmpeg folder in the project

 

 

My solution has 5 classes;

 

Encoder.cs, does the main job and gets FFmpegPath as input.

It has 3 methods :

  •  EncodeVideo: Encodes video with FFmpeg according to commands
  •  GetVideoThumbnail: Gets video thumbnail image without encoding video
  •  GetVideoInfo: Gets information about source video and assigns it to VideoFile class such as Duration, BitRate, AudioFormat, VideoFormat, Height, Width 

 

To do: Implement a class to insert logo on to the video with ffmpeg -vhook

 

Source of Encoder.cs

 

using System;
using System.Diagnostics;
using System.IO;
using System.Text.RegularExpressions;


namespace VideoEncoder
{
    public class Encoder
    {

        public EncodedVideo EncodeVideo(VideoFile input, string encodingCommand, string outputFile, bool getVideoThumbnail)
        {
            EncodedVideo encoded = new EncodedVideo();

            Params = string.Format("-i {0} {1} {2}", input.Path, encodingCommand, outputFile);
            string output = RunProcess(Params);
            encoded.EncodingLog = output;
            encoded.EncodedVideoPath = outputFile;
            




            if (File.Exists(outputFile))
            {
                encoded.Success = true;

                //get thumbnail?
                if (getVideoThumbnail)
                {
                    string saveThumbnailTo = outputFile + "_thumb.jpg";

                    if (GetVideoThumbnail(input, saveThumbnailTo))
                    {
                        encoded.ThumbnailPath = saveThumbnailTo;
                    }
                }
            }
            else
            {
                encoded.Success = false;
            }


            return encoded;

        }
        public bool GetVideoThumbnail(VideoFile input, string saveThumbnailTo)
        {
            if (!input.infoGathered)
            {
                GetVideoInfo(input);
            }
            int secs;
            //divide the duration in 3 to get a preview image in the middle of the clip
            //instead of a black image from the beginning.
            secs = (int)Math.Round(TimeSpan.FromTicks(input.Duration.Ticks / 3).TotalSeconds, 0);
            string Params = string.Format("-i {0} {1} -vcodec mjpeg -ss {2} -vframes 1 -an -f rawvideo", input.Path, saveThumbnailTo, secs);
            string output = RunProcess(Params);

            if (File.Exists(saveThumbnailTo))
            {
                return true;
            }
            else
            {
                //try running again at frame 1 to get something
                Params = string.Format("-i {0} {1} -vcodec mjpeg -ss {2} -vframes 1 -an -f rawvideo", input.Path, saveThumbnailTo, 1);
                output = RunProcess(Params);

                if (File.Exists(saveThumbnailTo))
                {
                    return true;
                }
                else
                {
                    return false;
                }
            }


        }
        public void GetVideoInfo(VideoFile input)
        {
            string Params = string.Format("-i {0}", input.Path);
            string output = RunProcess(Params);
            input.RawInfo = output;
            input.Duration = ExtractDuration(input.RawInfo);
            input.BitRate = ExtractBitrate(input.RawInfo);
            input.RawAudioFormat = ExtractRawAudioFormat(input.RawInfo);
            input.AudioFormat = ExtractAudioFormat(input.RawAudioFormat);
            input.RawVideoFormat = ExtractRawVideoFormat(input.RawInfo);
            input.VideoFormat = ExtractVideoFormat(input.RawVideoFormat);
            input.Width = ExtractVideoWidth(input.RawInfo);
            input.Height = ExtractVideoHeight(input.RawInfo);
            input.infoGathered = true;
        }
        private string RunProcess(string Parameters)
        {
            //create a process info
            ProcessStartInfo oInfo = new ProcessStartInfo(this.FFmpegPath, Parameters);
            oInfo.UseShellExecute = false;
            oInfo.CreateNoWindow = true;
            oInfo.RedirectStandardOutput = true;
            oInfo.RedirectStandardError = true;

            //Create the output and streamreader to get the output
            string output = null; StreamReader srOutput = null;

            //try the process
            try
            {
                //run the process
                Process proc = System.Diagnostics.Process.Start(oInfo);

                proc.WaitForExit();

                //get the output
                srOutput = proc.StandardError;

                //now put it in a string
                output = srOutput.ReadToEnd();

                proc.Close();
            }
            catch (Exception)
            {
                output = string.Empty;
            }
            finally
            {
                //now, if we succeded, close out the streamreader
                if (srOutput != null)
                {
                    srOutput.Close();
                    srOutput.Dispose();
                }
            }
            return output;
        }
        public string FFmpegPath { get; set; }
        private string Params { get; set; }
        private TimeSpan ExtractDuration(string rawInfo)
        {
            TimeSpan t = new TimeSpan(0);
            Regex re = new Regex("[D|d]uration:.((\\d|:|\\.)*)", RegexOptions.Compiled);
            Match m = re.Match(rawInfo);

            if (m.Success)
            {
                string duration = m.Groups[1].Value;
                string[] timepieces = duration.Split(new char[] { ':', '.' });
                if (timepieces.Length == 4)
                {
                    t = new TimeSpan(0, Convert.ToInt16(timepieces[0]), Convert.ToInt16(timepieces[1]), Convert.ToInt16(timepieces[2]), Convert.ToInt16(timepieces[3]));
                }
            }

            return t;
        }
        private double ExtractBitrate(string rawInfo)
        {
            Regex re = new Regex("[B|b]itrate:.((\\d|:)*)", RegexOptions.Compiled);
            Match m = re.Match(rawInfo);
            double kb = 0.0;
            if (m.Success)
            {
                Double.TryParse(m.Groups[1].Value, out kb);
            }
            return kb;
        }
        private string ExtractRawAudioFormat(string rawInfo)
        {
            string a = string.Empty;
            Regex re = new Regex("[A|a]udio:.*", RegexOptions.Compiled);
            Match m = re.Match(rawInfo);
            if (m.Success)
            {
                a = m.Value;
            }
            return a.Replace("Audio: ", "");
        }
        private string ExtractAudioFormat(string rawAudioFormat)
        {
            string[] parts = rawAudioFormat.Split(new string[] { ", " }, StringSplitOptions.None);
            return parts[0].Replace("Audio: ", "");
        }
        private string ExtractRawVideoFormat(string rawInfo)
        {
            string v = string.Empty;
            Regex re = new Regex("[V|v]ideo:.*", RegexOptions.Compiled);
            Match m = re.Match(rawInfo);
            if (m.Success)
            {
                v = m.Value;
            }
            return v.Replace("Video: ", ""); ;
        }
        private string ExtractVideoFormat(string rawVideoFormat)
        {
            string[] parts = rawVideoFormat.Split(new string[] { ", " }, StringSplitOptions.None);
            return parts[0].Replace("Video: ", "");
        }
        private int ExtractVideoWidth(string rawInfo)
        {
            int width = 0;
            Regex re = new Regex("(\\d{2,4})x(\\d{2,4})", RegexOptions.Compiled);
            Match m = re.Match(rawInfo);
            if (m.Success)
            {
                int.TryParse(m.Groups[1].Value, out width);
            }
            return width;
        }
        private int ExtractVideoHeight(string rawInfo)
        {
            int height = 0;
            Regex re = new Regex("(\\d{2,4})x(\\d{2,4})", RegexOptions.Compiled);
            Match m = re.Match(rawInfo);
            if (m.Success)
            {
                int.TryParse(m.Groups[2].Value, out height);
            }
            return height;
        }
    }
}

 

 

 

EncodedVideo.cs is output package for Encode method

Source of EncodedVideo.cs

 

namespace VideoEncoder
{
    public class EncodedVideo
    {
        public string EncodedVideoPath { get; set; }
        public string ThumbnailPath {get; set; }
        public string EncodingLog { get; set; }
        public bool Success { get; set; }
    }

}

 

 

VideoFile.cs holds properties of input/source video

Source of VideoFile.cs

 

using System;
using System.IO;

namespace VideoEncoder
{

    public class VideoFile
    {
        private string _Path;
        public string Path
        {
            get
            {
                return _Path;
            }
            set
            {
                _Path = value;
            }
        }
        public TimeSpan Duration { get; set; }
        public double BitRate { get; set; }
        public string RawAudioFormat { get; set; }
        public string AudioFormat { get; set; }
        public string RawVideoFormat { get; set; }
        public string VideoFormat { get; set; }
        public int Height { get; set; }
        public int Width { get; set; }
        public string RawInfo { get; set; }
        public bool infoGathered { get; set; }

        public VideoFile(string path)
        {
            _Path = path;
            Initialize();
        }
        private void Initialize()
        {
            this.infoGathered = false;
            if (string.IsNullOrEmpty(_Path))
            {
                throw new Exception("Video file Path not set or empty.");
            }
            if (!File.Exists(_Path))
            {
                throw new Exception("The video file " + _Path + " does not exist.");
            }
        }
    }
}

 

Project also have two helper classes QuickAudioEncodingCommands.cs and QuickVideoEncodingCommands.cs to make video encoding easier. I simple created FFmpeg command-line snippets for easy encoding

Source of QuickAudioEncodingCommands.cs

 

/// 
/// 
/// Ready made encoding commands for FFmpeg
/// Use when calling EncodeVideo commands as string encodingCommand
/// Add remove as you like
/// 
///
///
public class QuickAudioEncodingCommands
{
        //mp3
    public static string MP3128Kbps = "-y -ab 128k -ar 44100";
    public static string MP396Kbps = "-y -ab 96k -ar 44100";
    public static string MP364Kbps = "-y -ab 64k -ar 44100";
    public static string MP332Kbps = "-y -ab 32k -ar 44100";
 }

 

 

Source of  QuickVideoEncodingCommands.cs

 

/// 
/// 
/// Ready made encoding commands for FFmpeg
/// Use when calling EncodeVideo commands as string encodingCommand
/// Add remove as you like
/// 
///
///
namespace VideoEncoder
{
    public class QuickVideoEncodingCommands
    {
        //-b
        static string LQVideoBitrate = "256k";
        static string MQVideoBitrate = "512k";
        static string HQVideoBitrate = "756k";
        static string VHQVideoBitrate = "1024k";
        //-ab 
        static string LQAudioBitrate = "32k";
        static string MQAudioBitrate = "64k";
        static string HQAudioBitrate = "96k";
        static string VHQAudioBitrate = "128k";
        //-ar
        static string LQAudioSamplingFrequency = "22050";
        static string MQAudioSamplingFrequency = "44100";
        static string HQAudioSamplingFrequency = "44100";
        //-s
        static string SQCIF = "sqcif"; //128x96
        static string QCIF = "qcif"; //176x144
        static string QVGA = "qvga"; //320x240
        static string CIF = "cif"; //352x288
        static string VGA = "vga"; //640x480
        static string SVGA = "svga"; //800x600

   
        // todo
        //insert logo
        //
        //string LogoPath ="/Path/to/transparent/png";
        //string PositionX ="0";
        //string PositionY ="0";
        //string.Format("-vhook \"vhook/imlib2.dll -x {0} -y {1}  -i {2}\"", PositionX,PositionY,LogoPath);



        //flv
        public static string FLVLowQualityQCIF = string.Format("-y -b {0} -ab {1} -ar {2} -s {3} -f flv", LQVideoBitrate, LQAudioBitrate, LQAudioSamplingFrequency, QVGA);
        public static string FLVMediumQualityCIF = string.Format("-y -b {0} -ab {1} -ar {2} -s {3} -f flv", MQVideoBitrate, MQAudioBitrate, MQAudioSamplingFrequency, CIF);
        public static string FLVHighQualityVGA = string.Format("-y -b {0} -ab {1} -ar {2} -s {3} -f flv", HQVideoBitrate, HQAudioBitrate, HQAudioSamplingFrequency, VGA);
        public static string FLVVeryHighQualitySVGA = string.Format("-y -b {0} -ab {1} -ar {2} -s {3} -f flv", VHQVideoBitrate, VHQAudioBitrate, HQAudioSamplingFrequency, SVGA);

        public static string FLVLowQualityKeepOriginalSize = string.Format("-y -b {0} -ab {1} -ar {2} -f flv", LQVideoBitrate, LQAudioBitrate, LQAudioSamplingFrequency, QVGA);
        public static string FLVMediumQualityKeepOriginalSize = string.Format("-y -b {0} -ab {1} -ar {2} -f flv", MQVideoBitrate, MQAudioBitrate, MQAudioSamplingFrequency, CIF);
        public static string FLVHighQualityKeepOriginalSize = string.Format("-y -b {0} -ab {1} -ar {2} -f flv", HQVideoBitrate, HQAudioBitrate, HQAudioSamplingFrequency, VGA);
        public static string FLVVeryHighQualityKeepOriginalSize = string.Format("-y -b {0} -ab {1} -ar {2} -f flv", VHQVideoBitrate, VHQAudioBitrate, HQAudioSamplingFrequency, SVGA);

        //3gp
        public static string THREEGPLowQualitySQCIF = string.Format("-y -acodec aac -ac 1 -b {0} -ab {1} -ar {2} -s {3} -f 3gp", LQVideoBitrate, LQAudioBitrate, LQAudioSamplingFrequency, SQCIF);
        public static string THREEGPMediumQualityQCIF = string.Format("-y -acodec aac -b {0} -ab {1} -ar {2} -s {3} -f 3gp", MQVideoBitrate, MQAudioBitrate, MQAudioSamplingFrequency, QCIF);
        public static string THREEGPHighQualityCIF = string.Format("-y -acodec aac -b {0} -ab {1} -ar {2} -s {3} -f 3gp", VHQVideoBitrate, VHQAudioBitrate, HQAudioSamplingFrequency, CIF);
        //mp4
        public static string MP4LowQualityKeepOriginalSize = string.Format("-y -b {0} -ab {1} -ar {2} -f mp4", LQVideoBitrate, LQAudioBitrate, LQAudioSamplingFrequency, QVGA);
        public static string MP4MediumQualityKeepOriginalSize = string.Format("-y -b {0} -ab {1} -ar {2} -f mp4", MQVideoBitrate, MQAudioBitrate, MQAudioSamplingFrequency, CIF);
        public static string MP4HighQualityKeepOriginalSize = string.Format("-y -b {0} -ab {1} -ar {2} -f mp4", HQVideoBitrate, HQAudioBitrate, HQAudioSamplingFrequency, VGA);

        public static string MP4LowQualityQVGA = string.Format("-y -b {0} -ab {1} -ar {2} -s {3} -f mp4", LQVideoBitrate, LQAudioBitrate, LQAudioSamplingFrequency, QVGA);
        public static string MP4MediumQualityCIF = string.Format("-y -b {0} -ab {1} -ar {2} -s {3} -f mp4", MQVideoBitrate, MQAudioBitrate, MQAudioSamplingFrequency, CIF);
        public static string MP4HighQualityVGA = string.Format("-y -b {0} -ab {1} -ar {2} -s {3} -f mp4", HQVideoBitrate, HQAudioBitrate, HQAudioSamplingFrequency, VGA);

        //WMV
        public static string WMVLowQualityQVGA = string.Format("-y -vcodec wmv2  -acodec wmav2 -b {0} -ab {1} -ar {2} -s {3}", LQVideoBitrate, LQAudioBitrate, LQAudioSamplingFrequency, QVGA);
        public static string WMVMediumQualityCIF = string.Format("-y -vcodec wmv2  -acodec wmav2 -b {0} -ab {1} -ar {2} -s {3}", MQVideoBitrate, MQAudioBitrate, MQAudioSamplingFrequency, CIF);
        public static string WMVHighQualityVGA = string.Format("-y -vcodec wmv2  -acodec wmav2 -b {0} -ab {1} -ar {2} -s {3}", HQVideoBitrate, HQAudioBitrate, HQAudioSamplingFrequency, VGA);
        public static string WMVVeryHighQualitySVGA = string.Format("-y -vcodec wmv2  -acodec wmav2 -b {0} -ab {1} -ar {2} -s {3}", VHQVideoBitrate, VHQAudioBitrate, HQAudioSamplingFrequency, SVGA);

        public static string WMVLowQualityKeepOriginalSize = string.Format("-y -vcodec wmv2  -acodec wmav2 -b {0} -ab {1} -ar {2}", LQVideoBitrate, LQAudioBitrate, LQAudioSamplingFrequency, QVGA);
        public static string WMVMediumQualityKeepOriginalSize = string.Format("-y -vcodec wmv2  -acodec wmav2 -b {0} -ab {1} -ar {2}", MQVideoBitrate, MQAudioBitrate, MQAudioSamplingFrequency, CIF);
        public static string WMVHighQualityKeepOriginalSize = string.Format("-y -vcodec wmv2  -acodec wmav2 -b {0} -ab {1} -ar {2}", HQVideoBitrate, HQAudioBitrate, HQAudioSamplingFrequency, VGA);
        public static string WMVVeryHighQualityKeepOriginalSize = string.Format("-y -vcodec wmv2  -acodec wmav2 -b {0} -ab {1} -ar {2}", VHQVideoBitrate, VHQAudioBitrate, HQAudioSamplingFrequency, SVGA);

    }
}

Sample Usage

 

using System;
using VideoEncoder;

public partial class _Default : System.Web.UI.Page
{
    protected void Page_Load(object sender, EventArgs e)
    {
        Encoder enc = new Encoder();
        enc.FFmpegPath = Server.MapPath("~/FFmpeg/ffmpeg.exe");
        VideoFile inputv = new VideoFile(Server.MapPath("~/WorkingFolder/SourceVideo.wmv"));
        string outputVPath = Server.MapPath("~/WorkingFolder/OutputVideo.flv");
        string saveThumbnailTo = Server.MapPath("~/WorkingFolder/OutputVideoThumbnail.jpg");
        
        // to get video thumbnail call
        enc.GetVideoThumbnail(inputv,saveThumbnailTo);


        // to encode video call
        EncodedVideo encoded = enc.EncodeVideo(inputv, QuickVideoEncodingCommands.FLVVeryHighQualityKeepOriginalSize, outputVPath, true);
        if (encoded.Success)
        {
            Response.Write(encoded.ThumbnailPath);
            Response.Write("
"); Response.Write(encoded.EncodedVideoPath); Response.Write("
"); Response.Write(encoded.EncodingLog); } else { Response.Write(encoded.EncodingLog); } } }

This project borrowed some code from http://jasonjano.wordpress.com/2010/02/09/a-simple-c-wrapper-for-ffmpeg/

 

Comments (41) -

  • youngbobby

    5/18/2010 3:59:45 PM | Reply

    Quite a huge source thanks.

    You make me wanna change mind over to .net c# Laughing

  • Ingve Moss Liknes

    5/31/2010 11:52:21 AM | Reply

    Great article! Thanks!

  • Anders Tornes

    8/24/2010 12:51:44 AM | Reply

    Hei, thank you very much for this code Smile

    I have fixed a bug where filenames with spaces caused errors and and added Async methods, progress event and finished event. Will be adding some more functionality soon. Drop me a line if ur interested.

    Best regards, Anders.

  • Ingve Moss Liknes

    8/24/2010 6:17:32 AM | Reply

    Anders, have you posted your code somewhere? Smile

    • Anders Tornes

      8/24/2010 6:14:06 PM | Reply

      Hi, not yet. I need to add more error handling, do some more testing and clean up the code. I will ping here when it's ready Smile

      • Ingve Moss Liknes

        8/25/2010 2:48:16 AM | Reply

        Thanks! Smile

      • nolovelust

        8/25/2010 4:42:26 PM | Reply

        i'd love to post it here once it is available if you don't mind

        • Anders Tornes

          8/25/2010 9:00:41 PM | Reply

          Sure, I think it's stable enough now. Atleast it's good enough for the use I intended Smile

          I haven't tested this in anything but WinForms as that is what i need if for.

          Here's a download link for the source:
          www.mediafire.com/.../VideoEncoderAsync.rar

          Changelog:
          -Fixed filename with spaces bug
          -Fixed deadlock issue with process execution
          -Added delegates, events and methods for progress and finish
          -Added extra fields in VideoFile for video and audio bitrate, framerate, totalframes
          -Added extraction methods for the above
          -Added RunProcessAsync
          -Added EncodeVideoAsync and EncodeVideoAsyncAutoCommand
          -Added encoder threads *read below*

          Threads:
          Threads in ffmpeg is not straight forward. Some codecs dont support multiple threads. The maximum thread count is not the same for codecs.
          Auto thread count can be used passing 0 as parameter, not all codecs support auto thead count.
          To disable threads, pass 1 as parameter.

          Example usage in WinForms: Add methods Progress and Finish
          Encoder enc = new Encoder();
          enc.FFmpegPath = "ffmpeg.exe";
          VideoFile videoFile = new VideoFile("C:\\some file.avi");
          string outputFile = "C:\\output file.wmv";
          enc.OnEncodeProgress += new EncodeProgressEventHandler(Progress);
          enc.OnEncodeFinished += new EncodeFinishedEventHandler(Finished);
          enc.EncodeVideoAsync(videoFile, QuickVideoEncodingCommands.WMVVeryHighQualityKeepOriginalSize, outputFile, this, 1);


          Enjoy
          Best regards, Anders Tornes

        • Tommy

          2/16/2012 11:58:10 PM | Reply

          Hi,

          I have the progressevent working firing in a WPF application c#
          No input is being received so i am not getting the total frames to drive the progressbar, is there something i am missing from your sample code to send in the data duration totalframes etc, if i put a value of frames progressbar works your code    //Set total frames
                              epe.TotalFrames = tempVideoFile.TotalFrames;
          the tempVideoFile is not getting the TotalFrames.

          Tommy

        • Tommy

          2/17/2012 1:35:13 AM | Reply

          Hi,

          Ok got it, i was using the RunProcessLargefiles for ASpnet which was causing the problem(regarding my last message to you Progressbar) Changed back to RunProgress all working as should thanks

            Encoder enc2 = new Encoder();
                    
                      string inputfile = _ctlUploadFile.Text;
                    
                      VideoFile videoFile2 = new VideoFile(inputfile);

                    
                
                  enc2.FFmpegPath = "C:\\Test/ffmpeg/ffmpeg.exe";
                
                  string outputFile2 = "C:\\Test/outputfile.mp4";
                  enc2.OnEncodeProgress += new EncodeProgressEventHandler(ProgressStart);
                  enc2.OnEncodeFinished += new EncodeFinishedEventHandler(Finished);
                       string saveThumbnailTo = "C:\\Test/OutputVideoThumbnail.jpg";
                      
                  enc2.GetVideoThumbnail(videoFile2, saveThumbnailTo);
                  enc2.EncodeVideoAsync(videoFile2, QuickVideoEncodingCommands.MP4HighQualityKeepOriginalSize,outputFile2, 1);





          For those c# WPF code progressbar
             private void ProgressStart(object sender,EncodeProgressEventArgs e)
                  {
                    
                      pb.Dispatcher.BeginInvoke(DispatcherPriority.Normal,
                          new DispatcherOperationCallback(delegate
                          {
                              // ignore just teting _ctlFileTransferLabel.Text =" % * " + e.Percentage+ " Total Frames *" + e.TotalFrames + " RawData *////// " + e.RawOutputLine;
                             // pb.Minimum = 0;
                             // pb.Maximum = 100;
                              pb.Value = e.Percentage;// pb is the progressbar
                              return null;
                          }), null);
                  }
          Tommy

          • ali ahmadi

            11/1/2012 4:32:27 AM | Reply

            How can I use progress bar in my winform ? I use your change code, but have error in ProgressStart and Finish. please help me! my progressbar name is pb.

        • Tommy

          2/17/2012 2:23:26 AM | Reply

          Hi,
          Final thing on progress for correct percentage to work
            public void GetVideoInfo(VideoFile input)
                  {
                      string Params = string.Format("-i \"{0}\"", input.Path);
                      string output =  RunProcess(Params);

                      input.RawInfo = output;
                      input.Duration = ExtractDuration(input.RawInfo);
                      input.BitRate = ExtractBitrate(input.RawInfo);
                      input.RawAudioFormat = ExtractRawAudioFormat(input.RawInfo);
                      input.AudioFormat = ExtractAudioFormat(input.RawAudioFormat);
                      input.RawVideoFormat = ExtractRawVideoFormat(input.RawInfo);
                      input.VideoFormat = ExtractVideoFormat(input.RawVideoFormat);
                      input.Width = ExtractVideoWidth(input.RawInfo);
                      input.Height = ExtractVideoHeight(input.RawInfo);
                      input.FrameRate = ExtractFrameRate(input.RawVideoFormat);
                      input.TotalFrames = ExtractTotalFrames(input.Duration, input.FrameRate / 100);// /100 needed here for correct percentage
                      input.AudioBitRate = ExtractAudioBitRate(input.RawAudioFormat);
                      input.VideoBitRate = ExtractVideoBitRate(input.RawVideoFormat);

                      input.infoGathered = true;
                  }
          /100 needed input.Framerate or you can to the maths somewhere else

          Tommy

  • Miguel

    9/7/2010 8:33:55 PM | Reply

    I was trying to get to the latest code Anders posted, but the link doesn’t work. I'm hoping mediafire is just down right now?

    Thanks for your work!

  • nolovelust

    9/7/2010 8:38:58 PM | Reply

    I have uploaded Anders' changes next to my download link

  • Vladimir Vincent

    12/15/2010 2:51:20 AM | Reply

    Need help

    Hi, I have tried your c# wrapper for ffmpeg the output file is always empty 0kb, the encodingLog field is empty. I am using the latest built of ffmpeg version 0.6. The output did create the thumbl pic.

    sample code:
    MediaVerse.Converter.Encoder enc = new MediaVerse.Converter.Encoder();
    enc.FFmpegPath = @"C:\Video\ffmpeg.exe";
    string inputFile = @"C:\Video\Wall.avi";
    VideoFile videoFile = new VideoFile(inputFile);
    string outputFile = @"C:\Encoded\Wall.mp4";            
    EncodedVideo encodedVideo = enc.EncodeVideo(videoFile, QuickVideoEncodingCommands.MP4LowQualityQVGA, outputFile, true);

  • Vladimir Vincent

    12/15/2010 3:10:24 AM | Reply

    Need Help
    the output file size is 0kb, the thumb pic file was created.
    I am using ffmpeg version 0.6, same thing with version 0.5

    MediaVerse.Converter.Encoder enc = new MediaVerse.Converter.Encoder();
                enc.FFmpegPath = @"C:\Video\ffmpeg.exe";
                string inputFile = @"C:\Video\Wall.avi";
                VideoFile videoFile = new VideoFile(inputFile);
                string outputFile = @"C:\Encoded\Wall.mp4";            
                EncodedVideo encodedVideo = enc.EncodeVideo(videoFile, QuickVideoEncodingCommands.MP4LowQualityQVGA, outputFile, true);


  • nolovelust

    12/17/2010 8:25:39 AM | Reply

    what does command line encoding returns? Try running ffmpeg on command line first to see if there is an error.

  • Jay

    2/28/2011 7:55:31 PM | Reply

    Hello,
    thanks for such a nice wrapper .I  want to add images in video file at bottom of video like youtube now a days.
    please help what i have to do with wrapper .
    please please help me. Frown

  • nolovelust

    2/28/2011 9:47:25 PM | Reply

    This is what i use to insert logo

    encodingCommand = "-y -vhook \"vhook/imlib2.dll -x 0 -y 0  -i " + LogoPath + "\" -acodec libfaac -ac 1 -ar 11025 -ab 12kb -b " + _SourceBitrate.ToString() + "k -f " + vidoeFormat;

    You need to download ffmpeg with vhook from http://ffmpeg.arrozcru.org/builds/

  • Jay

    3/1/2011 4:53:34 PM | Reply

    hello nolovelust
    sorry  but i am newbie to this type development can u explain more like i what i have to do first ,
    i mean i have to downloaded build from provided link now i have to install it or any thing ?please explain step to pre-requirement steps.


    2.I found something in QuickVideoEncodingCommands.cs file insert logo which is commented and if i comment out it give syntax error...please give me example  if u can

    help me please

  • Jay

    3/3/2011 5:03:42 PM | Reply

    hello i have following output when i look into this variable
    b  Params = string.Format("-i {0} {1} {2}", input.Path, encodingCommand, outputFile);
                string output = RunProcess(Params);
    output=FFmpeg version SVN-r25512, Copyright (c) 2000-2010 the FFmpeg developers
      built on Oct 18 2010 04:06:45 with gcc 4.4.2
      configuration: --enable-gpl --enable-version3 --enable-libgsm --enable-pthreads --enable-libvorbis --enable-libtheora --enable-libspeex --enable-libmp3lame --enable-libopenjpeg --enable-libschroedinger --enable-libopencore_amrwb --enable-libopencore_amrnb --enable-libvpx --arch=x86 --enable-runtime-cpudetect --enable-libxvid --enable-libx264 --extra-libs='-lx264 -lpthread' --enable-librtmp --extra-libs='-lrtmp -lpolarssl -lws2_32 -lwinmm' --target-os=mingw32 --enable-avisynth --cross-prefix=i686-mingw32- --cc='ccache i686-mingw32-gcc' --enable-memalign-hack
      libavutil     50.32. 3 / 50.32. 3
      libavcore      0. 9. 1 /  0. 9. 1
      libavcodec    52.92. 0 / 52.92. 0
      libavformat   52.83. 0 / 52.83. 0
      libavdevice   52. 2. 2 / 52. 2. 2
      libavfilter    1.52. 0 /  1.52. 0
      libswscale     0.12. 0 /  0.12. 0
    [mov,mp4,m4a,3gp,3g2,mj2 @ 01cfe060] multiple edit list entries, a/v desync might occur, patch welcome
    Input #0, mov,mp4,m4a,3gp,3g2,mj2, from 'D:\Data\Project\Project\ProjectWatermark\ProjectWatermark\bin\Debug\Demo.mp4':
      Metadata:
        major_brand     : mp42
        minor_version   : 0
        compatible_brands: mp42isom
        encoder         : mp4creator 1.6.1d
      Duration: 00:01:02.88, start: 0.000000, bitrate: 465 kb/s
        Stream #0.0(eng): Video: mpeg4, yuv420p, 320x240 [PAR 1:1 DAR 4:3], 401 kb/s, 18 fps, 18 tbr, 90k tbn, 18 tbc
        Stream #0.1(eng): Audio: aac, 22050 Hz, stereo, s16, 63 kb/s
    Unrecognized option 'vhook'


    this last line show that it doesnt work ..what should i do ?
    please guys help me...any help would b appreciate...i dont know any other option i have tried lot to solve this or achieve this funcationality .

  • Vincent

    3/22/2011 8:58:22 AM | Reply

    Some issue.
    I tried to generate the thumbnail using your method on movie files in the range of 1MB to 2 Gigs.
    On some the program just took minutes per video!
    Also I couldn't get the thumbnails in other sizes as the original size.

    So I changed the Params
    Your code:  string Params = string.Format("-i {0} {1} -vcodec mjpeg -ss {2} -vframes 1 -an -f rawvideo", input.Path, saveThumbnailTo, secs);

    into:
                string Params = string.Format("-itsoffset -4  -i {0} -vcodec mjpeg -vframes 1 -an -f rawvideo -s 320x240 {1}", input.Path, saveThumbnailTo);

    the 4 means take shot at 4 seconds, but of course can take it from anything else as well..
    the -s which didn't work in the original params string now works.

    So, in case others get these problems as well...
    oh yeah, taking a thumbnail from a 2Gigs Video now takes only a second..

  • nolovelust

    3/22/2011 9:17:28 AM | Reply

    If you check the comment

    "//divide the duration in 3 to get a preview image in the middle of the clip
    //instead of a black image from the beginning.
    "
    you'll see that it ready whole file, for large files like 2GB, your approach is better.

  • rajesh

    5/3/2011 9:00:17 AM | Reply

    hi..how can i set the height,width,bit ratio of the output video???

  • sagnik

    5/4/2011 3:31:59 PM | Reply

    hello,
    i am getting 0 as the duration of video. ffmpeg.exe process not starting yet .
    please suggest ....

  • raju

    5/4/2011 3:43:17 PM | Reply

    hi..how can i set the height,width,bit ratio of the output video???
    please give me a solution

  • sagnik

    5/5/2011 1:25:46 PM | Reply

    @nolovelust solved. it was my fault . thanks .

    a Suggestion :

    In GetVideoThumbnail method we can change   -f rawvideo (-f Force format option) into -f image2. It reduces the size of thumbnail file.  Normally for a jpeg file (400x300) of size 800kb comes into 6kb.


    Example :

    Params = string.Format("-i {0} {1} -vcodec mjpeg -ss {2} -vframes 1 -an -f rawvideo", input.Path, saveThumbnailTo, 1);

    to

    Params = string.Format("-i {0} {1} -vcodec mjpeg -ss {2} -vframes 1 -an -f image2", input.Path, saveThumbnailTo, 1);


    Thanks.

  • naseer123

    5/9/2011 1:17:47 AM | Reply

    hiSmile i'm new to this.. can u please tell me step by step procedure, how to build this wrapper successfully.. please help me out with this..
    thank youSmile

  • mrgenie

    7/13/2011 10:47:24 AM | Reply

    //create a process info
                ProcessStartInfo oInfo = new ProcessStartInfo(this.FFmpegPath, Parameters);
                oInfo.UseShellExecute = false;
                oInfo.CreateNoWindow = true;
                oInfo.RedirectStandardOutput = true;
                oInfo.RedirectStandardError = true;

                //Create the output and streamreader to get the output
                string output = null; StreamReader srOutput = null;

                //try the process
                try
                {
                    //run the process
                    Process proc = System.Diagnostics.Process.Start(oInfo);

                    proc.WaitForExit();

                    //get the output
                    srOutput = proc.StandardError;

                    //now put it in a string
                    output = srOutput.ReadToEnd();

                    proc.Close();
                }

    This Error was copied from Jasons Blog. He also wrote this error.

    Here's the fix:

    //create a process info
                ProcessStartInfo oInfo = new ProcessStartInfo(this.FFmpegPath, Parameters);
                oInfo.UseShellExecute = false;
                oInfo.CreateNoWindow = true;
                oInfo.RedirectStandardOutput = true;
                oInfo.RedirectStandardError = true;

                //Create the output and streamreader to get the output
                string output = "";

                //try the process
                try
                {
                    //run the process
                    Process proc = new Process {StartInfo = oInfo};
                    proc.Start();
                    output = proc.StandardError.ReadToEnd();
                    proc.WaitForExit();

                    proc.Close();
                }
                catch (Exception)
                {
                    output = string.Empty;
                }

                return output;

    Comment: if you enable the redirectstandards.  then ReadToEnd() has to be BEFORE The WaitForExit because
    .net needs it..
    if you try to get your readtoend() after the process exited.. well, hmm, not sure what you want to read there?
    should be empty once the process exited..

  • Murtaza

    1/30/2012 11:31:55 AM | Reply

    Hi, this is great, thanks. I just getting one problem, when I am converting my mp4 into wmv or avi, it is not working, I think my command line have some missing, can anyone give me list of command line to convert mp4 to avi or mp4 to any other format.

    Thanks,

  • rasheed

    2/3/2012 8:44:36 PM | Reply

    hey, thank you very much for this article, but i have a problem, in the ExtractBitrate method always i got the m.Success false, anybody can help me please?

  • Tommy

    2/18/2012 2:39:03 AM | Reply

    Hi All,

    Anyone know how to add a watermark to the video when converting or even after converted ?


    ps this has no loss in quality when converted

    public static string HD720x480 = string.Format("-y -c:v libx264 -preset fast -crf 24 -f mp4", HQVideoBitrate, HQAudioBitrate, HQAudioSamplingFrequency, VGA);





    Tommy

  • Tommy

    2/28/2012 10:40:16 PM | Reply

    Ok i answered my own question about adding a watermark, so in this case i do not use the -vhook but the libvavfilter note: in my case i am using ffmpeg static 32bit build which has all needed built-in other than my preset though there are a few presets built-in. In your quickvideocommands.cs file add

    public static string HD720x480 = string.Format("-y -c:v libx264 -preset fast -crf 24 -vf \"movie=starlogo.png [watermark]; [in][watermark] overlay=10:10 [out]\" -f mp4", HQVideoBitrate, HQAudioBitrate, HQAudioSamplingFrequency, VGA);

    I just named it HD720x480 this will convert to hd size with no loss of quality picture and sound and output .mp4 so it is H.264 now this will not work if the logo png is not in the correct path, in the above it is in my bin debug folder so if your logo path is some where else add the correct path, the "" are needed as for movie=
    so the watermark part of the above is -vf \"movie=starlogo.png [watermark]; [in][watermark] overlay=10:10 [out]\" do not change the\" unless you know what you are doing and are doing it a different way. your logo will be placed in the top left hand corner, my png is transparent background and the size is 100x30 it can be any size you wish.

    other options are

    Top right corner
    overlay=main_w-overlay_w-10:10 [out]"

    Bottom left corner
    overlay=10:main_h-overlay_h-10 [out]"

    Bottom right corner
    overlay=main_w-overlay_w-10:main_h-overlay_h-10 [out]"

    Rember this adds the water mark during the conversion, doing it after the conversion will require alot more time to finish.

    I hope i explained this easy, any problems just put your logo in the bin debug folder of your project and paste in the

    public static string HD720x480 = string.Format("-y -c:v libx264 -preset fast -crf 24 -vf \"movie=starlogo.png [watermark]; [in][watermark] overlay=10:10 [out]\" -f mp4", HQVideoBitrate, HQAudioBitrate, HQAudioSamplingFrequency, VGA);

    When you get it working you can try different logo path.

    Best of luck!

    • Nouman Ashraf

      4/19/2012 3:59:50 PM | Reply

      Hi, I m facing File Deadlock issue, some process seems continue to run after completion which keeps the input file locked. Any help on that will be appreciated.

  • Hadeer

    2/22/2013 10:24:30 AM | Reply

    Hi thanks a lot for the article, i just have a problem now when i try converting to mpeg small files do convert but a file which is 25mb doesn't get converted it just stops at 2.59 mb which i don't understand why , do you have any idea why such a problem occurs  ?

  • Michael Hagesfeld

    5/1/2013 7:37:08 PM | Reply

    This is absolutely fantastic.  Thank you so much.

  • MURSEL GURKAN

    5/16/2013 1:27:02 PM | Reply

    Hello. Thx for sharing. My question is how to use dll proect this code. I tried but didn't.
    I want to use dll on own web app. But dont work. Can you help me ?

  • mi

    7/5/2013 10:26:57 AM | Reply

    在 web 项目中无法获取媒体信息 异常 StandardError 尚未重定向  媒体转码却正常
    在winform 中获取媒体信息和转码都正常 求解

  • chary

    8/1/2013 7:15:48 AM | Reply

    Am used videoencoder for generating thumbnails from video.
    Issues am not solved.

    1. The generated thumbnail image are displayed as blank images(full black).

    2. How i can set thumbnail height and widht.

    Thanks and regards

    chary

Pingbacks and trackbacks (1)+

Add comment