Showing posts with label Expression Encoder. Show all posts
Showing posts with label Expression Encoder. Show all posts

Wednesday, November 9, 2011

How To: Create A Thumbnail Image From A Video Using The Microsoft Expression Encoder SDK

In the modern day of the web, video players of all sorts of technology are being used from Flash, Windows Media Player, Silverlight, HTML, and many more. Commonly we will use a preview image (like seen on YouTube for example) to give a still image of what the video visually represents. You can accomplish the creation of this video thumbnail dynamically in .NET using the Expression Encoder SDK.

The idea is to load a video into a 'AudioVideoFile' object and then create a still image file based on a provided interval within the video. This gives managing video thumbnails a hands-off approach to creation saving a lot of time as opposed to someone needing to manually create this file from the Encoder product directly. Using the right naming convention, once created you could just load the thumbnail into your video player automatically without ever needing to touch the video.

To being you need to install Microsoft Expression Encoder and applicable service packs. As of this post the current version is Expression Encoder 4 SP2. The Expression Encoder 4 SDK and the documents are installed with the application. You can access the SDK from the Start menu by clicking All Programs and then clicking Microsoft Expression. The links below have the installations needed:

Microsoft Expression Encoder 4

Microsoft Expression Encoder 4 SP2

This method of creating a thumbnail is best suited for a WCF service or directly within a ASP.NET web application because of the required Encoder components. It must be installed on each server or machine where the code is ran. Therefore unless you have a limited user base, this may not work well within a WinForms or WPF application. In this case porting the functionality to a WCF service and having the remote applications call it to create the thumbnail would work best. This reduces the locations where the components need installed.

An interesting fact is you need the full version of Expression Encoder installed on the machine or server that has the code to generate the thumbnails, but you never actually need to open or use the Encoder product itself. In the past, I did have success installing a trial version of Encoder and having the code continue to run successfully with the SDK, but you will need to confirm or deny this independently. The SDK alone is not enough to allow the code to work; it relies on the Expression Encoder product being installed. For the purposes of this code here, you never actually have to open Expression Encoder.

After you have Expression Encoder, any current service packs, and the SDK installed you are ready to being. I recommend just making a little test harness in a web app or WPF app locally to see how it works. Then you can port it out to a service or in an actually application.

To being add the following references to your application from the following location (assuming you are using the Expression Encoder 4 SDK) "C:\Program Files\Microsoft Expression\Encoder 4\SDK\":

Now add the following 'Imports' or 'using' statements to your code:
Imports System.IO
Imports System.Drawing
Imports System.Drawing.Imaging
Imports Microsoft.Expression.Encoder
Next let's make a method named 'GenerateVideoThumbnailImage' that takes some input parameters about the location of the video, the size of the thumbnail to generate, and the path to save the generated thumbnail image. The code below shows using the Expression Encoder SDK to generate the thumbnail:
Private Sub CreateVideoThumnailImage(ByVal VideoPath As String,
ByVal SecondIntervalForThumbCapture As Integer,
ByVal ThumbnailWidth As Integer,
ByVal ThumbnailHeight As Integer,
ByVal ThumbnailSavePath As String)

'Create the AudioVideoFile object which stems from the Expression Encoder SDK .dlls
Dim avFile As New AudioVideoFile(VideoPath)

'Create a value equal to the length of the video
Dim FileDuration As Double = avFile.Duration.TotalSeconds
'Set thumbnail value to second interval indicated by argument passed in:
Dim ThumbnailLocation As Double = SecondIntervalForThumbCapture

'If the interval passed in is at a location longer than the video, then redefine an interval to the mid-point of the video.
If ThumbnailLocation > FileDuration Then
ThumbnailLocation = (FileDuration / 2)
End If

