0

I am trying to find solution to play YouTube video from http stream. Not as embedded player or via website. The reason of that as I need to play some clips locally in app that prevented to be embedded. So the first task to obtain http stream is easy to solve, e.g. using YouTubeExtractor. For example from this youtube url https://www.youtube.com/watch?v=31crA53Dgu0

YouTubeExtractor extracts such url for downloading video. As you can see there is no piece of path to concrete .mp4 or .mov file. There is also binding to IP, so the url won't work on your side.

https://r3---sn-puu8-3c2e.googlevideo.com:443/videoplayback?sparams=dur,gcr,id,initcwndbps,ip,ipbits,itag,lmt,mime,mm,mn,ms,mv,pl,ratebypass,requiressl,source,upn,expire&source=youtube&initcwndbps=3147500&pl=19&upn=oYYkSNBwoc8&fexp=9412913,9416126,9416891,9422596,9428398,9429016,9431012,9431364,9431901,9432206,9432825,9433096,9433424,9433623,9433946,9434085,9435504,9435703,9435937&id=o-AGanAaajMgOmp4VrXIwo9jewJnqlsvZecDxCcRpSN3lS&expire=1462821352&gcr=ua&ip=12.34.56.149&lmt=1458705532562546&ms=au&mt=1462799507&mv=m&dur=217.849&sver=3&itag=22&key=yt6&mn=sn-puu8-3c2e&mm=31&ipbits=0&mime=video/mp4&ratebypass=yes&requiressl=yes&signature=A142619EBA90D00CC46FF05B9CF1E3469B0EF196.072B532670A4D833582F94CF9C46F1F7D298F230&fallback_host=tc.v1.cache5.googlevideo.com

private string ExtractVideoUrl(string youtubeUrl)
    {
        IEnumerable<VideoInfo> videoInfos = DownloadUrlResolver.GetDownloadUrls(youtubeUrl, false);
        var video = videoInfos.First();
        if (video.RequiresDecryption)
        {
            DownloadUrlResolver.DecryptDownloadUrl(video);
        }

        return video.DownloadUrl;       // videoInfos.First().DownloadUrl;
    }

Then to download video this lib uses the code below. The interesting moment is in reading stream and writing to file the contents of youtube video.

var request = (HttpWebRequest)WebRequest.Create(this.Video.DownloadUrl);
        if (this.BytesToDownload.HasValue)
        {
            request.AddRange(0, this.BytesToDownload.Value - 1);
        }

        // the following code is alternative, you may implement the function after your needs
        using (WebResponse response = request.GetResponse())
        {
            using (Stream source = response.GetResponseStream())
            {
            **// HOW to Play source stream???**
                using (FileStream target = File.Open(this.SavePath, FileMode.Create, FileAccess.Write))
                {
                    var buffer = new byte[1024];
                    bool cancel = false;
                    int bytes;
                    int copiedBytes = 0;

                    while (!cancel && (bytes = source.Read(buffer, 0, buffer.Length)) > 0)
                    {
                        target.Write(buffer, 0, bytes);
                        .... 

So the general question is how to play video from that open stream? For example Chrome, Firefox and KMPlayer are doing this easily. The browsers generate a simple page with video tag, so it will be trivial to manage the player through JS. But...internal WebBrowser control can't, it suggests to download file. I tried CEFSharp (Chrome Embeded Framework) and no luck there. Maybe anybody know good video player WPF library which can streaming video? I also tried VLC.wpf and Shockwave Flash, but still unhappy with this extracted url. A lot of searching but results insufficient for now.

Denys Kazakov
  • 472
  • 3
  • 17

1 Answers1

1

After 2 days researching I found the solution of how to play youtube video url directly from WPF application. Some notes before:

  • WebBrowser component for WPF and the same for WinForms does not support HTML5. So no way to play video using <video> tag there
  • Chrome Embeded Framework (CEF)and its CEFSharp wrapper does not support <audio> and <video> tags by default. As I found on SO it is needed to recompile CEF to support audio and it seems video too. --enable-multimedia-streams option didn't work on my side at all to play video
  • WPF MediaElement component does not support playing video from streams. However there are workaroung exists, they are unsuitable to play youtube url's.
  • No .NET media player found which could play video from Stream object returned by HttpWebRequest

So the solution is in using GeckoFx webbrowser which is also available via nuget. As it is WinForms based component it is needed to use WinFormsHosting to use it in WPF. Final solution is:

<xmlns:gecko="clr-namespace:Gecko;assembly=Geckofx-Winforms">
....
<WindowsFormsHost Width="400" Height="300" HorizontalAlignment="Stretch"  VerticalAlignment="Stretch" >
                <gecko:GeckoWebBrowser x:Name="_geckoBrowser"/>
            </WindowsFormsHost>

And simple code to use:

public void PlayVideo(string videoId)
    {                        
        var url = string.Format("https://www.youtube.com/watch?v={0}", videoId);
        var videoUrl = ExtractVideoUrl(url);

        _geckoBrowser.Navigate(videoUrl);
    }

GeckoFx is depeneded on XulRunner runtime sdk. It is installed with nuget package though. One cons in this solution is the size of all app dependencies increased for over +70mb.

Community
  • 1
  • 1
Denys Kazakov
  • 472
  • 3
  • 17
  • Now you could also use WebView2: https://learn.microsoft.com/en-us/dotnet/api/microsoft.web.webview2.wpf.webview2?view=webview2-dotnet-1.0.1343.22 – Setyo N Sep 30 '22 at 05:54