VideoFrameReader Class

Reads a video frame by frame, also allows seeking and provides info on the video.

Definition

Namespace: GleamTech.VideoUltimate
Assembly: GleamTech.VideoUltimate (in GleamTech.VideoUltimate.dll) Version: 3.8.6
C#
public class VideoFrameReader : IDisposable, 
	IEnumerable<Image>, IEnumerable
Inheritance
Object    VideoFrameReader
Implements
IEnumerableImage, IEnumerable, IDisposable

Example

C#
//Read video from "c:\SomeFolder\InputFile.mp4"
using (var videoFrameReader = new VideoFrameReader(@"c:\SomeFolder\InputFile.mp4"))
{
}

//---------------------------------------

//Read with a virtual path string:
//See below for other path string examples.
using (var videoFrameReader = new VideoFrameReader("~/SomeFolder/InputFile.mp4"))
{
}

//Read with a URL string:
//See below for other path string examples.
using (var videoFrameReader = new VideoFrameReader("http://example.com/SomeFolder/InputFile.mp4"))
{
}

//Read with a Data URL string:
//See below for other path string examples.
using (var videoFrameReader = new VideoFrameReader("data:image/gif;base64,R0lGODlhAQABAIAAAAAAAP///yH5BAEAAAAALAAAAAABAAEAAAIBRAA7"))
{
}

//Read with a file provider instance:
//See below for other file provider examples (UNC Path, AmazonS3, AzureBlob, Database etc.).
var fileProvider = new FileSystemFileProvider
{
    File = "InputFile.mp4",
    Location = new PhysicalLocation
    {
        Path = @"c:\SomeFolder"
    }
};
using (var videoFrameReader = new VideoFrameReader(fileProvider))
{
}

//Read with a provider string:
//See below for other provider string examples (UNC Path, AmazonS3, AzureBlob, Database etc.).
using (var videoFrameReader = new VideoFrameReader(@"Type=FileSystem; File=InputFile.mp4; Location='Type=Physical; Path=c:\SomeFolder'"))
{
}

Read first frame from a video file and save it as an image file:

C#
using (var videoFrameReader = new VideoFrameReader(@"C:\Video.mp4"))
{
    if (videoFrameReader.Read()) //Only if frame was read successfully
    {
        //Get a System.Drawing.Bitmap for the current frame
        //You are responsible for disposing the bitmap when you are finished with it.
        //So it's good practice to have a "using" statement for the retrieved bitmap.
        using (var frame = videoFrameReader.GetFrame())
            //Reference System.Drawing and use System.Drawing.Imaging namespace for the following line.
            frame.Save(@"C:\Frame1.jpg", ImageFormat.Jpg);
    }
}

Read a video file from a stream:

C#
using (Stream videoStream = OpenYourVideoStream())
using (var videoFrameReader = new VideoFrameReader(videoStream))
{
    //Process..
}

Loop through all frames of a video file:

C#
using (var videoFrameReader = new VideoFrameReader(@"C:\Video.mp4"))
{
    while (videoFrameReader.Read())
    {
        //Do something with current frame
    }
}

Loop through all frame bitmaps of a video file. This combines Read and GetFrame method calls:

C#
using (var videoFrameReader = new VideoFrameReader(@"C:\Video.mp4"))
{
    foreach (var frame in videoFrameReader)
    {
        using (frame)
        {
            //Do something with current frame bitmap
        }
    }
}

Seek to the middle of a video file:

C#
using (var videoFrameReader = new VideoFrameReader(@"C:\Video.mp4"))
{
    videoFrameReader.Seek(videoFrameReader.Duration.TotalSeconds / 2);

    if (videoFrameReader.Read())
        Console.WriteLine("Seeked Frame Number: " + videoFrameReader.CurrentFrameNumber);
    else
        Console.WriteLine("Frame read failed!");
}

Retrieve info or metadata of a video file:

