Reversing media

Reverse is possible by operating on streams using Reverse() method:

IMediaInfo inputFile = await FFmpeg.GetMediaInfo(Resources.MkvWithAudio);
string outputPath = Path.ChangeExtension(Path.GetTempFileName(), ".mp4");

IVideoStream videoStream = inputFile.VideoStreams.First()
    .SetCodec(VideoCodec.H264)
    .Reverse();

IConversionResult conversionResult = await FFmpeg.Conversions.New()
    .AddStream(videoStream)
    .SetOutput(outputPath)
    .Start();

In given example output video file will have only one stream - reversed first video stream from source file.

Use Reverse() method is possible on IAudioStream and IVideoStream.

Changing speed

IVideoStream and IAudioStream allow to change media speed:

IMediaInfo inputFile = await FFmpeg.GetMediaInfo(Resources.MkvWithAudio);
string outputPath = Path.ChangeExtension(Path.GetTempFileName(), ".mp4");

IVideoStream videoStream = inputFile.VideoStreams.First().SetCodec(VideoCodec.H264).ChangeSpeed(1.5);

IConversionResult conversionResult = await FFmpeg.Conversions.New()
    .AddStream(videoStream)
    .SetOutput(outputPath)
    .Start();

ChangeSpeed() method accepting 1 argument - multiplayer. Multiplayer has to be between 0.5 and 2.0. If you want to speed up streams, use values greater than 1, if not, less than 1.

Changing size

The simplest way to change video size is by FFmpeg.Conversions.FromSnippet.ChangeSize:

string output = Path.ChangeExtension(Path.GetTempFileName(), ".mkv");
string input = Resources.MkvWithAudio;

var conversion = await FFmpeg.Conversions.FromSnippet.ChangeSize(input, output, VideoSize.Nhd);

IConversionResult result = await conversion.Start();

Changing video format

FFmpeg.Conversions.FromSnippet contains few predefined methods to change video format e.g.:

await FFmpeg.Conversions.FromSnippet.ToOgv(inputVideoPath, outputPathOgv);
await FFmpeg.Conversions.FromSnippet.ToTs(inputVideoPath, outputPathTs);
await FFmpeg.Conversions.FromSnippet.ToWebM(inputVideoPath, outputPathWebm);

More conversion types are possible by using new Conversion:

string inputVideoPath = Path.Combine("C:", "Temp", "input.mkv");
string outputPathMp4 = Path.Combine("C:", "Temp", "result.mp4");

IMediaInfo info = await FFmpeg.GetMediaInfo(inputVideoPath);

IStream videoStream = info.VideoStreams.FirstOrDefault()
    ?.SetCodec(VideoCodec.H264);
IStream audioStream = info.AudioStreams.FirstOrDefault()
    ?.SetCodec(AudioCodec.Aac);

return FFmpeg.Conversions.New()
    .AddStream(videoStream, audioStream)
    .SetOutput(outputPathMp4);

Working with images

Sometimes it is necessary to handle a lot of images and converting images to videos or vice versa. Changing video to images is possible thanks to ExtractEveryNthFrame:

Func outputFileNameBuilder = (number) => { return 'fileNameNo' + number + ".png"; };
IMediaInfo info = await FFmpeg.GetMediaInfo(Resources.MkvWithAudio).ConfigureAwait(false);
IVideoStream videoStream = info.VideoStreams.First()?.SetCodec(VideoCodec.Png);

IConversionResult conversionResult = await FFmpeg.Conversions.New()
    .AddStream(videoStream)
    .ExtractEveryNthFrame(10, outputFileNameBuilder)
    .Start();

Above code extracts every 10th frame from input video and saves it to the files: 'fileNameNo001.png', 'fileNameNo002.png' and so on until every 10th frame is saved. For example, if video has 26 frames, only 2 images is saved.

ExtractNthFrame can be used only if one frame is required:

Func outputFileNameBuilder = (number) => { return 'fileNameNo' + number + ".png"; };
IMediaInfo info = await FFmpeg.GetMediaInfo(Resources.MkvWithAudio).ConfigureAwait(false);
IVideoStream videoStream = info.VideoStreams.First()?.SetCodec(VideoCodec.Png);

IConversionResult conversionResult = await FFmpeg.Conversions.New()
    .AddStream(videoStream)
    .ExtractNthFrame(10, outputFileNameBuilder)
    .Start();

Above example creates file named 'fileNameNo001.png' containing 10th frame of a video.

