Video processing is an essential part of many applications, whether you're building a content management system or simply providing video previews for your users. In this DevTip, you'll learn how to automate video thumbnail generation using FFmpeg in .NET. With modern libraries and async programming, you can integrate a robust thumbnail extraction process into your applications.

Setting up FFmpeg and ffmpegcore

First, ensure FFmpeg is installed on your system. You can download it from the official website or use package managers:

  • Windows: winget install ffmpeg
  • macOS: brew install ffmpeg
  • Ubuntu/Debian: apt install ffmpeg

Next, add the FFMpegCore NuGet package to your .NET project:

<PackageReference Include="FFMpegCore" Version="5.2.0" />

Creating a thumbnail generator service

Let's create a service that handles thumbnail generation using FFMpegCore:

using FFMpegCore;
using FFMpegCore.Enums;
using Microsoft.Extensions.Logging;

public class ThumbnailService
{
    private readonly ILogger<ThumbnailService> _logger;

    public ThumbnailService(ILogger<ThumbnailService> logger)
    {
        _logger = logger;
    }

    public async Task<bool> GenerateThumbnailAsync(
        string inputFile,
        string outputFile,
        TimeSpan captureTime,
        int width = 320,
        int height = 240)
    {
        try
        {
            await FFMpegArguments
                .FromFileInput(inputFile)
                .OutputToFile(outputFile, false, options =>
                    options
                        .Seek(captureTime)
                        .WithFrameOutputCount(1)
                        .WithVideoFilters(filterOptions =>
                            filterOptions.Scale(width: width, height: height))
                )
                .ProcessAsynchronously();

            return true;
        }
        catch (FFMpegException ex)
        {
            _logger.LogError(ex, "FFmpeg error while generating thumbnail");
            return false;
        }
        catch (Exception ex)
        {
            _logger.LogError(ex, "Unexpected error while generating thumbnail");
            return false;
        }
    }
}

How the code works

  • The service uses dependency injection for logging
  • FFMpegCore provides a fluent API for configuring FFmpeg commands
  • The -ss seek operation is handled by the Seek method
  • Video scaling is configured through the WithVideoFilters option
  • Proper async/await patterns are implemented
  • Comprehensive error handling with logging is included

Using the thumbnail service

Here's how to use the thumbnail service in a .NET application:

public class Program
{
    public static async Task Main(string[] args)
    {
        using var loggerFactory = LoggerFactory.Create(builder =>
        {
            builder
                .AddConsole()
                .SetMinimumLevel(LogLevel.Information);
        });

        var logger = loggerFactory.CreateLogger<ThumbnailService>();
        var thumbnailService = new ThumbnailService(logger);

        var result = await thumbnailService.GenerateThumbnailAsync(
            inputFile: "sample.mp4",
            outputFile: "thumbnail.jpg",
            captureTime: TimeSpan.FromSeconds(5)
        );

        Console.WriteLine(result
            ? "Thumbnail generated successfully"
            : "Failed to generate thumbnail");
    }
}

Advanced features

The thumbnail service can be extended with additional features:

public class ThumbnailService
{
    // ... existing code ...

    public async Task<IReadOnlyList<string>> GenerateMultipleThumbnailsAsync(
        string inputFile,
        string outputDirectory,
        int count)
    {
        var mediaInfo = await FFProbe.AnalyseAsync(inputFile);
        var duration = mediaInfo.Duration;
        var interval = duration.TotalSeconds / (count + 1);
        var thumbnails = new List<string>();

        for (var i = 1; i <= count; i++)
        {
            var time = TimeSpan.FromSeconds(interval * i);
            var outputFile = Path.Combine(
                outputDirectory,
                $"thumbnail_{i:D2}.jpg"
            );

            if (await GenerateThumbnailAsync(inputFile, outputFile, time))
            {
                thumbnails.Add(outputFile);
            }
        }

        return thumbnails;
    }
}

This extension allows generating multiple thumbnails at evenly spaced intervals throughout the video.

Cross-platform considerations

FFMpegCore automatically handles path differences across operating systems, but ensure FFmpeg is properly installed and accessible in your system's PATH. For containerized environments, include FFmpeg installation in your Dockerfile:

FROM mcr.microsoft.com/dotnet/sdk:8.0
RUN apt-get update && apt-get install -y ffmpeg

Version compatibility

This solution has been tested with:

  • .NET 6.0 or later
  • FFmpeg 4.x or later
  • FFMpegCore 5.2.0

Conclusion

FFMpegCore provides a modern, type-safe way to integrate FFmpeg with .NET applications for video thumbnail generation. This approach offers better error handling, cross-platform support, and async operations compared to direct process calls. For more advanced video processing needs, check out Transloadit's video/thumbs robot, which handles thumbnail generation at scale.

Happy coding!