C#
using (var videoFrameReader = new VideoFrameReader(@"C:\Video.mp4"))
{
    Console.WriteLine("Info:");
    Console.WriteLine("----------------------------");
    Console.WriteLine("Duration: " + videoFrameReader.Duration);
    Console.WriteLine("Width: " + videoFrameReader.Width);
    Console.WriteLine("Height: " + videoFrameReader.Height);
    Console.WriteLine("CodecName: " + videoFrameReader.CodecName);
    Console.WriteLine("CodecDescription: " + videoFrameReader.CodecDescription);
    Console.WriteLine("CodecTag: " + videoFrameReader.CodecTag);
    Console.WriteLine("BitRate: " + videoFrameReader.BitRate);
    Console.WriteLine("FrameRate: " + videoFrameReader.FrameRate);

    Console.WriteLine();
    Console.WriteLine("Metadata:");
    Console.WriteLine("----------------------------");
    foreach (var entry in videoFrameReader.Metadata)
    {
        Console.WriteLine("Key: " + entry.Key);
        Console.WriteLine("Value: " + entry.Value);
        Console.WriteLine();
    }
}

Get the first non-blank frame of a video file:

C#
using (var videoFrameReader = new VideoFrameReader(@"C:\Video.mp4"))
{
    var attempts = 0;

    //Loop through frames but limit to first 20 times
    while (videoFrameReader.Read() && attempts++ < 20)
    {
        //Skip first 3 seconds (e.g. possible logo intro) if video is longer than 5 seconds
        if (videoFrameReader.Duration.TotalSeconds > 5)
            videoFrameReader.Seek(3);

        using (var frame = videoFrameReader.GetFrame())
        {
            //IsBlank is our useful extension method for System.Drawing.Bitmap
            //The tolerance parameter determines the image blankness.
            //Higher the value higher the number of matches. 
            //Default value is 1 which means image must be very blank to return true. 
            //For example 5 can be used for a frame with a logo only to be detected as blank. 
            if (!frame.IsBlank(5))
            {
                frame.Save(@"C:\NonBlankFrame.jpg", ImageFormat.Jpg);
                break;
            }
        }
    }
}

  Notes to Callers

Below are the examples for setting a FileProvider parameter/property.

Setting a plain string:

C#
FileProvider fileProvider;

//Setting a physical/virtual path string:
//These strings are parsed as a FileSystemFileProvider instance with a PhysicalLocation instance.
fileProvider = @"c:\SomeFolder\SomeFile.ext";
//Note that virtual paths can only be resolved in a web application
//and on Linux paths starting with "/" are physical paths and not virtual paths.
fileProvider = "/SomeFolder/SomeFile.ext";
fileProvider = "~/SomeFolder/SomeFile.ext"; //"~" means relative to web application root.

//Setting a URL or a Data URL string:
//Strings starting with "http://" or "https://" are parsed as a UrlFileProvider instance.
//Strings starting with "data:" are parsed as a DataUrlFileProvider instance.
fileProvider = "http://example.com/SomeFolder/SomeFile.ext";
fileProvider = "data:image/gif;base64,R0lGODlhAQABAIAAAAAAAP///yH5BAEAAAAALAAAAAABAAEAAAIBRAA7";

Setting a MemoryFileProvider instance, to connect to a file in a byte array (byte) or a MemoryStream:

C#
FileProvider fileProvider;

//Setting a MemoryFileProvider instance,
//to connect to a file in a byte array (byte[]) or a MemoryStream:
//Optional parameter dateModified: used for detailed file info, e.g. for generating better cache keys.
fileProvider = new MemoryFileProvider(
    "SomeFile.ext", //file can also be set as a relative path "SomeFolder/SomeFile.ext".
    yourByteArray,
    yourFileDateModified //Provide dateModified to prevent cache key conflicts.
);
fileProvider = new MemoryFileProvider(
    "SomeFile.ext", //file can also be set as a relative path "SomeFolder/SomeFile.ext".
    yourMemoryStream,
    yourFileDateModified //Provide dateModified to prevent cache key conflicts.
);

//Create with empty MemoryStream
//Note that this instance should be written (filled with data via OpenWrite method) before being read
fileProvider = new MemoryFileProvider("SomeFolder/SomeFile.ext");

Setting a StreamFileProvider instance, to connect to a file in a Stream:

C#
FileProvider fileProvider;

//Setting a StreamFileProvider instance,
//to connect to a file in a Stream:
//Optional parameters dateModified and size: used for detailed file info, e.g. for generating better cache keys.
fileProvider = new StreamFileProvider(
    "SomeFile.ext", //file can also be set as a relative path "SomeFolder/SomeFile.ext".
    yourStream,
    yourFileDateModified, //Provide dateModified to prevent cache key conflicts.
    yourFileSize //Provide size only if your stream is not seekable to prevent cache key conflicts.
);