BuildVideoFromImages is used to do oposite thing - changing collection of images to video:

List files = Directory.EnumerateFiles(Resources.Images).ToList();

await Conversion.New()
    .SetInputFrameRate(1)
    .BuildVideoFromImages(files)
    .SetFrameRate(1)
    .SetOutputPixelFormat(PixelFormat.Yuv420P)
    .SetOutput("outputfile.mp4")
    .Start();

Changing bitrate

Xabe.FFmpeg provide support for changing bitrate on Audio and Video streams:

string inputVideoPath = Path.Combine("C:", "Temp", "input.mkv");
string outputPathMp4 = Path.Combine("C:", "Temp", "result.mp4");

IMediaInfo info = await FFmpeg.GetMediaInfo(inputVideoPath);

IStream videoStream = info.VideoStreams.FirstOrDefault()
    ?.SetBitrate(6000);
IStream audioStream = info.AudioStreams.FirstOrDefault()
    ?.SetBitrate(192000);

return FFmpeg.Conversions.New()
    .AddStream(videoStream, audioStream)
    .SetOutput(outputPathMp4);

Changing video framerate

string inputVideoPath = Path.Combine("C:", "Temp", "input.mkv");
string outputPathMp4 = Path.Combine("C:", "Temp", "result.mp4");

IMediaInfo info = await FFmpeg.GetMediaInfo(inputVideoPath);

IStream videoStream = info.VideoStreams.FirstOrDefault()
    ?.SetFramerate(29.97);

return FFmpeg.Conversions.New()
    .AddStream(videoStream, audioStream)
    .SetOutput(outputPathMp4);

Methods


