Share via


Create thumbnail from Video

Question

Wednesday, January 24, 2018 7:32 PM

I want to create 5 thumbnails from a video (at 5 different moment in the video) to let the user choose the thumbnail. I did some search and I didn't find the good way to do that. Can someone help me? Thanks

All replies (13)

Thursday, January 25, 2018 1:24 PM âś…Answered

On iOS you can do this:

public ImageSource GenerateThumbImage(string url, long usecond)
{      
    AVAssetImageGenerator imageGenerator = new AVAssetImageGenerator(AVAsset.FromUrl((new Foundation.NSUrl(url))));
    imageGenerator.AppliesPreferredTrackTransform = true;
    CMTime actualTime;
    NSError error;
    CGImage cgImage = imageGenerator.CopyCGImageAtTime(new CMTime(usecond, 1000000), out actualTime, out error);
    return ImageSource.FromStream(() => new UIImage(cgImage).AsPNG().AsStream());mageSource.FromStream(() => new UIImage(cgImage).AsPNG().AsStream());
}

On Android:

public ImageSource GenerateThumbImage(string url, long usecond)
{   
    MediaMetadataRetriever retriever = new MediaMetadataRetriever();
    retriever.SetDataSource(url, new Dictionary<string, string>());
    Bitmap bitmap = retriever.GetFrameAtTime(usecond);
    if (bitmap != null)
    {
        MemoryStream stream = new MemoryStream();
        bitmap.Compress(Bitmap.CompressFormat.Png, 0, stream);
        byte[] bitmapData = stream.ToArray();
        return ImageSource.FromStream(() => new MemoryStream(bitmapData));
    }
    return null;
}

Friday, January 26, 2018 6:21 PM

@flchaux thank you it's working


Monday, October 1, 2018 4:58 AM

@flchaux said:

On iOS you can do this:

public ImageSource GenerateThumbImage(string url, long usecond) {
AVAssetImageGenerator imageGenerator = new AVAssetImageGenerator(AVAsset.FromUrl((new Foundation.NSUrl(url)))); imageGenerator.AppliesPreferredTrackTransform = true; CMTime actualTime; NSError error; CGImage cgImage = imageGenerator.CopyCGImageAtTime(new CMTime(usecond, 1000000), out actualTime, out error); return ImageSource.FromStream(() => new UIImage(cgImage).AsPNG().AsStream());mageSource.FromStream(() => new UIImage(cgImage).AsPNG().AsStream()); }

On Android:

public ImageSource GenerateThumbImage(string url, long usecond) {
MediaMetadataRetriever retriever = new MediaMetadataRetriever(); retriever.SetDataSource(url, new Dictionary()); Bitmap bitmap = retriever.GetFrameAtTime(usecond); if (bitmap != null) { MemoryStream stream = new MemoryStream(); bitmap.Compress(Bitmap.CompressFormat.Png, 0, stream); byte[] bitmapData = stream.ToArray(); return ImageSource.FromStream(() => new MemoryStream(bitmapData)); } return null; }

It works for iOS but doesn't work for Android. retriever.SetDataSource(url, new Dictionary<string, string>()); makes exception. url like this /storage/emulated/0/Android/data/com.ibase.mtwpublicapp/files/Movies/temp/VID_20180706_005641_1.mp4

Please help me to fix, thanks!


Sunday, October 21, 2018 12:52 PM

@flchaux said:

On iOS you can do this:

public ImageSource GenerateThumbImage(string url, long usecond) {
AVAssetImageGenerator imageGenerator = new AVAssetImageGenerator(AVAsset.FromUrl((new Foundation.NSUrl(url)))); imageGenerator.AppliesPreferredTrackTransform = true; CMTime actualTime; NSError error; CGImage cgImage = imageGenerator.CopyCGImageAtTime(new CMTime(usecond, 1000000), out actualTime, out error); return ImageSource.FromStream(() => new UIImage(cgImage).AsPNG().AsStream());mageSource.FromStream(() => new UIImage(cgImage).AsPNG().AsStream()); }

On Android:

public ImageSource GenerateThumbImage(string url, long usecond) {
MediaMetadataRetriever retriever = new MediaMetadataRetriever(); retriever.SetDataSource(url, new Dictionary()); Bitmap bitmap = retriever.GetFrameAtTime(usecond); if (bitmap != null) { MemoryStream stream = new MemoryStream(); bitmap.Compress(Bitmap.CompressFormat.Png, 0, stream); byte[] bitmapData = stream.ToArray(); return ImageSource.FromStream(() => new MemoryStream(bitmapData)); } return null; }

I have tried this solution but in iOS the image didn't appear


Wednesday, November 7, 2018 7:13 AM

