CommunityToolkit / Maui

The .NET MAUI Community Toolkit is a community-created library that contains .NET MAUI Extensions, Advanced UI/UX Controls, and Behaviors to help make your life as a .NET MAUI developer easier
https://learn.microsoft.com/dotnet/communitytoolkit/maui
MIT License
2.2k stars 375 forks source link

[Proposal] Add support for local files and package resources to MediaElement #2151

Open ne0rrmatrix opened 2 weeks ago

ne0rrmatrix commented 2 weeks ago

Feature name

Add support for local files and package resources to MediaElement

Link to discussion

https://github.com/CommunityToolkit/Maui/discussions/1989

Progress tracker

Summary

Add support for local files and package resources as a source for MediaElement.ArtworkUrl. This will add the missing support for all types of files on all device for artwork images.

Motivation

Allow developer more options to add images from more locations to use as artwork for player.

Detailed Design

API Design:

/// <summary>
    /// Backing store for the <see cref="MetadataArtworkUrl"/> property.
    /// </summary>
    public static readonly BindableProperty MetadataArtworkUrlProperty = BindableProperty.Create(nameof(MetadataArtworkUrl), typeof(MediaSource), typeof(MediaElement));
/// Gets or sets the Artwork Image Url of the media.
    /// This is a bindable property.
    /// </summary>
    [TypeConverter(typeof(MediaSourceConverter))]
    public MediaSource? MetadataArtworkUrl
    {
        get => (MediaSource)GetValue(MetadataArtworkUrlProperty);
        set => SetValue(MetadataArtworkUrlProperty, value);
    }

Usage Syntax

XAML:

 <toolkit:MediaElement
     x:Name="MediaElement"
     ShouldAutoPlay="True"
     Source="https://commondatastorage.googleapis.com/gtv-videos-bucket/sample/BigBuckBunny.mp4"
     MetadataArtworkUrl="ebedded://robot.jpg"
     MetadataTitle="Big Buck Bunny"
     MetadataArtist="Blender Foundation"/>

Code Behind:

MediaElement.MetadataArtworkUrl = MediaSource.FromResource("robot.jpg");  

Drawbacks

None. No reason not to add this.

Alternatives

Adding it with OnPropertyChanged and OnPropertyChanging so that it can dynamically update when added/changed/removed. This would add significant complexity but could be done. I would suggest adding it in a different PR to keep the complexity down.

Unresolved Questions

No response

JohnStrudwick commented 2 weeks ago

I support this so long as ImageSource.FromStream will work, which I assume it will.

This will move #1989 out of new feature discussions?

ne0rrmatrix commented 2 weeks ago

I support this so long as ImageSource.FromStream will work, which I assume it will.

This will move #1989 out of new feature discussions?

ATM I am only planning on adding support for MediaSource I would have to rewrite a class library to add that in. I am adding support for existing types. MediaSource supports local Resources in Application package, local files, and URL's. There is no current support for Stream. I will look into adding it later. I will most likely need to modify the MediaSource class library to add support for it.

JohnStrudwick commented 2 weeks ago

hmmm - MP3 files usually contain the image, so it would seem daft to extract it, save it to a local file to display - and then delete it after......

ne0rrmatrix commented 2 weeks ago

@JohnStrudwick the code added here adds the same support that Source has in media element. It just completes support for MediaSource and replaces string class. It allows for more options. I looked into adding FromStream and the issue with that is do I just add it for images? or do I do it across the board for adding source too?

If I add it for Source it needs to be a seekable stream and that can be a huge headache to implement. I actually spent the last week working on that. I had it working for windows, android, ios, and mac. But the issue of having to download the whole stream before playback is a no go if we want to add it as a source. I am working on a few different things and i hit a wall for ideas on how to handle a stream that needs to be converted from a non seekable one to a seekable stream. It is also platform and class specific in this case for each device type when I do conversion.

I did have a full implementation for all devices working but that was using MediaSource which I added the support for a Stream to and then configured media element to ingest. But I don't plan on spending any more time on it unless someone has a easy way to implement a method to convert a non seekable stream to a seekable one.