/// <summary>
///     Rotate video
/// </summary>
/// <param name="rotateDegrees">Rotate type</param>
/// <returns>IVideoStream</returns>
IVideoStream Rotate(RotateDegrees rotateDegrees);
/// <summary>
///     Change speed of video
/// </summary>
/// <param name="multiplicator">Speed value. (0.5 - 2.0). To double the speed set this to 2.0</param>
/// <returns>IVideoStream</returns>
/// <exception cref="ArgumentOutOfRangeException">When speed isn't between 0.5 - 2.0.</exception>
IVideoStream ChangeSpeed(double multiplicator);
/// <summary>
///     Melt watermark into video
/// </summary>
/// <param name="imagePath">Watermark</param>
/// <param name="position">Position of watermark</param>
/// <returns>IVideoStream</returns>
IVideoStream SetWatermark(string imagePath, Position position);
/// <summary>
///     Reverse video
/// </summary>
/// <returns>IVideoStream</returns>
IVideoStream Reverse();
/// <summary>
///     Set Flags for conversion (-flags option)
/// </summary>
/// <param name="flags">Flags to use</param>
/// <returns>IVideoStream</returns>
IVideoStream SetFlags(params Flag[] flags);
/// <summary>
///     Set Flags for conversion (-flags option)
/// </summary>
/// <param name="flags">Flags to use</param>
/// <returns>IVideoStream</returns>
IVideoStream SetFlags(params string[] flags);
/// <summary>
///     Set Framerate of the video (-r option)
/// </summary>
/// <param name="framerate">Framerates in FPS</param>
/// <returns>IVideoStream</returns>
IVideoStream SetFramerate(double framerate);
/// <summary>
///     Set Bitrate of the video (-b:v option)
/// </summary>
/// <param name="minBitrate">Bitrate in bits</param>
/// <param name="maxBitrate">Bitrate in bits</param>
/// <param name="buffersize">Buffersize in bits</param>
/// <returns>IVideoStream</returns>
IVideoStream SetBitrate(long minBitrate, long maxBitrate, long bufferSize);
/// <summary>
///     Set Bitrate of the video (-b:v option)
/// </summary>
/// <param name="bitrate">Bitrate in bits</param>
/// <returns>IVideoStream</returns>
IVideoStream SetBitrate(long bitrate);
/// <summary>
///     Set size of video
/// </summary>
/// <param name="size">VideoSize</param>
/// <returns>IVideoStream</returns>
IVideoStream SetSize(VideoSize size);
/// <summary>
///     Set size of video
/// </summary>
/// <param name="width">Width</param>
/// <param name="height">Height</param>
/// <returns>IVideoStream</returns>
IVideoStream SetSize(int width, int height);
/// <summary>
///     Set video codec
/// </summary>
/// <param name="codec">Video codec</param>
/// <returns>IVideoStream</returns>
IVideoStream SetCodec(VideoCodec codec);
/// <summary>
///     Set video codec
/// </summary>
/// <param name="codec">Video codec</param>
/// <returns>IVideoStream</returns>
IVideoStream SetCodec(string codec);
/// <summary>
///     Set stream to copy with orginal codec
/// </summary>
/// <returns>IVideoStream</returns>
IVideoStream CopyStream();
/// <summary>
///     Set filter
/// </summary>
/// <param name="filter">Filter</param>
/// <returns>IVideoStream</returns>
IVideoStream SetBitstreamFilter(BitstreamFilter filter);
/// <summary>
///     Loop over the input stream.(-loop)
/// </summary>
/// <param name="count">Number of repeats</param>
/// <param name="delay">Delay between repeats (in seconds)</param>
/// <returns>IVideoStream</returns>
IVideoStream SetLoop(int count, int delay = 0);
/// <summary>
///     Set output frames count
/// </summary>
/// <param name="number">Number of frames</param>
/// <returns>IVideoStream</returns>
IVideoStream SetOutputFramesCount(int number);
/// <summary>
///     Seeks in input file to position. (-ss argument)
/// </summary>
/// <param name="seek">Position</param>
/// <returns>IVideoStream</returns>
IVideoStream SetSeek(TimeSpan seek);
/// <summary>
///     Burn subtitle into file
/// </summary>
/// <param name="subtitlePath">Path to subtitle file in .srt format</param>
/// <param name="encode">Set subtitles input character encoding. Only useful if not UTF-8.</param>
/// <param name="style">
///     Override default style or script info parameters of the subtitles. It accepts a string containing
///     ASS style format KEY=VALUE couples separated by ","
/// </param>
/// <returns>IVideoStream</returns>
IVideoStream AddSubtitles(string subtitlePath, string encode = null, string style = null);
/// <summary>
///     Burn subtitle into file
/// </summary>
/// <param name="subtitlePath">Path to subtitle file in .srt format</param>
/// <param name="encode">Set subtitles input character encoding. Only useful if not UTF-8.</param>
/// <param name="style">
///     Override default style or script info parameters of the subtitles. It accepts a string containing
///     ASS style format KEY=VALUE couples separated by ","
/// </param>
/// <param name="originalSize">
///     Specify the size of the original video, the video for which the ASS style was composed. This
///     is necessary to correctly scale the fonts if the aspect ratio has been changed.
/// </param>
/// <returns>IVideoStream</returns>
IVideoStream AddSubtitles(string subtitlePath, VideoSize originalSize, string encode = null, string style = null);
/// <summary>
///     Get part of video
/// </summary>
/// <param name="startTime">Start point</param>
/// <param name="duration">Duration of new video</param>
/// <returns>IVideoStream</returns>
IVideoStream Split(TimeSpan startTime, TimeSpan duration);
/// <summary>
///     Set filter
/// </summary>
/// <param name="filter">Filter</param>
/// <returns>IVideoStream</returns>
IVideoStream SetBitstreamFilter(string filter);
/// <summary>
/// Sets the format for the input file using the -f option before the input file name
/// </summary>
/// <param name="inputFormat">The input format to set</param>
/// <returns>IConversion object</returns>
IVideoStream SetInputFormat(string inputFormat);
/// <summary>
/// Sets the format for the input file using the -f option before the input file name
/// </summary>
/// <param name="inputFormat">The input format to set</param>
/// <returns>IConversion object</returns>
IVideoStream SetInputFormat(Format inputFormat);
/// <summary>
///     "-re" parameter. Read input at native frame rate. Mainly used to simulate a grab device, or live input stream (e.g. when reading from a file). Should not be used with actual grab devices or live input streams (where it can cause packet loss). By default ffmpeg attempts to read the input(s) as fast as possible. This option will slow down the reading of the input(s) to the native frame rate of the input(s). It is useful for real-time output (e.g. live streaming).
/// </summary>
/// <param name="readInputAtNativeFrameRate">Read input at native frame rate. False set parameter to default value.</param>
/// <returns>IConversion object</returns>
IVideoStream UseNativeInputRead(bool readInputAtNativeFrameRate);
/// <summary>
///     "-stream_loop" parameter. Set number of times input stream shall be looped. 
/// </summary>
/// <param name="loopCount">Loop 0 means no loop, loop -1 means infinite loop.</param>
/// <returns>IConversion object</returns>
IVideoStream SetStreamLoop(int loopCount);