Giter Site home page Giter Site logo

youtubeexplode's Introduction

YoutubeExplode

Status Made in Ukraine Build Coverage Version Downloads Discord Fuck Russia

Development of this project is entirely funded by the community. Consider donating to support!

Icon

YoutubeExplode is a library that provides an interface to query metadata of YouTube videos, playlists and channels, as well as to resolve and download video streams and closed caption tracks. Behind a layer of abstraction, this library works by scraping raw page data and exploiting reverse-engineered internal endpoints.

📝 Interested in the inner workings of this library? See the Reverse-Engineering YouTube article.

Extension packages:

Terms of use[?]

By using this project or its source code, for any purpose and in any shape or form, you grant your implicit agreement to all the following statements:

  • You condemn Russia and its military aggression against Ukraine
  • You recognize that Russia is an occupant that unlawfully invaded a sovereign state
  • You support Ukraine's territorial integrity, including its claims over temporarily occupied territories of Crimea and Donbas
  • You reject false narratives perpetuated by Russian state propaganda

To learn more about the war and how you can help, click here. Glory to Ukraine! 🇺🇦

Install

  • 📦 NuGet: dotnet add package YoutubeExplode

Screenshots

demo

Usage

YoutubeExplode exposes its functionality through a single entry point — the YoutubeClient class. Create an instance of this class and use the provided operations on Videos, Playlists, Channels, and Search properties to send requests.

Videos

Retrieving video metadata

To retrieve the metadata associated with a YouTube video, call Videos.GetAsync(...):

using YoutubeExplode;

var youtube = new YoutubeClient();

// You can specify either the video URL or its ID
var videoUrl = "https://youtube.com/watch?v=u_yIGGhubZs";
var video = await youtube.Videos.GetAsync(videoUrl);

var title = video.Title; // "Collections - Blender 2.80 Fundamentals"
var author = video.Author.ChannelTitle; // "Blender"
var duration = video.Duration; // 00:07:20

Downloading video streams

Every YouTube video has a number of streams available, differing in containers, video quality, bitrate, framerate, and other parameters. Additionally, the streams are further divided into 3 categories based on their content:

  • Muxed streams — contain both video and audio
  • Audio-only streams — contain only audio
  • Video-only streams — contain only video

Warning: Muxed streams contain both audio and video, but these streams are limited in quality (up to 720p30). To download the video in the highest available quality, you will need to resolve the best audio-only and video-only streams separately and then mux them together. The muxing process can be performed using FFmpeg with the help of the YoutubeExplode.Converter package.

You can request the manifest that lists all available streams for a particular video by calling Videos.Streams.GetManifestAsync(...):

using YoutubeExplode;

var youtube = new YoutubeClient();

var videoUrl = "https://youtube.com/watch?v=u_yIGGhubZs";
var streamManifest = await youtube.Videos.Streams.GetManifestAsync(videoUrl);

Once the manifest is obtained, you can filter through the streams and identify the ones you're interested in:

using YoutubeExplode;
using YoutubeExplode.Videos.Streams;

// ...

// Get highest quality muxed stream
var streamInfo = streamManifest.GetMuxedStreams().GetWithHighestVideoQuality();

// ...or highest bitrate audio-only stream
var streamInfo = streamManifest.GetAudioOnlyStreams().GetWithHighestBitrate();

// ...or highest quality MP4 video-only stream
var streamInfo = streamManifest
    .GetVideoOnlyStreams()
    .Where(s => s.Container == Container.Mp4)
    .GetWithHighestVideoQuality()

Finally, you can resolve the actual stream represented by the specified metadata using Videos.Streams.GetAsync(...) or download it directly to a file with Videos.Streams.DownloadAsync(...):

// ...

// Get the actual stream
var stream = await youtube.Videos.Streams.GetAsync(streamInfo);

// Download the stream to a file
await youtube.Videos.Streams.DownloadAsync(streamInfo, $"video.{streamInfo.Container}");