For Android: if file path is => /storage/emulated/0/Download/Sample.mp4 something like that, use => retriever.SetDataSource(url);
instead of => retriever.SetDataSource(url, new Dictionary());


Tuesday, January 8, 2019 12:19 PM

@flchaux please can you tell me how to convert ImageSource returned from each method to a string ( as a file path ).


Thursday, October 31, 2019 12:14 PM

Line: retriever.SetDataSource(url, new Dictionary()); Exception : setDataSource failed: status = 0x80000000' can you tell me why this error occurring


Friday, November 8, 2019 11:57 AM

@flchaux said:

On iOS you can do this:

public ImageSource GenerateThumbImage(string url, long usecond) {
AVAssetImageGenerator imageGenerator = new AVAssetImageGenerator(AVAsset.FromUrl((new Foundation.NSUrl(url)))); imageGenerator.AppliesPreferredTrackTransform = true; CMTime actualTime; NSError error; CGImage cgImage = imageGenerator.CopyCGImageAtTime(new CMTime(usecond, 1000000), out actualTime, out error); return ImageSource.FromStream(() => new UIImage(cgImage).AsPNG().AsStream());mageSource.FromStream(() => new UIImage(cgImage).AsPNG().AsStream()); }

In IOS I am using same code but i want to store the thumbnail in particular location Like "Environment.GetFolderPath(Environment.SpecialFolder.MyDocuments)" how can i do this .

please give some suggestions

    UIImage uIImage = UIImage.FromImage(cgImage);
             var img = uIImage.AsPNG().AsStream();

                Byte[] mybytes = new Byte[img.Length];
                var videos = Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.MyDocuments)+ "/" + fileName);
                System.IO.File.WriteAllBytes(videos, mybytes); 

I do like this but it is not working


Monday, December 9, 2019 9:16 PM

@flchaux It doesn't work for IOS 13 devices. I'm getting a null object (cgImage) back. Do you know a solution for this problem?


Tuesday, January 28, 2020 5:09 AM

iOS here

public ImageSource ExecuteCommand(string url, long usecond) { var asset = AVAsset.FromUrl(NSUrl.FromFilename(url)); var imageGenerator = AVAssetImageGenerator.FromAsset(asset); imageGenerator.AppliesPreferredTrackTransform = true; var actualTime = asset.Duration; CoreMedia.CMTime cmTime = new CoreMedia.CMTime(usecond, 1000000); NSError error; var cgImage= imageGenerator.CopyCGImageAtTime(cmTime, out actualTime, out error); return ImageSource.FromStream(() => new UIImage(cgImage).AsPNG().AsStream()); }


Wednesday, February 26, 2020 11:14 PM

For iOS, I use PHCachingImageManager

PHAsset videoAsset;
...
readonly PHCachingImageManager imageManager = new PHCachingImageManager();

var thumbnailFilePath = Path.Combine(cachePath, filename);
                if (!File.Exists(thumbnailFilePath))
                {   // if can't find thumbnail, request it
                    //Console.WriteLine("not exist: {0}", thumbnailFilePath);
                    imageManager.RequestImageForAsset(videoAsset, thumbnailSize, PHImageContentMode.AspectFill, null, (image, info) =>
                    {
                        if (image != null)
                        {
                            File.WriteAllBytes(thumbnailFilePath, image.AsPNG().ToArray());
                        }
                    });
                }

Thursday, August 13, 2020 12:10 PM

For Android retriever.SetDataSource(url); retriever.SetDataSource(url, new Dictionary());

These two didn't work with me


Thursday, August 20, 2020 12:28 AM

Thank you at @junnn @flchaux these two worked for me with minor modifications:

iOS - haven't tested it yet.

public Stream GenerateThumbImage(string filePath, long millisecond) { var asset = AVAsset.FromUrl(NSUrl.FromFilename(filePath)); var imageGenerator = AVAssetImageGenerator.FromAsset(asset); imageGenerator.AppliesPreferredTrackTransform = true; var actualTime = asset.Duration; CoreMedia.CMTime cmTime = new CoreMedia.CMTime(millisecond, 1000000); NSError error; var cgImage = imageGenerator.CopyCGImageAtTime(cmTime, out actualTime, out error); return new UIImage(cgImage).AsJPEG().AsStream(); }

Android public System.IO.Stream GenerateThumbImage(string filePath, long millisecond) { MediaMetadataRetriever retriever = new MediaMetadataRetriever(); retriever.SetDataSource(filePath); Bitmap bitmap = retriever.GetFrameAtTime(millisecond); if (bitmap != null) { MemoryStream stream = new MemoryStream(); bitmap.Compress(Bitmap.CompressFormat.Jpeg, 80, stream); return stream; } return null; }