Search code examples
youtubemauimediaelement

Higher quality HLS stream from youtube for Media Element in dotnet Maui


I am trying to figure out how to get a higher bitrate video from a youtube stream of a live show in progress. I am playing it back using media element in dotnet maui. Right now it is very low quality video and I have no idea how to improve it. I am using Youtube Explode packgage. The function that I use to get stream is GetHttpLiveStreamUrlAsync(). This is the only way I have been able to get any video to playback in media element for maui.

xaml:

<?xml version="1.0" encoding="utf-8" ?>
<ContentPage
    x:Class="NerdNewsNavigator2.View.LivePage"
    xmlns="http://schemas.microsoft.com/dotnet/2021/maui"
    xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
    xmlns:toolkit="http://schemas.microsoft.com/dotnet/2022/maui/toolkit"
    xmlns:viewmodel="clr-namespace:NerdNewsNavigator2.ViewModel"
    Title=""
    x:DataType="viewmodel:LiveViewModel"
    Loaded="ContentPage_Loaded"
    Unloaded="ContentPage_Unloaded"
    Shell.NavBarIsVisible="False">

    <Shell.BackButtonBehavior>
        <BackButtonBehavior IsEnabled="True" IsVisible="False" />
    </Shell.BackButtonBehavior>

    <Grid>
        <toolkit:MediaElement
            x:Name="mediaElement"
            ShouldAutoPlay="True"
            ShouldShowPlaybackControls="True" />
    </Grid>

</ContentPage>

code to display video:

 private void ContentPage_Loaded(object? sender, EventArgs e)
    {
        if (sender is null)
        {
            return;
        }

        _ = LoadVideo();
        SetFullScreen();
    }
    private async Task LoadVideo()
    {
        var youtube = new YoutubeClient();
        mediaElement.Source = await youtube.Videos.Streams.GetHttpLiveStreamUrlAsync("F2NreNEmMy4");
        mediaElement.Play();
    }

This is abbreviated code that shows the methods I use to get it to display. I am looking for either an alternative method or an improvement of current code to get better video.


Solution

  • Figured out the mediaelement source I provided was in fact an m3u8 file that i was getting and saving as a string. I could parse that to give me a list of resolutions that I could then get a url for. The two packages I ended up using were Youtube Explode and M3U8Parser.

        /// <summary>
        /// Method returns 720P URL for <see cref="mediaElement"/> to Play.
        /// </summary>
        /// <param name="m3UString"></param>
        /// <returns></returns>
        public static string ParseM3UPLaylist(string m3UString)
        {
            var masterPlaylist = MasterPlaylist.LoadFromText(m3UString);
            var list = masterPlaylist.Streams.ToList();
            return list.ElementAt(list.FindIndex(x => x.Resolution.Height == 720)).Uri;
        }
    
        /// <summary>
        /// Method returns the Live stream M3U Url from youtube ID.
        /// </summary>
        /// <param name="url"></param>
        /// <returns></returns>
        public static async Task<string> GetM3U_Url(string url)
        {
            var content = string.Empty;
            var client = new HttpClient();
            var youtube = new YoutubeClient();
            var result = await youtube.Videos.Streams.GetHttpLiveStreamUrlAsync(url);
            var response = await client.GetAsync(result);
            if (response.IsSuccessStatusCode)
            {
                content = await response.Content.ReadAsStringAsync();
            }
    
            return content;
        }
        /// <summary>
        /// Method Starts <see cref="MediaElement"/> Playback.
        /// </summary>
        /// <returns></returns>
        private async Task LoadVideo()
        {
            var m3u = await LivePage.GetM3U_Url("F2NreNEmMy4");
            mediaElement.Source = LivePage.ParseM3UPLaylist(m3u);
            mediaElement.Play();
        }
    

    This code snippet shows how I got the 720P url from a youtube stream using one additional package to parse the m3u8 file.