Note
Access to this page requires authorization. You can try signing in or changing directories.
Access to this page requires authorization. You can try changing directories.
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; }