5
\$\begingroup\$

I wrote a simple, yet disgusting video thumbnail image generator method—which uses the MediaToolkit .NET library.

The code is not self-explanatory whatsoever, and it's extremely inefficient.

It accepts a video byte array & MIME type—and writes it to a video file. Then, it obtains the video file's duration, stores the middle frame, and writes it to an image file. Finally, it retrieves the image file bytes and returns them ... after deleting the video & image file.

How can I make it more efficient?

    public static byte[] GetVideoThumbnail(byte[] bytes, string mediaType)
    {
        var video = new MediaFile
        {
            Filename = Path.GetTempPath() + Guid.NewGuid() + MimeTypeMap.GetExtension(mediaType)
        };
        var image = new MediaFile { Filename = Path.GetTempPath() + Guid.NewGuid() + ".jpg" };
        File.WriteAllBytes(video.Filename, bytes);
        using (var engine = new Engine())
        {
            engine.GetMetadata(video);
            engine.GetThumbnail(video, image,
                new ConversionOptions { Seek = TimeSpan.FromSeconds(video.Metadata.Duration.TotalSeconds / 2) });
        }
        var thumbnail = File.ReadAllBytes(image.Filename);
        File.Delete(video.Filename);
        File.Delete(image.Filename);
        return thumbnail;
    }
\$\endgroup\$
  • 1
    \$\begingroup\$ Have you read answers in this SO post ? stackoverflow.com/questions/15702031/… especially answer withFFMpeg usage ? Problems and inefficient of your code is caused by MediaToolkit. \$\endgroup\$ – Aram Kocharyan Oct 9 '17 at 10:44
  • \$\begingroup\$ @AramKocharyan FFmpeg is even more inefficient for doing this than MediaToolkit is. \$\endgroup\$ – Owen Oct 12 '17 at 1:23
  • \$\begingroup\$ What is inefficient here ? nrecosite.com/video_converter_net.aspx \$\endgroup\$ – Aram Kocharyan Oct 12 '17 at 10:31
  • \$\begingroup\$ Have you tried to use asynchronous operations? I have no experience whatsoever with MediaToolkit, but from what I can see you can run var image = new MediaFile { Filename = Path.GetTempPath() + Guid.NewGuid() + ".jpg" };, File.WriteAllBytes(video.Filename, bytes); and other read/write/delete operations in new threads. \$\endgroup\$ – Gentian Kasa Oct 12 '17 at 15:49
  • \$\begingroup\$ @AramKocharyan I'll look into NReco right now. I found it last week and dismissed it. \$\endgroup\$ – Owen Oct 12 '17 at 16:03
3
\$\begingroup\$

The most inefficient thing in your code is usage of byte[] to hold video or image data. There is a concept of Large Object Heap in .NET which is not compacted unless explicitly otherwise made-to starting .Net 4.5.1.

Red Gate's Explanation of Large Object Heap

Latest behavior of Large Object Heap

All your objects with a size of more that 85000 bytes are allocated on large object heap. These are not collected like mentioned in .Net garbage collection and dealt with separately. You can read better in the links above.

As a sidenote, You can cross-check if you do need engine.GetMetadata(video); to generate the thumbnail.

The answer to your question would be

  1. Like you are returning image as a byte array, you can choose to return a image url from the disk. Some part of byte array will be reduced.

  2. With .net 4.5.1, you can call .net LOH compaction programmatically.

  3. You can also do this processing in completely separate appdomain in memory, and then unloading it.

  4. Or you can generate thumbnails from a completely separate windows service or console application, you simply restart them.

Read few more things on Large Object Heap

\$\endgroup\$
  • \$\begingroup\$ I didn't know about the LOH. Thanks for sharing! \$\endgroup\$ – Owen Oct 15 '17 at 20:14

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.