Warning: While the Url property in the stream metadata can be used to access the underlying content, you need a series of carefully crafted HTTP requests in order to do so. It's highly recommended to use Videos.Streams.GetAsync(...) or Videos.Streams.DownloadAsync(...) instead, as they will perform all the heavy lifting for you.

Downloading closed captions

Closed captions can be downloaded in a similar way to media streams. To get the list of available closed caption tracks, call Videos.ClosedCaptions.GetManifestAsync(...):

using YoutubeExplode;

var youtube = new YoutubeClient();

var videoUrl = "https://youtube.com/watch?v=u_yIGGhubZs";
var trackManifest = await youtube.Videos.ClosedCaptions.GetManifestAsync(videoUrl);

Then retrieve the metadata for a particular track:

// ...

// Find closed caption track in English
var trackInfo = trackManifest.GetByLanguage("en");

Finally, use Videos.ClosedCaptions.GetAsync(...) to get the actual content of the track:

// ...

var track = await youtube.Videos.ClosedCaptions.GetAsync(trackInfo);

// Get the caption displayed at 0:35
var caption = track.GetByTime(TimeSpan.FromSeconds(35));
var text = caption.Text; // "collection acts as the parent collection"

You can also download the closed caption track in the SRT file format with Videos.ClosedCaptions.DownloadAsync(...):

// ...

await youtube.Videos.ClosedCaptions.DownloadAsync(trackInfo, "cc_track.srt");

Playlists

Retrieving playlist metadata

You can get the metadata associated with a YouTube playlist by calling the Playlists.GetAsync(...) method:

using YoutubeExplode;

var youtube = new YoutubeClient();

var playlistUrl = "https://youtube.com/playlist?list=PLa1F2ddGya_-UvuAqHAksYnB0qL9yWDO6";
var playlist = await youtube.Playlists.GetAsync(playlistUrl);

var title = playlist.Title; // "First Steps - Blender 2.80 Fundamentals"
var author = playlist.Author.ChannelTitle; // "Blender"

Retrieving videos included in a playlist

To get the videos included in a playlist, call Playlists.GetVideosAsync(...):

using YoutubeExplode;
using YoutubeExplode.Common;

var youtube = new YoutubeClient();
var playlistUrl = "https://youtube.com/playlist?list=PLa1F2ddGya_-UvuAqHAksYnB0qL9yWDO6";

// Get all playlist videos
var videos = await youtube.Playlists.GetVideosAsync(playlistUrl);

// Get only the first 20 playlist videos
var videosSubset = await youtube.Playlists.GetVideosAsync(playlistUrl).CollectAsync(20);

You can also enumerate the videos iteratively without waiting for the whole list to load:

using YoutubeExplode;

var youtube = new YoutubeClient();
var playlistUrl = "https://youtube.com/playlist?list=PLa1F2ddGya_-UvuAqHAksYnB0qL9yWDO6";

await foreach (var video in youtube.Playlists.GetVideosAsync(playlistUrl))
{
    var title = video.Title;
    var author = video.Author;
}

If you need precise control over how many requests you send to YouTube, use Playlists.GetVideoBatchesAsync(...) which returns videos wrapped in batches:

using YoutubeExplode;

var youtube = new YoutubeClient();
var playlistUrl = "https://youtube.com/playlist?list=PLa1F2ddGya_-UvuAqHAksYnB0qL9yWDO6";

// Each batch corresponds to one request
await foreach (var batch in youtube.Playlists.GetVideoBatchesAsync(playlistUrl))
{
    foreach (var video in batch.Items)
    {
        var title = video.Title;
        var author = video.Author;
    }
}

Note: You can craft playlist IDs to fetch special auto-generated playlists, such as music mixes, popular channel uploads, liked videos, and more. See this reference for more information.

Channels

Retrieving channel metadata

You can get the metadata associated with a YouTube channel by calling the Channels.GetAsync(...) method:

using YoutubeExplode;

var youtube = new YoutubeClient();

var channelUrl = "https://youtube.com/channel/UCSMOQeBJ2RAnuFungnQOxLg";
var channel = await youtube.Channels.GetAsync(channelUrl);

