Html error when downloading youtube video - html
I downloaded a Youtube downloader from Github it was a WPF and it works however I want to reproduce this C# for Windows App. The original code from WPF is:
public async Task BeginDownload()
{
if (!CheckInputs())
return;
ChangeButtonStates(false);
string link = videoLink.Text;
string? downloadFormat = null;
string savedDirectory = Properties.Settings.Default.savedDirectory;
if (saveMP3.IsChecked == true)
downloadFormat = "mp3";
else
downloadFormat = "mp4";
try
{
cancellationToken = cancellationTokenSource.Token;
// If the given URL contains "&list" it means it is playlist
if (!link.Contains("&list"))
await DownloadSingle(link, savedDirectory, downloadFormat);
else
await DownloadPlaylist(link, savedDirectory, downloadFormat);
}
catch (Exception ex)
{
new Thread(() =>
{
MessageBox.Show($"An error occurred: \"{ex.Message}\".", "Downloader", MessageBoxButton.OK, MessageBoxImage.Error);
}).Start();
}
ChangeButtonStates(true);
}
My code converted for use with windows form
public async Task BeginDownload()
{
if (!CheckInputs())
return;
ChangeButtonStates(false);
string link = videoLink.Text;
string downloadFormat = null;
string savedDirectory = Properties.Settings.Default.savedDirectory;
if (cmbDownloadType.SelectedIndex == 1)
downloadFormat = "mp3";
else
downloadFormat = "mp4";
try
{
cancellationToken = cancellationTokenSource.Token;
//// If the given URL contains "&list" it means it is playlist
//if (!link.Contains("&list"))
await DownloadSingle(link, savedDirectory, downloadFormat);
//else
//await DownloadPlaylist(link, savedDirectory, downloadFormat);
}
catch (Exception ex)
{
new Thread(() =>
{
MessageBox.Show($"An error occurred: \"{ex.Message}\".", "Downloader", MessageBoxButtons.OK, MessageBoxIcon.Error);
}).Start();
}
ChangeButtonStates(true);
}
for simplicity I commented out playlist I can add it later I only want to start with a single download. When I run my code it get a html error not sure how to troubleshoot the error.
WPF code to download single
public async Task DownloadSingle(string link, string path, string format)
{
// Needed for security
var handler = new HttpClientHandler();
var httpClient = new HttpClient(handler, true);
handler.UseCookies = false;
// Get video data
var youtube = new YoutubeClient(httpClient);
var streamData = await youtube.Videos.GetAsync(link);
var title = ReplaceInvalidCharacters(streamData.Title);
var progress = new Progress<double>(value =>
{
// To split the progress bar into two halves, fill one half and then the next,
// maximum of both progress bars is 50
if (downloadProgressOne.Value != 50)
{
downloadProgressOne.Value = value * 100.00f;
}
else
{
downloadProgressTwo.Value = (value * 100.00f) - 50;
}
// Taskbar icon progress bar
taskbarIcon.ProgressValue = value;
downloadStatus.Text = $"Downloading... {Convert.ToInt32(value * 100.00f)}%";
});
try
{
// Download content
await youtube.Videos.DownloadAsync(link, $"{path}\\{title}.{format}", o => o.SetContainer(format).SetPreset(ConversionPreset.UltraFast), progress, cancellationToken);
}
catch (TaskCanceledException)
{
new Thread(() =>
{
MessageBox.Show($"Successfully cancelled the download of: \"{title}\".", "Downloader", MessageBoxButton.OK, MessageBoxImage.Information);
}).Start();
File.Delete($"{path}\\{title}.{format}");
return;
}
catch (Exception ex)
{
new Thread(() =>
{
MessageBox.Show($"Failed to download video: \"{title}\" due to an error.\n\nReason: \"{ex.Message}\".", "Downloader", MessageBoxButton.OK, MessageBoxImage.Warning);
}).Start();
return;
}
new Thread(() =>
{
MessageBox.Show($"Successfully downloaded video: \"{title}\".", "Downloader", MessageBoxButton.OK, MessageBoxImage.Information);
}).Start();
}
public async Task DownloadPlaylist(string link, string path, string format)
{
// Create a string list incase any videos fail to download
List<string> failedVideosTitles = new();
string finalList = "";
int failedVideosAmount = 0;
// Needed for security
var handler = new HttpClientHandler();
var httpClient = new HttpClient(handler, true);
handler.UseCookies = false;
// Get playlist data
var youtube = new YoutubeClient(httpClient);
var playlistData = await youtube.Playlists.GetAsync(link);
var playlistName = ReplaceInvalidCharacters(playlistData.Title);
var total = await youtube.Playlists.GetVideosAsync(link);
var totalNumber = total.Count;
int currentNumber = 0;
// Foreach video in the playlist try to download them as the desired format
await foreach (var video in youtube.Playlists.GetVideosAsync(playlistData.Id))
{
currentNumber++;
var title = ReplaceInvalidCharacters(video.Title);
// Skip download of video if it already exists
if (File.Exists($"{path}\\{title}.{format}"))
{
downloadStatus.Text = $"Skipping {currentNumber}/{totalNumber}...";
await Task.Delay(100);
continue;
}
var progress = new Progress<double>(value =>
{
// To split the progress bar into two halves, fill one half and then the next,
// maximum of both progress bars is 50
if (value < 0.5f || downloadProgressOne.Value < 50)
{
downloadProgressOne.Value = value * 100.00f;
downloadProgressTwo.Value = 0;
}
else
downloadProgressTwo.Value = (value * 100.00f) - 50;
// Taskbar icon progress bar
taskbarIcon.ProgressValue = value;
downloadStatus.Text = $"Downloading... {currentNumber}/{totalNumber} - {Convert.ToInt32(value * 100.00f)}%";
});
try
{
// Download content
await youtube.Videos.DownloadAsync(video.Id, $"{path}\\{title}.{format}", o => o.SetContainer(format).SetPreset(ConversionPreset.UltraFast), progress, cancellationToken);
}
catch (TaskCanceledException)
{
new Thread(() =>
{
MessageBox.Show($"Successfully cancelled the download of playlist: \"{playlistName}\".\n\nFiles have not been deleted.", "Downloader", MessageBoxButton.OK, MessageBoxImage.Information);
}).Start();
File.Delete($"{path}\\{title}.{format}");
return;
}
catch (Exception ex)
{
new Thread(() =>
{
// Increase the failed videos amount by one and add the title to the list
failedVideosAmount++;
failedVideosTitles.Add($"\"{title}\"");
MessageBox.Show($"Skipping download of video: \"{title}\" due to an error.\n\nReason: \"{ex.Message}\".", "Downloader", MessageBoxButton.OK, MessageBoxImage.Warning);
}).Start();
}
}
if (failedVideosAmount != 0)
{
new Thread(() =>
{
// Show a messagebox telling the user it failed to download X amount of videos
MessageBox.Show($"Downloaded playlist: \"{playlistName}\" but failed to download {failedVideosAmount} of the videos.\n\nPress OK to see list of failed videos.", "Downloader", MessageBoxButton.OK, MessageBoxImage.Warning);
// Loop for the length of the string list, build a final string containing
// a list of titles of failed videos then display it in a messagebox for the user
for (int i = 0; i < failedVideosTitles.Count; i++)
{
if (i == 0) { finalList = $"{finalList}{i + 1}. {failedVideosTitles[i]}."; }
else { finalList = $"{finalList}\n\n{i + 1}. {failedVideosTitles[i]}."; }
}
MessageBox.Show(finalList, "Downloader", MessageBoxButton.OK, MessageBoxImage.Information);
}).Start();
}
else
{
new Thread(() =>
{
// The entire playlist was downloaded successfully
MessageBox.Show($"Successfully downloaded playlist: \"{playlistName}\".", "Downloader", MessageBoxButton.OK, MessageBoxImage.Information);
}).Start();
}
}
my converted code
public async Task DownloadSingle(string link, string path, string format)
{
// Needed for security
var handler = new HttpClientHandler();
var httpClient = new HttpClient(handler, true);
handler.UseCookies = false;
// Get video data
var youtube = new YoutubeClient(httpClient);
var streamData = await youtube.Videos.GetAsync(link);
var title = ReplaceInvalidCharacters(streamData.Title);
var progress = new Progress<double>(value =>
{
// To split the progress bar into two halves, fill one half and then the next,
// maximum of both progress bars is 50
if (downloadProgressOne.Value != 50)
{
downloadProgressOne.Value = (int)(value * 100.00f);
}
else
{
downloadProgressTwo.Value = (int)((value * 100.00f) - 50);
}
// Taskbar icon progress bar
//taskbarIcon.ProgressValue = value;
downloadStatus.Text = $"Downloading... {Convert.ToInt32(value * 100.00f)}%";
});
try
{
// Download content
await youtube.Videos.DownloadAsync(link, $"{path}\\{title}.{format}", o => o.SetContainer(format).SetPreset(ConversionPreset.UltraFast), progress, cancellationToken);
}
catch (TaskCanceledException)
{
new Thread(() =>
{
MessageBox.Show($"Successfully cancelled the download of: \"{title}\".", "Downloader", MessageBoxButtons.OK, MessageBoxIcon.Information);
}).Start();
File.Delete($"{path}\\{title}.{format}");
return;
}
catch (Exception ex)
{
new Thread(() =>
{
MessageBox.Show($"Failed to download video: \"{title}\" due to an error.\n\nReason: \"{ex.Message}\".", "Downloader", MessageBoxButtons.OK, MessageBoxIcon.Warning);
}).Start();
return;
}
new Thread(() =>
{
MessageBox.Show($"Successfully downloaded video: \"{title}\".", "Downloader", MessageBoxButtons.OK, MessageBoxIcon.Information);
}).Start();
}
Argh rookie mistake just had to update the nuget package for codepages.
Related
How to manage and control content of Webview2 Tab from main tab
I have a dynamic webview2 tab with URL loaded during 1st tab creation. my question is how to update the URL on the tab created via the main page form? Is any possibility event handler and proper instance method data source URL on tab panel can be reloaded? method create dynamic tab private async void CreateNewTabAsync(string appname, string url) { try { TabPage page1 = new TabPage(); page1.Name = appname; page1.Text = appname; Microsoft.Web.WebView2.WinForms.WebView2 webviewnew = new Microsoft.Web.WebView2.WinForms.WebView2(); webviewnew.Name = "webView2" + appname; webviewnew.Dock = System.Windows.Forms.DockStyle.Fill; var userDataFolder = #System.Configuration.ConfigurationManager.AppSettings["path"]; var env = await CoreWebView2Environment.CreateAsync(null, userDataFolder); await webviewnew.EnsureCoreWebView2Async(env); webviewnew.Source = new Uri(url); // handling new page webviewnew.CoreWebView2.NewWindowRequested += webViewnew_NewWindowRequested; page1.Controls.Add(webviewnew); tabControl1.TabPages.Add(page1); int indexpag = tabControl1.TabPages.IndexOfKey(appname); this.tabControl1.SelectedTab = this.tabControl1.TabPages[indexpag]; foreach (TabPage tp in tabControl1.TabPages) { tp.Show(); } } catch (Exception err) { _logger.Error("error loading new window " + err.Message); } } code for handling event new window private void webViewnew_NewWindowRequested(object sender, CoreWebView2NewWindowRequestedEventArgs e) { e.Handled = true; string address = string.Empty; string tabname = string.Empty; address = e.Uri; if (address.Contains("www.msn.com")) { tabname = "msn"; } else { tabname = "otherSite"; } try { int indexpag = tabControl1.TabPages.IndexOfKey(tabname); if (indexpag == 0 || indexpag < 0) { \\ create new tab and load URL CreateNewTabAsync(tabname, address); } else { \\ open the tab, make focus,and load URL this.tabControl1.SelectedTab = this.tabControl1.TabPages[indexpag]; \\ URL still reflect to the origin url } } catch (Exception exc) { _logger.Error("open new tab aplication error with " + exc.Message); } }
How to send JSON objects to another computer?
Using Websockets, I am able to use 1 computer and 1 kinect v2.0 to generate JSON objects of the joints x,y, and z coordinates in real-time. The next steps is to have this data transferred to another computer, using possibly TCP/IP network. My question is to anyone who knows how this is done. Having this data transferred to another computer. Output that needs to be transferred to another computer in real-time namespace WebSockets.Server { class Program { // Store the subscribed clients. static List<IWebSocketConnection> clients = new List<IWebSocketConnection>(); // Initialize the WebSocket server connection. static Body[] bodies = new Body[6]; //static KinectSensor kinectSensor = null; static CoordinateMapper _coordinateMapper; static Mode _mode = Mode.Color; static void Main(string[] args) { //const string SkeletonStreamName = "skeleton"; //SkeletonStreamMessage skeletonStreamMessage;// = new SkeletonStreamMessage { stream = SkeletonStreamName }; KinectSensor kinectSensor = KinectSensor.GetDefault(); BodyFrameReader bodyFrameReader = null; bodyFrameReader = kinectSensor.BodyFrameSource.OpenReader(); ColorFrameReader colorFrameReader = null; colorFrameReader = kinectSensor.ColorFrameSource.OpenReader(); _coordinateMapper = kinectSensor.CoordinateMapper; kinectSensor.Open(); WebSocketServer server = new WebSocketServer("ws://localhost:8001"); server.Start(socket => { socket.OnOpen = () => { // Add the incoming connection to our list. clients.Add(socket); }; socket.OnClose = () => { // Remove the disconnected client from the list. clients.Remove(socket); }; socket.OnMessage = message => { if (message == "get-video") { int NUMBER_OF_FRAMES = new DirectoryInfo("Video").GetFiles().Length; // Send the video as a list of consecutive images. for (int index = 0; index < NUMBER_OF_FRAMES; index++) { foreach (var client in clients) { string path = "Video/" + index + ".jpg"; byte[] image = ImageUtil.ToByteArray(path); client.Send(image); } // We send 30 frames per second, so sleep for 34 milliseconds. System.Threading.Thread.Sleep(270); } } else if (message == "get-bodies") { if (kinectSensor.IsOpen) { if (bodyFrameReader != null) { bodyFrameReader.FrameArrived += bodyFrameReader_FrameArrived; } } } else if (message == "get-color") { if (kinectSensor.IsOpen) { if (colorFrameReader != null) { colorFrameReader.FrameArrived += colorFrameReader_FrameArrived; } } } }; }); // Wait for a key press to close... Console.ReadLine(); kinectSensor.Close(); } private static void colorFrameReader_FrameArrived(object sender, ColorFrameArrivedEventArgs e) { //throw new NotImplementedException(); using (ColorFrame colorFrame = e.FrameReference.AcquireFrame()) { if (colorFrame != null) { var blob = colorFrame.Serialize(); foreach (var client in clients) { if (blob != null) { client.Send(blob); Console.WriteLine("After color Blob sent"); } } } } } private static void bodyFrameReader_FrameArrived(object sender, BodyFrameArrivedEventArgs e) { //throw new NotImplementedException(); bool dataReceived = false; using (BodyFrame bodyFrame = e.FrameReference.AcquireFrame()) { if (bodyFrame != null) { if (bodies == null) { bodies = new Body[bodyFrame.BodyCount]; } // The first time GetAndRefreshBodyData is called, Kinect will allocate each Body in the array. // As long as those body objects are not disposed and not set to null in the array, // those body objects will be re-used. bodyFrame.GetAndRefreshBodyData(bodies); dataReceived = true; } } if (dataReceived) { foreach (var client in clients) { var users = bodies.Where(s => s.IsTracked.Equals(true)).ToList(); if (users.Count>0){ string json = users.Serialize(_coordinateMapper, _mode); Console.WriteLine("jsonstring: " + json); Console.WriteLine("After body serialization and to send"); } } } } } }
Try changing it from WebSocketServer server = new WebSocketServer("ws://localhost:8001"); to WebSocketServer server = new WebSocketServer(" ws://192.168.X.X:8001"); on the client end. Enter the IP address of the client computer and make sure both server and client are on the same network.
Get Thumbnail in Vimeo
Is there any way to get the thumbnail from server side call? The only method that I researched is: $.getJSON('http://www.vimeo.com/api/v2/video/' + vimeoVideoId + '.json?callback=?', { format: "json" }, function (data) { $(".thumbnail").attr('src', data[0].thumbnail_medium); }); Is there a way to make the same call from code behind? or is there a single URL call like in youtube img.youtube.com/vi/{0}/0.jpg
List item I found a way to do this from code behind: public static string GetVimeoPreviewImage(string videoId) { var imageUrl = string.Empty; try { var doc = new XmlDocument(); doc.Load("http://vimeo.com/api/v2/video/" + videoId + ".xml"); var root = doc.DocumentElement; if (root != null) { var selectSingleNode = root.FirstChild.SelectSingleNode("thumbnail_medium"); if (selectSingleNode != null) { var vimeoThumb = selectSingleNode.ChildNodes[0].Value; imageUrl = vimeoThumb; return imageUrl; } } } catch (Exception ex) { var message = string.Format("{0} Exception: {1}", typeof(VideoHelper).FullName, ex.Message); Log.Error(message, typeof(VideoHelper)); } return imageUrl; }
WP8 Some images not downloading using HttpClient
I am building a WP8 app that downloads images using HttpClient in a background task. My problem is that some images are not downloaded no matter how much time I wait for them to finish. The image sizes are a few megabytes at maximum. The code I use to download images: internal static async Task<bool> Download_Wallpaper(string image_url, string file_name, string destination_folder_name) { try { using (var client = new HttpClient()) { // 12MB max images client.Timeout = TimeSpan.FromSeconds(5); client.MaxResponseContentBufferSize = DeviceStatus.ApplicationMemoryUsageLimit / 2; //client.Timeout = TimeSpan.FromSeconds(5); byte[] image_byte_arr; try { /* var requestMessage = new HttpRequestMessage( HttpMethod.Get, image_url ); var responseMessage = await client.SendAsync((requestMessage)); // byte array of image image_byte_arr = await responseMessage.Content.ReadAsByteArrayAsync(); */ // byte array of image image_byte_arr = await client.GetByteArrayAsync(image_url); } // Could not download catch (OutOfMemoryException X) { GC.Collect(); return false; } var folder = await StorageFolder.GetFolderFromPathAsync(destination_folder_name); // Create file StorageFile file = await folder.CreateFileAsync(file_name, CreationCollisionOption.ReplaceExisting); using (var write_stream = await file.OpenStreamForWriteAsync()) { write_stream.Write(image_byte_arr, 0, image_byte_arr.Length); } Console.WriteLine(DeviceStatus.ApplicationCurrentMemoryUsage); return true; } } catch (HttpRequestException X) { Console.WriteLine(X); return false; } catch (OutOfMemoryException X) { GC.Collect(); return false; } catch (Exception X) { Console.WriteLine(X); return false; } } This is an example image that fails to download: https://upload.wikimedia.org/wikipedia/commons/9/95/Tracy_Caldwell_Dyson_in_Cupola_ISS.jpg In my experience all wikimedia images fail to download for some reason. I see no way of tracking download progress using HttpClient. Is there a way to do so? Edit: It seems that setting the timeout does not have any function. The HttpRequestException is not thrown after 5 seconds. Edit2: I tried a different approach, the one that anonshankar suggested. With that method the code would get stuck at the line: byte[] img = response.Content.ReadAsByteArrayAsync(); So the HttpResponse arrives, but somehow the bytes could not be read out, no matter how much time I gave it. How could this even happen? The hard part is getting the response, reading out the bytes should be simple. Again, this only happens with some images, most of them downloads correctly. One example is mentioned above. I have modified my image downloader code, so that it times out after a few seconds. Here is my final code: internal static async Task<bool> Download_Wallpaper(string image_url, string file_name, string destination_folder_name) { try { using (var client = new HttpClient()) { // prevent running out of memory client.MaxResponseContentBufferSize = DeviceStatus.ApplicationMemoryUsageLimit / 3; byte[] image_byte_arr = null; using (CancellationTokenSource cts = new CancellationTokenSource()) { var task = Task.Factory.StartNew(() => { try { image_byte_arr = client.GetByteArrayAsync(image_url).Result; } catch (AggregateException X)// Handling read errors, usually image is too big { Console.WriteLine(X.Message); foreach (var v in X.InnerExceptions) Console.WriteLine(v.Message); image_byte_arr = null; } }, cts.Token); bool finished_in_time = task.Wait(TimeSpan.FromSeconds(5)); if (!finished_in_time)// Timeout { cts.Cancel(); task.Wait(); return false; } else if (image_byte_arr == null)// Read error { return false; } } var folder = await StorageFolder.GetFolderFromPathAsync(destination_folder_name); // Create file StorageFile file = await folder.CreateFileAsync(file_name, CreationCollisionOption.ReplaceExisting); using (var write_stream = await file.OpenStreamForWriteAsync()) { write_stream.Write(image_byte_arr, 0, image_byte_arr.Length); } Console.WriteLine(DeviceStatus.ApplicationCurrentMemoryUsage); return true; } } catch (HttpRequestException X) { Console.WriteLine(X); return false; } catch (OutOfMemoryException X) { GC.Collect(); return false; } catch (Exception X) { Console.WriteLine(X); return false; } } Any improvement suggestions are welcome, and I still don't understand why does the method HttpContent.ReadAsByteArrayAsync() gets stuck.
Just try out this snippet which worked for me. HttpClient client = new HttpClient(); HttpResponseMessage response = await client.GetAsync("give the url"); byte[] img = response.Content.ReadAsByteArray(); InMemoryRandomAccessStream randomAccessStream = new InMemoryRandomAccessStream(); DataWriter writer = new DataWriter(randomAccessStream.GetOutputStreamAt(0)); writer.WriteBytes(img); await writer.StoreAsync(); BitmapImage b = new BitmapImage(); b.SetSource(randomAccessStream); pic.Source = b; //(pic is an `<Image>` defined in the `XAML` Hope it helps!
When uploading Photo to Web API always 0 bytes
I have the following, and it uploads without errors, but the image is always 0 bytes. Windows Phone App (this is called after selecting or taking a photo): private void AddImage(PhotoResult e) { if (e.TaskResult == TaskResult.OK) { string serviceUri = Globals.GreedURL + #"API/UploadPhoto/test5.jpg"; HttpWebRequest request = (HttpWebRequest)HttpWebRequest.Create(serviceUri); request.Method = "POST"; request.BeginGetRequestStream(result => { Stream requestStream = request.EndGetRequestStream(result); e.ChosenPhoto.CopyTo(requestStream); requestStream.Close(); request.BeginGetResponse(result2 => { try { HttpWebResponse response = (HttpWebResponse)request.EndGetResponse(result2); if (response.StatusCode == HttpStatusCode.Created) { this.Dispatcher.BeginInvoke(() => { MessageBox.Show("Upload completed."); }); } else { this.Dispatcher.BeginInvoke(() => { MessageBox.Show("An error occured during uploading. Please try again later."); }); } } catch { this.Dispatcher.BeginInvoke(() => { MessageBox.Show("An error occured during uploading. Please try again later."); }); } e.ChosenPhoto.Close(); }, null); }, null); } And here is the Web API: public class UploadPhotoController : ApiController { public HttpResponseMessage Post([FromUri]string filename) { var task = this.Request.Content.ReadAsStreamAsync(); task.Wait(); Stream requestStream = task.Result; // Retrieve storage account from connection string. CloudStorageAccount storageAccount = CloudStorageAccount.Parse(ConfigurationManager.ConnectionStrings["StorageConnectionString"].ConnectionString); // Create the blob client. CloudBlobClient blobClient = storageAccount.CreateCloudBlobClient(); // Retrieve reference to a previously created container. CloudBlobContainer container = blobClient.GetContainerReference("profilepics"); container.CreateIfNotExists(); var permissions = container.GetPermissions(); permissions.PublicAccess = BlobContainerPublicAccessType.Blob; container.SetPermissions(permissions); string uniqueBlobName = string.Format("test.jpg"); CloudBlockBlob blob = container.GetBlockBlobReference(uniqueBlobName); blob.Properties.ContentType = "image\\jpeg"; blob.UploadFromStream(task.Result); HttpResponseMessage response = new HttpResponseMessage(); response.StatusCode = HttpStatusCode.Created; return response; } } Any ideas? Any help would be appreciated.