Setting a FileSystemFileProvider instance with a PhysicalLocation instance, to connect to physical file system:

C#
FileProvider fileProvider;

//Setting a physical file provider via a FileSystemFileProvider instance:
fileProvider = new FileSystemFileProvider
{
    File = "SomeFile.ext",
    Location = new PhysicalLocation
    {
        //Path can also be virtual path string like "~/SomeFolder" in a web application.
        Path = @"c:\SomeFolder"
    }
};

//Setting a physical file provider via a provider string (same as above):
//In a provider string, if a value contains semi-colon character, that value should be enclosed
//in single quotes (eg. Password='PASS;WORD') or double quotes (eg. Password="PASS;WORD").
fileProvider = @"Type=FileSystem; File=SomeFile.ext; Location='Type=Physical; Path=c:\SomeFolder'";

//---------------------------------------

//Setting a FileSystemFileProvider instance with a PhysicalLocation instance,
//to connect as a specific Windows user to a UNC path or a protected local path:
//UserName can be specified as "Domain\User", "User@Domain" (UPN format), "Machine\User", "User" (local user).
fileProvider = new FileSystemFileProvider
{
    File = "SomeFile.ext",
    Location = new PhysicalLocation
    {
        Path = @"\\server\share", //Path can be a UNC path or a local path
        UserName = "USERNAME",
        Password = "PASSWORD"
    }
};

//Setting a physical file provider via a provider string, to connect as a specific user (same as above):
//In a provider string, if a value contains semi-colon character, that value should be enclosed
//in single quotes (eg. Password='PASS;WORD') or double quotes (eg. Password="PASS;WORD").
fileProvider = @"Type=FileSystem; File=SomeFile.ext; Location='Path=\\server\share; User Name=USERNAME; Password=PASSWORD'";

//---------------------------------------

//Setting a physical file provider via a FileSystemFileProvider instance, to connect as the authenticated user:
//If Windows Authentication is used in IIS for this site, location can be specified like this
//to connect as the already authenticated user: 
fileProvider = new FileSystemFileProvider
{
    File = "SomeFile.ext",
    Location = new PhysicalLocation
    {
        Path = @"\\server\share", //Path can be a UNC path or a local path
        AuthenticatedUser = AuthenticatedUser.Windows
    }
};

//Setting a physical file provider via a provider string, to connect as the authenticated user:
fileProvider = @"Type=FileSystem; File=SomeFile.ext; Location='Path=\\server\share; Authenticated User=Windows'";

Setting a FileSystemFileProvider instance with an AzureBlobLocation instance, to connect to Azure Blob cloud file system:

C#
FileProvider fileProvider;

//Setting a FileSystemFileProvider instance with an AzureBlobLocation instance,
//to connect to Azure Blob cloud file system.
fileProvider = new FileSystemFileProvider
{
    File = "SomeFile.ext",
    Location = new AzureBlobLocation
    {
        //Leave Path empty to connect to the root of the container. 
        //For connecting to subfolders, Path should be specified as a relative path (eg. "some/folder")
        //Path = "some/folder",

        //Get these values from your Azure Portal (Storage Account -> Access Keys -> Connection String)
        Container = "CONTAINER",
        AccountName = "XXX",
        AccountKey = "XXX"
    }
};

//Setting a an Azure Blob file provider via a provider string (same as above):
//In a provider string, if a value contains semi-colon character, that value should be enclosed
//in single quotes (eg. Password='PASS;WORD') or double quotes (eg. Password="PASS;WORD").
fileProvider = @"Type=FileSystem; File=SomeFile.ext; Location='Type=AzureBlob; Container=CONTAINER; Account Name=XXX; Account Key=XXX'";

Setting a FileSystemFileProvider instance with an AmazonS3Location instance, to connect to Amazon S3 cloud file system:

C#
FileProvider fileProvider;

//Setting a FileSystemFileProvider instance with an AmazonS3Location instance,
//to connect to Amazon S3 cloud file system.
fileProvider = new FileSystemFileProvider
{
    File = "SomeFile.ext",
    Location = new AmazonS3Location
    {
        //Leave Path empty to connect to the root of the bucket. 
        //For connecting to subfolders, Path should be specified as a relative path (eg. "some/folder")
        //Path = "some/folder",

        BucketName = "BUCKET",
        Region = "eu-central-1",
        AccessKeyId = "XXX",
        SecretAccessKey = "XXX",
    }
};