var title = channel.Title; // "Blender"

You can also get the channel metadata by username or profile URL with Channels.GetByUserAsync(...):

using YoutubeExplode;

var youtube = new YoutubeClient();

var channelUrl = "https://youtube.com/user/BlenderFoundation";
var channel = await youtube.Channels.GetByUserAsync(channelUrl);

var id = channel.Id; // "UCSMOQeBJ2RAnuFungnQOxLg"

To get the channel metadata by slug or legacy custom URL, use Channels.GetBySlugAsync(...):

using YoutubeExplode;

var youtube = new YoutubeClient();

var channelUrl = "https://youtube.com/c/BlenderFoundation";
var channel = await youtube.Channels.GetBySlugAsync(channelUrl);

var id = channel.Id; // "UCSMOQeBJ2RAnuFungnQOxLg"

To get the channel metadata by handle or custom URL, use Channels.GetByHandleAsync(...):

using YoutubeExplode;

var youtube = new YoutubeClient();

var channelUrl = "https://youtube.com/@BeauMiles";
var channel = await youtube.Channels.GetByHandleAsync(channelUrl);

var id = channel.Id; // "UCm325cMiw9B15xl22_gr6Dw"

Retrieving channel uploads

To get the list of videos uploaded by a channel, call Channels.GetUploadsAsync(...):

using YoutubeExplode;
using YoutubeExplode.Common;

var youtube = new YoutubeClient();
var channelUrl = "https://youtube.com/channel/UCSMOQeBJ2RAnuFungnQOxLg";

var videos = await youtube.Channels.GetUploadsAsync(channelUrl);

Search

You can execute a search query by calling the Search.GetResultsAsync(...) method. Each search result may represent either a video, a playlist, or a channel, so you need to apply pattern matching to handle the corresponding cases:

using YoutubeExplode;

var youtube = new YoutubeClient();

await foreach (var result in youtube.Search.GetResultsAsync("blender tutorials"))
{
    // Use pattern matching to handle different results (videos, playlists, channels)
    switch (result)
    {
        case VideoSearchResult video:
        {
            var id = video.Id;
            var title = video.Title;
            var duration = video.Duration;
            break;
        }
        case PlaylistSearchResult playlist:
        {
            var id = playlist.Id;
            var title = playlist.Title;
            break;
        }
        case ChannelSearchResult channel:
        {
            var id = channel.Id;
            var title = channel.Title;
            break;
        }
    }
}

To limit the results to a specific type, use Search.GetVideosAsync(...), Search.GetPlaylistsAsync(...), or Search.GetChannelsAsync(...):

using YoutubeExplode;
using YoutubeExplode.Common;

var youtube = new YoutubeClient();

var videos = await youtube.Search.GetVideosAsync("blender tutorials");
var playlists = await youtube.Search.GetPlaylistsAsync("blender tutorials");
var channels = await youtube.Search.GetChannelsAsync("blender tutorials");

Similarly to playlists, you can also enumerate results in batches by calling Search.GetResultBatchesAsync(...):

using YoutubeExplode;

var youtube = new YoutubeClient();

// Each batch corresponds to one request
await foreach (var batch in youtube.Search.GetResultBatchesAsync("blender tutorials"))
{
    foreach (var result in batch.Items)
    {
        switch (result)
        {
            case VideoSearchResult videoResult:
            {
                // ...
            }
            case PlaylistSearchResult playlistResult:
            {
                // ...
            }
            case ChannelSearchResult channelResult:
            {
                // ...
            }
        }
    }
}

Authentication

You can access private videos and playlists by providing cookies that correspond to a pre-authenticated YouTube account. To do that, create an instance of YoutubeClient using a constructor that accepts IReadOnlyList<Cookie>:

using YoutubeExplode;

// Perform authentication and extract cookies
var cookies = ...;

// Cookie collection must be of type IReadOnlyList<System.Net.Cookie>
var youtube = new YoutubeClient(cookies);

