Forum Xamarin.Forms

Announcement:

The Xamarin Forums have officially moved to the new Microsoft Q&A experience. Microsoft Q&A is the home for technical questions and answers at across all products at Microsoft now including Xamarin!

To create new threads and ask questions head over to Microsoft Q&A for .NET and get involved today.

Xamarin Forms (IOS). Pick_Video and generate video thumbnail. Need to upload the video/thumbnail

TruciferTrucifer Member ✭✭
edited January 18 in Xamarin.Forms

Hi guys,. I use a dependency service to bind a thumbnail of a video to a preview image with no problem. I am using James Montemagno's xam.plugin.media. I am also able to save the video to the server. I need to get the thumbnail of the video that is generated by the dependency service to also be saved to the server. Also need to be able to set the filename of the thumbnail after creating it...
Here is the dependency service, it works fine. I am mainly focused on IOS. Thanks in advance!!

// The call to the dependency
ImageSource v = DependencyService.Get<DependencyThumbnail>().GenerateThumbImage(file.Path, 4); image.Source = v; // Shows preview thumbnail

// The IOS dependency
`public class ThumbnailDependImplement:DependencyThumbnail
{

    public ImageSource GenerateThumbImage(string url, long usecond)
    {
        var asset = AVAsset.FromUrl(NSUrl.FromFilename(url));
        AVAssetImageGenerator imageGenerator = AVAssetImageGenerator.FromAsset(asset);
        //
        //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());
    }
}`

// pick video
` pickVideo.Clicked += async (sender, args) =>
{

            if (!CrossMedia.Current.IsPickVideoSupported)
            {
               await DisplayAlert("Videos Not Supported", ":( Permission not granted for videos.", "OK");
                return;
            }
            var file = await CrossMedia.Current.PickVideoAsync();

            if (file == null)
                return;
            // call dep serv
            ImageSource v = DependencyService.Get<DependencyThumbnail>().GenerateThumbImage(file.Path, 4);
            image.Source = v; // set image. Shows preview thumbnail
            Image img = image;

            savePic.IsEnabled = true;
            myMedia = file;

            await DisplayAlert("Video Selected", "Location: " + v, "OK");

        };`