//Setting an Amazon S3 file provider via a provider string (same as above):
//In a provider string, if a value contains semi-colon character, that value should be enclosed
//in single quotes (eg. Password='PASS;WORD') or double quotes (eg. Password="PASS;WORD").
fileProvider = @"Type=FileSystem; File=SomeFile.ext; Location='Type=AmazonS3; Bucket Name=BUCKET; Region=eu-central-1; Access Key Id=XXX; Secret Access Key=XXX'";

Setting a UrlFileProvider instance, to connect to a file located at a URL:

C#
FileProvider fileProvider;

//Setting a URL file provider via a UrlFileProvider instance:
//File should start with "http://" or "https://".
fileProvider = new UrlFileProvider
{
    File = "http://example.com/SomeFolder/SomeFile.ext"
};

//Setting a URL file provider via a provider string (same as above):
fileProvider = "Type=Url; File=http://example.com/SomeFolder/SomeFile.ext";

Setting a DataUrlFileProvider instance, to connect to a file encoded in a Data URL:

C#
FileProvider fileProvider;

//Setting a Data URL file provider via a UrlFileProvider instance:
//File should start with "data:".
fileProvider = new DataUrlFileProvider
{
    File = "data:image/gif;base64,R0lGODlhAQABAIAAAAAAAP///yH5BAEAAAAALAAAAAABAAEAAAIBRAA7"
};

//Setting a Data URL file provider via a provider string (same as above):
fileProvider = "Type=DataUrl; File='data:image/gif;base64,R0lGODlhAQABAIAAAAAAAP///yH5BAEAAAAALAAAAAABAAEAAAIBRAA7'";

Setting a DatabaseFileProvider instance, to connect to a database file system:

C#
FileProvider fileProvider;

//Setting a DatabaseFileProvider instance,
//to connect to a database file system.
fileProvider = new DatabaseFileProvider
{
    File = "SomeFile.ext", //File can also be set as a relative path "SomeFolder/SomeFile.ext".
    ConnectionString = "Data Source=(local); Initial Catalog=SomeDb; Integrated Security=SSPI",
    //ProviderName = "System.Data.SqlClient" //ProviderName default value is "System.Data.SqlClient"

    Table = "SomeTable", //Table default value is "File".

    //Mandatory fields:
    KeyField = "Path", //KeyField default value is "Id".
    ContentField = "Content", //ContentField default value is "Content".

    //Optional fields DateModifiedField and SizeField: used for detailed file info, e.g. for generating better cache keys.
    //NameField = "Name", //NameField used for overriding file name specified in File.
    DateModifiedField = "DateModified", //Provide DateModifiedField to prevent cache key conflicts.
    SizeField = "Size" //Provide SizeField to prevent cache key conflicts.
};

//Setting a database file provider via a provider string (same as above):
//In a provider string, if a value contains semi-colon character, that value should be enclosed
//in single quotes (eg. Password='PASS;WORD') or double quotes (eg. Password="PASS;WORD").
fileProvider = "Type=Database; File=SomeFolder/SomeFile.ext; Connection String='Data Source=(local); Initial Catalog=SomeDb; Integrated Security=SSPI'; Table=SomeTable; Key Field=Path; Content Field=Content";

//---------------------------------------

/*

Sample SQL script to create a table in the database:

CREATE TABLE [File] (
    [Id] [int] IDENTITY(1, 1) PRIMARY KEY,
    [Path] [nvarchar](500) NOT NULL UNIQUE,
    [Name] [nvarchar](100),
    [DateModified] [smalldatetime],
    [Size] [bigint],
    [Content] [varbinary](max)
);

*
*/

Setting a AssemblyResourceFileProvider instance, to connect to a file embedded in an assembly:

C#
FileProvider fileProvider;

//Setting an assembly resource file provider via a AssemblyResourceFileProvider instance:
fileProvider = new AssemblyResourceFileProvider
{
    File = @"SomeFolder\SomeFile.ext",
    Assembly = typeof(SomeType).Assembly,
    BaseNamespace = typeof(SomeType).Namespace
};

//Setting an assembly file provider via a provider string (same as above):
fileProvider = @"Type=AssemblyResource; File=SomeFolder\SomeFile.ext; Assembly=SomeAssembly; Base Namespace=Some.Namespace";

Setting a TemporaryFileProvider instance, to connect to a temporary file:

