From ddf054dfd9b961d933b19043a226f88af8d94194 Mon Sep 17 00:00:00 2001 From: Standley Gury Date: Wed, 12 Aug 2026 20:56:55 +0800 Subject: [PATCH] fix: Use yt-dlp for YouTube title lookups and avoid failing play on title errors --- .../Interaction/NetCordInteraction.cs | 12 ++++++- src/Infrastructure/Services/YoutubeService.cs | 33 +++++++++++++++++++ 2 files changed, 44 insertions(+), 1 deletion(-) diff --git a/src/Infrastructure/Interaction/NetCordInteraction.cs b/src/Infrastructure/Interaction/NetCordInteraction.cs index db13d58..d92ee8e 100644 --- a/src/Infrastructure/Interaction/NetCordInteraction.cs +++ b/src/Infrastructure/Interaction/NetCordInteraction.cs @@ -40,7 +40,17 @@ public async Task Play() return "The requested song is blacklisted and cannot be played."; } - var title = await youtubeService.GetVideoTitleAsync(selectedValue, CancellationToken.None); + string title; + try + { + title = await youtubeService.GetVideoTitleAsync(selectedValue, CancellationToken.None); + } + catch (Exception ex) + { + logger.LogWarning(ex, "Failed to fetch title for {Url}, enqueueing without a title", selectedValue); + title = "the requested track"; + } + message = $"Added {title} to the queue!"; } else diff --git a/src/Infrastructure/Services/YoutubeService.cs b/src/Infrastructure/Services/YoutubeService.cs index 3c0a278..1e4df7a 100644 --- a/src/Infrastructure/Services/YoutubeService.cs +++ b/src/Infrastructure/Services/YoutubeService.cs @@ -146,6 +146,39 @@ public async Task GetAudioStreamUrlAsync(string url, CancellationToken c public async Task GetVideoTitleAsync(string url, CancellationToken cancellationToken) { + var (success, title) = await ExecuteWithTimeout(TryGetTitleWithYtDlpAsync, url, TimeSpan.FromSeconds(15), cancellationToken); + if (success) + { + return title!; + } + return (await _youtubeClient.Videos.GetAsync(url, cancellationToken)).Title; } + + private async Task<(bool Success, string? Url)> TryGetTitleWithYtDlpAsync(string url, CancellationToken cancellationToken) + { + try + { + var ytdl = new YoutubeDL { YoutubeDLPath = "yt-dlp" }; + var result = await ytdl.RunVideoDataFetch(url, ct: cancellationToken); + + if (!result.Success || string.IsNullOrWhiteSpace(result.Data?.Title)) + { + _logger.LogWarning("YT-DLP title fetch failed for: {Url}. Errors: {Errors}", url, + string.Join("; ", result.ErrorOutput ?? [])); + return (false, null); + } + + return (true, result.Data.Title); + } + catch (OperationCanceledException) + { + throw; + } + catch (Exception ex) + { + _logger.LogWarning(ex, "YT-DLP title fetch failed for: {Url}", url); + return (false, null); + } + } }