user1200226
user1200226

Reputation: 67

Youtube Class not working

I modified a Youtube Downloader class written in C# to use it on a windows phone. My result is the following. But when I call dw(); I get an File-not-found-exception from the web browser in the line e.Result.Read(buffer, 0, buffer.Length). I surely know what this means but I don't know how to fix it. So I have 2 questions: Why does my code not work? Or is there another way to download Youtube videos on WindowsPhone 7? (Like a library or a free code snippet...) Thank you.

class YoutubeDownload
{
    string youtubeurl;
    string fileext;

    private WebClient webClient = new WebClient();

    public void dw()
    {
        youtubeurl = "http://www.youtube.com/watch?v=locIxsfpgp4&feature=related";
        webClient.DownloadStringCompleted += new DownloadStringCompletedEventHandler(client_DownloadStringCompleted);
        webClient.DownloadStringAsync(new Uri(youtubeurl));
    }

    void client_DownloadStringCompleted(object sender, DownloadStringCompletedEventArgs e)
    {
        string rawHtml = e.Result;
        string getUrl = "http://www.youtube.com/get_video.php?video_id={0}&t={1}";
        Regex _titleRegex = new Regex("'VIDEO_TITLE': '(.+)',");
        Regex _qualiRegex = new Regex("\"fmt_map\": \"([0-9]{2})");
        Regex _idRegex = new Regex("\",\\s*\"t\":\\s*\"([^\"]+)");

        Match title = _titleRegex.Match(rawHtml);
        Match id = _idRegex.Match(rawHtml);
        Match quali = _qualiRegex.Match(rawHtml);

        string videotitle = title.Groups[1].Value;
        string videoid = youtubeurl.Substring(youtubeurl.IndexOf("?v=") + 3);
        string id2 = id.Groups[1].Value.Replace("%3D", "=");
        string dlurl = string.Format(getUrl, videoid, id2);

        fileext = "flv";
        if (rawHtml.Contains("'IS_HD_AVAILABLE': true")) // 1080p/720p
        {
          dlurl += "&fmt=" + quali.Groups[1].Value;
          fileext = "mp4";
        }
        else
        {
          dlurl += "&fmt=" + quali.Groups[1].Value;
          if (quali.Groups[1].Value == "18") // Medium
            fileext = "mp4";
          else if (quali.Groups[1].Value == "17") // Mobile
            fileext = "3gp";
        }
        webClient.OpenReadCompleted += new OpenReadCompletedEventHandler(client_OpenReadCompleted);
        webClient.OpenReadAsync(new Uri(dlurl));
    }

    void client_OpenReadCompleted(object sender, OpenReadCompletedEventArgs e)
    {
        var file = IsolatedStorageFile.GetUserStoreForApplication();
        file.CreateDirectory("YoutubeDownloader");

        using (IsolatedStorageFileStream stream = new IsolatedStorageFileStream("file." + fileext, System.IO.FileMode.Create, file))
        {
            byte[] buffer = new byte[1024];
            while (e.Result.Read(buffer, 0, buffer.Length) > 0)
            {
                stream.Write(buffer, 0, buffer.Length);
            }
        }
    }
}

Upvotes: 1

Views: 500

Answers (1)

Jon Skeet
Jon Skeet

Reputation: 1500983

When you copy the data from the result to isolated storage, you're always writing the entire contents of the buffer, however much you've read. Your loop should look like this:

using (var stream = new IsolatedStorageFileStream("file." + fileext,
                                                  FileMode.Create, file))
{
    byte[] buffer = new byte[1024];
    int bytesRead;
    while ((bytesRead = e.Result.Read(buffer, 0, buffer.Length)) > 0)
    {
        stream.Write(buffer, 0, bytesRead);
    }
}

(I haven't checked whether or not that's all that was wrong, but it sounds like it's helped...)

DISCLAIMER: I work for Google, but I have no idea of the legality of any of what you're doing with respect to the YouTube licence. Please don't treat this answer as any sort of indication of an opinion from Google. This answer is purely a fix to some general stream handling, as far as I'm concerned.

Upvotes: 3

Related Questions