C#
FileProvider fileProvider;

//Setting a temporary file provider via a TemporaryFileProvider instance:
//Note that this instance should be written (filled with data via OpenWrite method) before being read
fileProvider = new TemporaryFileProvider("SomeFolder/SomeFile.ext");

Setting and implementing a custom file provider:

C#
FileProvider fileProvider;

//Setting a custom file provider:
fileProvider = new CustomFileProvider
{
    File = @"SomeFolder\SomeFile.ext",
    Parameters = new Dictionary<string, string>
    {
        {"parameter1", "value1"}
    }
};
C#
public class CustomFileProvider: FileProvider
{
    public override string File { get; set; }

    //Return true if DoGetInfo method is implemented, and false if not.
    public override bool CanGetInfo => true;

    //Return true if DoOpenRead method is implemented, and false if not.
    public override bool CanOpenRead => true;

    //Return true if DoOpenWrite method is implemented, and false if not.
    public override bool CanOpenWrite => false;

    //Return true only if File identifier is usable across processes/machines.
    public override bool CanSerialize => false;

    protected override FileProviderInfo DoGetInfo()
    {
        //Return info here which corresponds to the identifier in File property.

        //When this file provider is used in DocumentViewer:
        //This method will be called every time DocumentViewer requests a document.
        //The cache key and document format will be determined according to the info you return here.

        string fileName = File;
        DateTime dateModified = DateTime.Now;
        long size = 81920;

        return new FileProviderInfo(fileName, dateModified, size);

        //throw new NotImplementedException();
    }

    protected override Stream DoOpenRead()
    {
        //Open and return a readable stream here which corresponds to the identifier in File property.

        //You can make use of Parameters dictionary which was passed when this provider was initialized.
        //var someParameter = Parameters["parameter1"];

        //When this file provider is used in DocumentViewer:
        //This method will be called only when original input document is required, 
        //For example if DocumentViewer already did the required conversions and cached the results, 
        //it will not be called.

        return readableStream;

        //throw new NotImplementedException();
    }

    protected override Stream DoOpenWrite()
    {
        //Open and return a writable stream here which corresponds to the identifier in File property.

        throw new NotImplementedException();
    }
}

Constructors

VideoFrameReader(FileProvider, VideoUltimateConfiguration) Initializes a new instance of the VideoFrameReader class from the specified video file.
VideoFrameReader(Stream, VideoUltimateConfiguration) Initializes a new instance of the VideoFrameReader class from the specified video stream.

Properties

BitRateGets the average bitrate of the video in kbps.
CodecDescription Gets the descriptive name of the codec used in the video, meant to be more human readable than name.
CodecNameGets the name of the codec used in the video.
CodecTagGets the tag of the codec used in the video, also known as FourCC code.
CurrentFrameNumber Gets the coded picture number of the current frame. Note that this number may be occasionally in wrong order because it is in the coded order, not in the display order. So if you are reading a video from beginning to the end, you may also use a separate variable incremented in your loop.
DurationGets the duration of the video.
FrameRateGets the frame rate of the video, expressed in frames per second (FPS).
HeightGets the height of the video in pixels.
MetadataGets a dictionary representing metadata stored in the video.
WidthGets the width of the video in pixels.

Methods

DisposeReleases all resources used by this instance.
GetEnumerator Returns an enumerator that iterates through the frames in the video.
GetFrame Gets the frame at current position as Image. Every call returns a new Image instance which should be disposed by the caller.
Read Reads and decodes the next frame from the video. If successful, then GetFrame can be called to get a Image instance.
Seek(Double)Seeks the video to the given time position in seconds.
Seek(TimeSpan)Seeks the video to the given time position in seconds.
SetFrameHeight Set the frame height to be used for Image instances returned by GetFrame. The width will be automatically calculated according to the video aspect ratio. This method can be called if a different frame size is required than the original video frame size.
SetFrameSize(Int32) Set the frame size to be used for Image instances returned by GetFrame. This method can be called if a different frame size is required than the original video frame size.
SetFrameSize(Int32, Int32) Set the frame size to be used for Image instances returned by GetFrame. This method can be called if a different frame size is required than the original video frame size.
SetFrameWidth Set the frame width to be used for Image instances returned by GetFrame. The height will be automatically calculated according to the video aspect ratio. This method can be called if a different frame size is required than the original video frame size.

See Also