In order to actually perform the authentication, you can use an embedded browser such as WebView to navigate the user to the YouTube login page, let them log in, and then extract the cookies from the browser.

Etymology

The "Explode" in YoutubeExplode comes from the name of a PHP function that splits up strings, explode(...). When I was starting the development of this library, most of the reference source code I read was written in PHP, hence the inspiration for the name.

youtubeexplode's People

Contributors

bcook254 avatar brunozell avatar d4n3436 avatar dalilasilva avatar dbakuntsev avatar dominicmaas avatar dr-beat avatar foritus avatar h0lg avatar hig-dev avatar jankowski-t avatar jpspringall avatar knightking100 avatar maxkatz6 avatar mercenaryntx avatar migueloliveiradev avatar omansak avatar polakosz avatar polynoman avatar pvogt avatar shaked6540 avatar slowlogicboy avatar thesn10 avatar tmm360 avatar tqk2811 avatar tyrrrz avatar unreal852 avatar wellwineo avatar wleader avatar xbaank avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

youtubeexplode's Issues

How do I use the progress bar with this API?

I want to create a YouTube download program with a progress bar.
After seeing the wiki, I knew how to download it, but I do not know how to add a progress bar.

The source of GitHub is an error and can not be opened.
Could you give me an example of how to make it?

I am sorry for my poor English ability.
I do not know if I can upload here, but if not, I'm sorry :(

Add few more playlist types

UU{channelId} - Channel Uploads
PU{channelId} - Popular

When I use these, exception is throw "Unexpected playlist ID [{0}]".

After modifying it through reflection by instead of throwing, returning PlaylistType.UserMode, these playlists yield results, so I think these should be added too.
You can differentiate them by
"UU" - Channel Uploads,
"PU" - Popular channel uploads,

Maybe a good Idea would be to return PlaylistType.Unknown when you can't differentiate what type it is.

This is also an opportunity to add method GetChannelUploadsAsync(string channelId);

However, if I look up youtube channel url it is "https://www.youtube.com/channel/UC*" so for uploads I have to make it to "UU*" same with "PU*"

YouTubeExplode.Exceptions.UnexpectedIdentifierException