'Create the formatted filename to append on to the VideoFile (Format = "VideoFileName_thumb.png")
'Note: You can change this logic to be a passed in value or whatever you would like. This is not critical to generating the thumbnail image.
Dim FormattedFileName As String = Path.GetFileName(VideoPath)
'Strip off the video file extension and add an "_thumb" and the format extension (.Png will be used) to be saved to.
FormattedFileName = Path.GetFileNameWithoutExtension(FormattedFileName)
FormattedFileName += "_thumb." & ImageFormat.Png.ToString().ToLower()

'Create ThumbnailGenerator object to get thumbs from AudioVideoFile. Use the Width and Height arguments passed in to determine the size to Save.
Dim ThumbnailImageGenerator As Microsoft.Expression.Encoder.ThumbnailGenerator = avFile.CreateThumbnailGenerator(New System.Drawing.Size(ThumbnailWidth, ThumbnailHeight))
'Create the thumbnail image based on interval set above
Dim ThumbnailImage As Bitmap = ThumbnailImageGenerator.CreateThumbnail(TimeSpan.FromSeconds(ThumbnailLocation))
'Save the file to the ThumbnailSavePath argument passed in with the formatted file name (above) added:
ThumbnailImage.Save(ThumbnailSavePath & FormattedFileName, ImageFormat.Png)

'Clean up
ThumbnailImage.Dispose()
ThumbnailImageGenerator.Dispose()

End Sub
Here is a sample call to the above method that will output "MyVideo_thumb.png":
'Make a call to generate a thumbnail of the video at the '10' second interval (size will be 150x150) and save it to the same directory:
CreateVideoThumnailImage("C:\Videos\MyVideo.wmv", 10, 150, 150, "C:\Videos\")
Previously I have used the 'MediaItem' object and its 'GetThumbnail' method within the SDK to generate the thumbnail. I had success using this on Windows Server 2003 and the Encoder 2 SDK, but could *never* get it to work on Windows Server 2008 with either the Encoder 2 or Encoder 4 SDK. It works so long as the code is directly run within your application, but if you try to port it out to a service (i.e. WCF) regardless of the hosting type (IIS or Windows Service) and regardless of the user context (Administrator), the service would always throw the following exception:

"Microsoft.Expression.Encoder.InvalidMediaFileException: File type isn't supported. ---> Microsoft.Expression.Encoder.UnableToAnalyzeFileException: Exception from HRESULT: 0x80040218"

I had a lengthy MSDN post that was never resolved and can be read about here, but my strong recommendation is to port any use of the 'MediaItem' object over to using a 'AudioVideoFile' object. There seemed to be some underlying caching of credentials or some other oddity with trying to load the video file into the MediaItem constructor that I could never get to work properly. However with the code above, I can successfully implement it in a WCF service hosted by IIS or as a Windows Service. Just make sure to run the app pool hosting the IIS site or Windows Service under the LocalSystem or other Administrator account to make sure the service has the proper permissions.

Lastly, you may run into issues if you try and generate a thumbnail image from a video in which your machine does not have the codec installed. For information on this, please see one of my older posts that is listed below:

Fixing the "File type isn't supported" Error When Working With Expression Encoder SDK

Sunday, July 11, 2010

Fixing the "File type isn't supported" Error When Working With Expression Encoder SDK

Recently I had trouble on a Windows 7 Ultimate Machine with Expression Encoder 4 installed with a "File type isn't supported" error being returned when programming against the SDK. Upon creating an instance of the MediaItem object, the exception was thrown. It turns out even with Win7 ultimate, EE4, and Windows Media Player 11 installed I was still missing some codecs. I downloaded a robust codec pack from the link below and it solved the issues. Microsoft also offers a codec package for older versions of Windows Media Player, but to make sure I had no more issues I installed the larger free package offered from CNet. Once the additional codecs were installed, the code continued to work perfectly. Remember as well, if this code is in a service or .dll, make sure those codecs are in place on machine or server where deployed as well, to prevent the "Well it works on my machine, but not the server..." kind of issue.

Media Player Codec Pack

Codec Installation Package for Windows Media Player 7.1 and later