Answers

  • LucasZhangLucasZhang Member, Xamarin Team Xamurai

    Firstly , you should convert the stream to Byte array so that you can upload them .

    public byte[] GetImageStreamAsBytes(Stream input)
    {
      var buffer = new byte[16*1024];
      using (MemoryStream ms = new MemoryStream())
      {
        int read;
        while ((read = input.Read(buffer, 0, buffer.Length)) > 0)
        {
                    ms.Write(buffer, 0, read);
        }
          return ms.ToArray();
       }
    }
    

    And you could use the plugin FileUploaderPlugin to upload the image to service .

    // you could set the file name in FileBytesItem
    CrossFileUploader.Current.UploadFileAsync("", new FileBytesItem("","",""), new Dictionary<string, string>()
    {
    {"

    " , "
    "}
    }
    );

    For more details and usage of the plugin you could check https://github.com/CrossGeeks/FileUploaderPlugin

  • TruciferTrucifer Member ✭✭

    @LucasZhang said:
    Firstly , you should convert the stream to Byte array so that you can upload them .

    public byte[] GetImageStreamAsBytes(Stream input)
    {
      var buffer = new byte[16*1024];
      using (MemoryStream ms = new MemoryStream())
      {
        int read;
        while ((read = input.Read(buffer, 0, buffer.Length)) > 0)
        {
                    ms.Write(buffer, 0, read);
        }
          return ms.ToArray();
       }
    }
    

    And you could use the plugin FileUploaderPlugin to upload the image to service .

    // you could set the file name in FileBytesItem
    CrossFileUploader.Current.UploadFileAsync("", new FileBytesItem("","",""), new Dictionary<string, string>()
    {
    {"

    " , "
    "}
    }
    );

    For more details and usage of the plugin you could check https://github.com/CrossGeeks/FileUploaderPlugin

    Thanks for the response sir! I will try your suggestion! I need to see if I can set the png/jpg filename using your suggestion prior to uploading to the server...

  • TruciferTrucifer Member ✭✭
    edited January 23

    Got it working for both IOS and android. Just gotta go back and clean up the code but this works. There are definitely better approaches to doing this but maybe this will help someone and get them going in the right direction.

    What i needed to accomplish was to pick a video from the device gallery and then create a thumbnail and have that thumbnail show as a image in the view/page. I then needed to rename the video and thumbnail and then upload the video and the thumbnail to a remote sql-server database.

    Helpful link: https://www.c-sharpcorner.com/UploadFile/nirmal.hota/working-with-dependencyservice-in-xamarin/

    // Interface
    public interface DependencyThumbnail
    {
    ImageSource GenerateThumbImage(string url, long usecond);
    void SaveImage(ImageSource imgSrc, string id, bool overwriteIfExist = false);
    string GetImage(string filename);
    }

    // IOS Dependency
    `public class ThumbnailDependImplement : DependencyThumbnail
    {
    public ImageSource GenerateThumbImage(string url, long usecond)
    {
    MediaMetadataRetriever retriever = new MediaMetadataRetriever();
    retriever.SetDataSource(url);
    Android.Graphics.Bitmap bitmap = retriever.GetFrameAtTime(usecond);
    if (bitmap != null)
    {
    MemoryStream stream = new MemoryStream();
    bitmap.Compress(Android.Graphics.Bitmap.CompressFormat.Png, 0, stream);
    byte[] bitmapData = stream.ToArray();
    return ImageSource.FromStream(() => new MemoryStream(bitmapData));
    }
    return null;
    }

        public async void SaveImage(ImageSource imgSrc, string id, bool overwriteIfExist = false)
        {
           // ** System.IO.Stream outputStream = null;
    
            var renderer = new Xamarin.Forms.Platform.Android.StreamImagesourceHandler();
    

    // Forms.Context is obsolete and wouldn't resolve. Use Android.App.Application.Context instead
    Android.Graphics.Bitmap photo = await renderer.LoadImageAsync(imgSrc, Android.App.Application.Context);
    var savedImageFilename = System.IO.Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.Personal), id + ".png");

            System.IO.Directory.CreateDirectory(Environment.GetFolderPath(Environment.SpecialFolder.Personal));
    
            FileStream stream = new System.IO.FileStream(savedImageFilename, System.IO.FileMode.Create);
            await photo.CompressAsync(Android.Graphics.Bitmap.CompressFormat.Png, 100, stream);
            MessagingCenter.Send<ImageUploadPage, string>(new ImageUploadPage(), "getPath", savedImageFilename);
            GetImage(savedImageFilename);
            stream.Close();
            // end test
    
        }
        public string GetImage(string filename)
        {
            var documentsPath = Environment.GetFolderPath(Environment.SpecialFolder.Personal);
            var filePath = System.IO.Path.Combine(documentsPath, filename);
            Console.WriteLine("file Path: " + System.IO.Path.GetFileName(filePath));
            MessagingCenter.Send<ImageUploadPage, string>(new ImageUploadPage(), "getFile", System.IO.Path.GetFileName(filePath));
            return File.ReadAllText(filePath);
        }
    }`
    

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

        public async void SaveImage(ImageSource imgSrc, string id, bool overwriteIfExist = false)
        {
           // ** System.IO.Stream outputStream = null;
    
            var renderer = new Xamarin.Forms.Platform.Android.StreamImagesourceHandler();
            Android.Graphics.Bitmap photo = await renderer.LoadImageAsync(imgSrc, Android.App.Application.Context);
            var savedImageFilename = System.IO.Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.Personal), id + ".png");
    
            System.IO.Directory.CreateDirectory(Environment.GetFolderPath(Environment.SpecialFolder.Personal));
    
            FileStream stream = new System.IO.FileStream(savedImageFilename, System.IO.FileMode.Create);
            await photo.CompressAsync(Android.Graphics.Bitmap.CompressFormat.Png, 100, stream);
            MessagingCenter.Send<ImageUploadPage, string>(new ImageUploadPage(), "getPath", savedImageFilename);
            GetImage(savedImageFilename);
            stream.Close();
            // end test
    
        }
        public string GetImage(string filename)
        {
            var documentsPath = Environment.GetFolderPath(Environment.SpecialFolder.Personal);
            var filePath = System.IO.Path.Combine(documentsPath, filename);
            string jelly = System.IO.Path.GetFileName(filePath);
            Console.WriteLine("file Path: " + System.IO.Path.GetFileName(filePath));
            MessagingCenter.Send<ImageUploadPage, string>(new ImageUploadPage(), "getFile", System.IO.Path.GetFileName(filePath));
            return File.ReadAllText(filePath);
        }
    }`
    

    // Call the dependency

    var file = await CrossMedia.Current.PickVideoAsync();

                if (file == null)
                    return;
                ImageSource v = DependencyService.Get<DependencyThumbnail>().GenerateThumbImage(file.Path, 4);
    

    // You can assign v as your image source to show the thumbnail on the view/page
    string s = "ABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789";
    Random r = new Random();
    StringBuilder sb = new StringBuilder();
    for (int i = 1; i <= 10; i++)
    {
    int idx = r.Next(0, 14);
    sb.Append(s.Substring(idx, 1));
    }
    DependencyService.Get().SaveImage(v, sb.ToString());

  • LucasZhangLucasZhang Member, Xamarin Team Xamurai

    For pick Image or Video you could use the plugin Xam.Plugin.Media

Sign In or Register to comment.