YoutubeExplode.Exceptions.UnexpectedIdentifierException occurred
  HResult=0x80131500
  Message=Unexpected itag [139]
  Source=YoutubeExplode
  StackTrace:
   at YoutubeExplode.Models.MediaStreams.MediaStreamInfo.GetContainer(Int32 itag)
   at YoutubeExplode.Models.MediaStreams.MediaStreamInfo..ctor(Int32 itag, String url, Int64 contentLength)
   at YoutubeExplode.Models.MediaStreams.AudioStreamInfo..ctor(Int32 itag, String url, Int64 contentLength, Int64 bitrate)
   at YoutubeExplode.YoutubeClient.<GetVideoInfoAsync>d__7.MoveNext()
   at System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(Task task)
   at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)
   at System.Runtime.CompilerServices.TaskAwaiter`1.GetResult()
   at PLAYER.MainWindow.<>c__DisplayClass127_0.<<GetURLS>b__0>d.MoveNext() in C:\Users\Dawid\Desktop\PLAYER\PLAYER\MainWindow.xaml.cs:line 2080

Line that called it:

var videoInfo = await client.GetVideoInfoAsync(currentLink);
Content of currentLink:
currentLink	"NnPKBwO4-P8"	string

It worked today. Now I have no idea what's causing the problem :/ Any ideas?

Add GetChannelInfoAsync

Implement by querying a UU playlist with the given channel ID and extracting the info from the first video

Progress reporting "100" twice

Hello!

I've recently started using the progress functionality of your library, and was a bit surprised that the following code

private void ProgressHandler_ProgressChanged(object sender, double args, VideoInfo videoInfo) {
    if (args * 100 == 100) {
        MessageBox.Show($"video {videoInfo.Title} 100%!");
    }
}

would send me two MessageBoxes.

Is this a bug? Am I doing it wrong?
Even though it's probably the latter, I'd really appreciate some help/info on this one.

Kind regards and thanks in advance! :)

Explode the URL

Hey, I won't mind pushing a PR myself, but wondering if you are still accepting them? Or you can do it yourself?

On this method, can you please return the URL of the downloadable video?

GetVideoInfoAsync

I don't want the streams, I simply want the URL to download it myself. Make sense? Just add it to the VideoInfo object. If you reply and let me know you can't or don't have time, Ill do it. Just wondering if you would be willing to do it first?

Not working on Xamarin.android

Hello !
I'm using the nuget package version 2.3.0 and while the library works fine in a normal console application, i cant get the library to work consistently on xamarin android,

I'm using latest xamarin.android, made an android unit test app compiling using API 25 target, and min sdk 16, running on 21 emulator( Genymotion ) using visual studio 2015 on windows 10 x64 .

I made an xamrain.android unit tester to test it after it failed in my application:

using NUnit.Framework;
using YoutubeExplode;

namespace UnitTestYoutubeExplode
{
    [TestFixture]
    public class TestsSample
    {

        public string[] ids = { "PMivT7MJ41M"};

        [Test, TestCaseSource("ids")]
        public async void TestMethod(string id)
        {
            using(var client = new YoutubeClient())
            {
                Assert.True(YoutubeClient.ValidateVideoId(id));      //This passed fine all the time
                Assert.True(await client.CheckVideoExistsAsync(id)); //This passed fine all the time

                var playlistItemInfo = await client.GetVideoInfoAsync(id);
                Assert.IsNotNull(playlistItemInfo.Title);
            }
        }

    }
}

All ids are valid.
Originally the test had more ids, but i couldn't get it to pass even with one.
Here are the exceptions i was getting at await client.GetVideoInfoAsync(id) :

TestMethod("h--P8HzYZ74") [FAIL] : System.Exception : Could not get video info
		  at YoutubeExplode.YoutubeClient+<CheckVideoExistsAsync>d__7.MoveNext () [0x000dd] in <9d4dbb3394174337b21bfdc5e06fc022>:0 

TestMethod("papuvlVeZg8") [FAIL] : System.Exception : Could not get video context
		  at YoutubeExplode.YoutubeClient+<GetVideoInfoAsync>d__8.MoveNext () [0x000f4] in <9d4dbb3394174337b21bfdc5e06fc022>:0 

TestMethod("gL-WVjvzu34") [FAIL] : System.Exception : Could not parse sts
		  at YoutubeExplode.Internal.Parser.VideoContextFromHtml (System.String rawHtml) [0x00066] in <9d4dbb3394174337b21bfdc5e06fc022>:0 
		  at YoutubeExplode.YoutubeClient+<GetVideoInfoAsync>d__8.MoveNext () [0x000ff] in <9d4dbb3394174337b21bfdc5e06fc022>:0 


I tried with or without reference to System.Net.Http, different httpclient implementations (Default, Managed,AndroidClientHandler) , debug and release build and nothing make it work consistently.

About 1 in a 10 would work fine, while in the regular console application, i had no problem running 50+ one after another.

The library stated it targets .NET Standard 1.1, which xamarin.android supports, so it should work.

Unable to open some of the projects in the solution

So i have downloaded the source and i can only load the DemoWpf so i can't make small changes to the exemple because it can't load

Error:
The default XML namespace of the project must be the MSBuild XML namespace. If the project is authored on the MSBuild 2003 format, please add xmlns="http://schemas.microsoft.com/developer/msbuild/2003" to the <Project> element. If the project has been authored in the old 1.0 or 1.2 format, please convet it to MSBuild 2003 format. C:\Userthomasmel.hole\Desktop\YouTubeExplode-3.2\(DemoConsole, Tests or YoutubeExplode)\the .csprj file in the folder

Demo's broken?

The console demo is broken for me.
What is broken you might ask?

  • doesnt have a field called id
  • char - does not contain a .Repeat() method (try "".PadRight(100, '-'); instead)
  • filename = filename.exept cannot be converted. A string.Join([the linq statement]); is needed

How to use CancellationToken with DownloadMediaStreamAsync()?

Hello!
I was wondering, if you had any solution to my following problem:
I included a CancellationToken into the DownloadMediaStreamAsync()-Method, and now I (obviously) get an exception thrown at me (the nasty MessageBox that tells me a Task was aborted), whenever i cancel a video download.
Is there any way to suppress that thing and maybe handle it with a custom MessageBox through some kind
of event?
I've browsed most of the code, but couldn't come up with a sollution myself (except for messing with your code and compiling a modified library myself, which I'd rather not do, because I'm not that good at coding really, and also I don't know if your code is licensed or something?).

Regards, thanks in advance, and keep up the awesome work!

C# Winforms

I would like to use this on winforms not wpf. how could i do this

Extract all available video qualities

How i can loop trough the available Video Qualities in the VideoInfo the right way?

I want to check it against a fixed array of qualities and decide if a checkbox is enabled or not.

someone can give me a hint for the right linq to use ?

WPF MediaElement doesn't play video from HTTPS source

... because it sucks.
Apparently it's a known issue and cannot be resolved with the native MediaElement control, because it doesn't support streaming sources over HTTPS and there's no way to set source from a stream.
One option would be to download video before playing, but it's a terrible approach for obvious reasons.
Another (better) option would be to use a different control, for which I'd like to hear suggestions.

VideoInfo has no publicly available constructor

DataBinding is difficult with VideoInfo (specifically in WPF) because most controls wont allow a null data source and we can't instantiate an instance of VideoInfo as it only has an internal constructor.

Difference between sample and NuGet package

In the GitHub code and sample, VideoInfo contains Streams. In the NuGet package, however, it instead contains MixedStreams, AudioStreams and VideoStreams. Why the discrepancy?

Adding ratebypass to download url

Hello again,
I noticed a very big speed gap between downloads with this library, and youtube dl which i took for reference.
Downloading itag 251, takes about 20 minute for 1 hour video, as with youtube dl - around 9 seconds.

I have dug a bit in their code, and found that an option is missing from the final stream url, which is 'ratebypass=true',and i confirmed that adding it, allows YouTube to send data at constant speed (usually is first 40 seconds at max speed, rest at watching speed).The parameter is present both at dash and non dash streams.

Relevant code in youtube dl - https://github.com/rg3/youtube-dl/blob/master/youtube_dl/extractor/youtube.py#L1644

Add an API for searching

The old SearchAsync was removed because it returned weird results, not in line with the actual Youtube search, however having a search API would be very useful.

Compatibility under Windows XP

Compatibility under YoutubeExplode has not been tested under Windows XP and any attempt to run YoutubeExplode from Windows XP will display a critical error saying YoutubeExplode.exe is not a valid Win32 application.

Get Channel Subscriptions and Playlists

From channel id get it's subscriptions and playlists if publicly available.

GetChannelSubscribtionsAsync(string channelId)
returns IEnumerable<string> ChannelIds //at minimum maybe there would be more info available

GetChannelPlaylistsAsync(string channelId)
returns IEnumerable<string> PlaylistIds //at minimum maybe there would be more info available

Or maybe it is possible to get everything through GetChannelInfoAsync(string channelId)?

I haven't looked on how to do this. Worst case scenario would be to parse/scrape channel page.

https://www.youtube.com/channel/{channelId}/channels
https://www.youtube.com/channel/{channelId}/playlists

Should the parser tests be done separately as unit tests?

Currently integration tests are verifying both the parsing logic, as well as the integration with Youtube front-end itself.
Earlier I stood by this decision because with the rather few tests we had, it was a lot easier to test everything at once, instead of maintaining mock server responses.
Seeing how there are a lot more tests now, majority of which just verify the integration workflow in various scenarios (normal video, signed video, restricted video, normal playlist, long playlist, etc), it might be a good idea to move part of the assertions to unit tests. That way we can test the parsing logic once in unit tests, while integration tests will only assert conditions that are directly relevant to the scenario.

Pros:

  • Reduce assertion clutter in integration tests
  • Detect parsing issues more reliably with predictable assertions
  • Able to test majority of YTE's logic offline

Cons:

  • Have to maintain and update mock responses when Youtube changes something
  • When something does change, it won't be as easy to detect it as it is now

Open discussion until 19th of April.

Get Video Metadata from GetPlaylistInfo

When I use GetPlaylistInfo I get only videoId list, but in response there are also video metadata, that could be returned as well.
Because right now I need to use GetPlaylistInfo and run GetVideoInfo for every video, when I could get Video Metadata with GetPlaylistInfo, without streams, that would save me so many unnecessary requests.

Possible to queue downloads and start them if < then 2 downloads active ?

Hello,

at first, thanks for this library, it's the best I've found :)

Now i want to code a download queue. I tried some things with the C# queue class but I'm relatively new to programming and I dont understand how most things work. Anyone has some tipps to integrate a download queue ? Heres my download code at the moment.

` private async void tUrl_TextChanged(object sender, EventArgs e)
{
int counter = Convert.ToInt32(label1.Text);

        if (cbAutoDownload.Checked)
        {
            try
            {

                var client = new YoutubeClient();                       
            
                string id = tUrl.Text;
                id = NormalizeId(id);

                var videoInfo = await client.GetVideoInfoAsync(id);
                var streamInfo = videoInfo.MixedStreams.OrderBy(s => s.VideoQuality).Last();

                grösse = videoInfo.MixedStreams[0].ContentLength;
                NormalizeFileSize(grösse);
                grösse = grösse;
                realSize = grösse / 1024;
                realSize2 = realSize / 1024;
                lblSize.Text = realSize2.ToString() + " MB";
               
                gesamtSög += realSize2;
                lblGesamt.Text = gesamtSög.ToString() + " MB";

                string fileExtension = streamInfo.Container.GetFileExtension();
                string fileName = $"{ videoInfo.Title}.{ fileExtension}";
                string EndDirectory = tPath.Text + @"\";
                fileName = fileName.Except(Path.GetInvalidFileNameChars());
                var videoFilePath = Path.Combine(EndDirectory, fileName);
                
                string fullFileName = Path.Combine(EndDirectory, fileName);

                if (!File.Exists(fullFileName))
                {
                
                    string[] arr = new string[4];
                    ListViewItem itm;
                    arr[0] = fileName;
                    arr[1] = "Downloading...";
                    arr[2] = EndDirectory;
                    arr[3] = tUrl.Text;
                    itm = new ListViewItem(arr);
                    listVideo.Text = arr[0];
                    downloading += 1;

                    label1.Text = downloading.ToString();
                    int senf = Convert.ToInt32(listFinished.Items.Count);
                    listFinished.Items.Add(itm);
                    
                    integer = senf;
                                       

                    var progressHandler = new Progress<double>(p => pbar = Convert.ToInt32(p * 100 ));
                    
                    await client.DownloadMediaStreamAsync(streamInfo, videoFilePath, progressHandler);
                                      
                    pBar.Value = 0;
                    downloading -= 1;
                    label1.Text = downloading.ToString();
                  

                    string countList = listFinished.Items.Count.ToString();
                    lblCount.Text = countList;
                   
                    listFinished.Items[0].SubItems[1].Text = "Fertig";
                    listFinished.Items[integer].SubItems[1].Text = "Fertig";
                    integer++;

                    ListItemsHelper listItemsHelper = new ListItemsHelper();
                    listItemsHelper.saveListViewItems(path23, listFinished);
                    path23 = AppDomain.CurrentDomain.BaseDirectory + "DownloadList.txt";
                    path23 = path23;
                    Properties.Settings.Default.Speicherpfad = tPath.Text;
                    Properties.Settings.Default.Save();

                }
            }
               
            catch (Exception) { }
        }
    }

`

Problem with downloading

Downloading from youtube almost not working always.

Wanted video exists but Youtube client says video not found

string request = $"https://www.youtube.com/get_video_info?video_id={videoId}&el=info&ps=default";

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.