static IEnumerable <IStreamInfo> GetOptimalStreams(StreamManifest streamManifest, Container container) { if (streamManifest.GetAudioOnlyStreams().Any() && streamManifest.GetVideoOnlyStreams().Any()) { // Include audio stream // Priority: transcoding -> bitrate yield return(streamManifest .GetAudioOnlyStreams() .OrderByDescending(s => s.Container == container) .ThenByDescending(s => s.Bitrate) .First()); // Include video stream if (!container.IsAudioOnly) { // Priority: video quality -> transcoding yield return(streamManifest .GetVideoOnlyStreams() .OrderByDescending(s => s.VideoQuality) .ThenByDescending(s => s.Container == container) .First()); } } // Use single muxed stream if adaptive streams are not available else { // Priority: video quality -> transcoding yield return(streamManifest .GetMuxedStreams() .OrderByDescending(s => s.VideoQuality) .ThenByDescending(s => s.Container == container) .First()); } }
private Utils.VideoSettings GetVideoSettings(VideoId videoId) { StreamManifest manifest = client.Videos.Streams.GetManifestAsync(videoId).Result; Utils.VideoSettings videoSettings = new Utils.VideoSettings() { StreamManifest = manifest, MuxedStreamInfo = manifest.GetMuxedStreams().ToList(), VideoOnlyStreamInfo = manifest.GetVideoOnlyStreams().ToList(), AudioOnlyStreamInfo = manifest.GetAudioOnlyStreams().ToList() }; return(videoSettings); }
private static IEnumerable <IStreamInfo> GetBestMediaStreamInfos( StreamManifest streamManifest, ConversionFormat format) { // Use single muxed stream if adaptive streams are not available if (!streamManifest.GetAudioOnlyStreams().Any() || !streamManifest.GetVideoOnlyStreams().Any()) { // Priority: video quality -> transcoding yield return(streamManifest .GetMuxedStreams() .OrderByDescending(s => s.VideoQuality) .ThenByDescending(s => !IsTranscodingRequired(s.Container, format)) .First()); yield break; } // Include audio stream // Priority: transcoding -> bitrate yield return(streamManifest .GetAudioOnlyStreams() .OrderByDescending(s => !IsTranscodingRequired(s.Container, format)) .ThenByDescending(s => s.Bitrate) .First()); // Include video stream if (!format.IsAudioOnly) { // Priority: video quality -> transcoding yield return(streamManifest .GetVideoOnlyStreams() .OrderByDescending(s => s.VideoQuality) .ThenByDescending(s => !IsTranscodingRequired(s.Container, format)) .First()); } }
public async Task DownloadTrack(MusixSongResult Track, string OutputDirectory, AudioEffectStack Effects = null, CancellationToken cancellationToken = default) { int Steps; int Step = 0; if (Effects == null) { Steps = 9; } else { Steps = 9 + Effects.EffectCount; } TryCallback(Step, Steps, "Starting Download", Track); if (cancellationToken.IsCancellationRequested) { return; } bool HasEffects = Effects != null; if (HasEffects) { Console.WriteLine("Has Effects"); if (string.IsNullOrEmpty(Effects.AudioCachePath)) { Effects.AudioCachePath = AudioCache; } } // Step 1 Step++; TryCallback(Step, Steps, "Preparing Download", Track); Console.WriteLine("Start Download"); if (!Track.HasVideo) { Console.WriteLine("No Vid"); } if (!Track.HasVideo) { return; } string SourceAudio = Path.Combine(AudioCache, $"audio_source_{DateTime.Now.Ticks}"); string AlbumCover = Path.Combine(ImageCachePath, $"cover_{DateTime.Now.Ticks}.jpg"); string OutputFile = Path.Combine(OutputDirectory, FileHelpers.ScrubFileName($"{Track.SpotifyTrack.Artists[0].Name} - {Track.SpotifyTrack.Name.Replace("?", "").Trim(' ')}.mp3")); string MidConversionFile = Path.Combine(AudioCache, FileHelpers.ScrubFileName($"MidConversion_{DateTime.Now.Ticks}.mp3")); // Step 2 Step++; TryCallback(Step, Steps, "Aquiring streams", Track); StreamManifest StreamData = await YouTube.Videos.Streams.GetManifestAsync(Track.YoutubeVideo.Id); if (cancellationToken.IsCancellationRequested) { return; } // Step 3 Step++; TryCallback(Step, Steps, "Sorting Streams", Track); List <AudioOnlyStreamInfo> AudioStreams = StreamData.GetAudioOnlyStreams().ToList(); AudioStreams.OrderBy(dat => dat.Bitrate); if (AudioStreams.Count() == 0) { Console.WriteLine("No Streams"); } if (AudioStreams.Count() == 0) { return; } IAudioStreamInfo SelectedStream = AudioStreams[0]; // Step 4 Step++; TryCallback(Step, Steps, "Starting downloads", Track); if (cancellationToken.IsCancellationRequested) { return; } //Task AudioDownloadTask = new Task(async () => await YouTube.Videos.Streams.DownloadAsync(SelectedStream, SourceAudio)); var req = WebRequest.CreateHttp(SelectedStream.Url); req.Method = "GET"; using (var resp = req.GetResponse()) using (var network = resp.GetResponseStream()) using (var fs = new FileStream(SourceAudio, FileMode.OpenOrCreate, FileAccess.ReadWrite)) { Console.WriteLine("Downloading"); await network.CopyToAsync(fs); Console.WriteLine("flushing"); await fs.FlushAsync(); Console.WriteLine("done"); } WebClient WebCl = new WebClient(); Step++; TryCallback(Step, Steps, "Starting", Track); SpotifyImage Cover = Track.SpotifyTrack.Album.Images[0]; var CoverDownloadTask = new Task(() => { Console.WriteLine("Downloading Cover"); WebCl.DownloadFile(new Uri(Cover.Url), AlbumCover); } ); CoverDownloadTask.Start(); Step++; TryCallback(Step, Steps, "Waiting for downloads", Track); if (cancellationToken.IsCancellationRequested) { return; } //if (!AudioDownloadTask.IsCompleted) //{ // Console.WriteLine("Waiting on artwork..."); // CoverDownloadTask.Wait(); //} if (cancellationToken.IsCancellationRequested) { return; } //if (!AudioDownloadTask.IsCompleted) //{ // Console.WriteLine("Waiting on audio..."); // AudioDownloadTask.Wait(); // Console.WriteLine("Download Complete."); //} Thread.Sleep(100); if (cancellationToken.IsCancellationRequested) { return; } string ConversionFile = OutputFile; if (HasEffects) { ConversionFile = MidConversionFile; } if (File.Exists(OutputFile)) { File.Delete(OutputFile); } if (File.Exists(ConversionFile)) { File.Delete(ConversionFile); } Step++; TryCallback(Step, Steps, "Transcoding audio to mp3", Track); // Step 8 Console.WriteLine("Starting Conversion..."); await ConversionsProvider.Convert(SourceAudio, ConversionFile); Console.WriteLine("Conversion Complete."); // Step 9 if (cancellationToken.IsCancellationRequested) { return; } if (HasEffects) { Step++; int InternalStep = Step; TryCallback(Step, Steps, "Applying audio effects", Track); Effects.ApplyEffects(ConversionFile, OutputFile, (step, stepmax, status, download) => { step++; TryCallback(Step, Steps, status, Track); }, cancellationToken); } if (cancellationToken.IsCancellationRequested) { return; } Step++; TryCallback(Step, Steps, "Applying ID3 metadata tags", Track); // Step 10 TagLib.Id3v2.Tag.DefaultVersion = 3; TagLib.Id3v2.Tag.ForceDefaultVersion = true; TagLibFile TLF = TagLibFile.Create(OutputFile); TagLibPicture Pic = new TagLibPicture(AlbumCover); TagLib.Id3v2.AttachedPictureFrame Frame = new TagLib.Id3v2.AttachedPictureFrame(Pic) { MimeType = System.Net.Mime.MediaTypeNames.Image.Jpeg }; Pic.Type = TagLib.PictureType.FrontCover; TagLib.IPicture[] Pics = { Pic }; TLF.Tag.Pictures = Pics; TLF.Tag.Title = Track.SpotifyTrack.Name.Split('-')[0].Trim(' '); TLF.Tag.Album = Track.SpotifyTrack.Album.Name; TLF.Tag.AlbumArtists = Track.SpotifyTrack.Album.Artists.CastEnumerable(x => x.Name).ToArray(); TLF.Tag.Disc = (uint)Track.SpotifyTrack.DiscNumber; TLF.Tag.AlbumSort = Track.SpotifyTrack.Album.AlbumType; DateTime?DT = GetDate(Track.SpotifyTrack.Album.ReleaseDate); if (DT.HasValue) { TLF.Tag.Year = (uint)DT.Value.Year; } if (cancellationToken.IsCancellationRequested) { return; } TLF.Save(); // Clean Up // Step 11 Step++; TryCallback(Step, Steps, "Cleaning up", Track); WebCl.Dispose(); TLF.Dispose(); Console.WriteLine("Done."); OnMusixDownloadComplete?.Invoke(Track); }
public async Task SendYoutubeAudioAsync(IMessage message, IGuildUser user, string query) { // Check that we have a query if (string.IsNullOrWhiteSpace(query)) { return; } if (this.connectedChannels.TryGetValue(user.GuildId, out AudioClient audioClient)) { VideoInfo videoInfo = new VideoInfo(user.GetName()); // Try to parse the url given to return just the video id string id; if (query.Contains("v=") && query.Length >= 3) { if (query.Contains("&")) { id = Regex.Match(query, "v=(.*?)&").ToString(); id = id.Substring(2, id.Length - 3); } else { id = Regex.Match(query, "v=(.*?)$").ToString(); id = id.Substring(2, id.Length - 2); } YoutubeExplode.Videos.Video video = await youtube.Videos.GetAsync(id); videoInfo.Title = video.Title; videoInfo.Duration = video.Duration.ToString(); videoInfo.Thumbnail = video.Thumbnails.GetFirst().Url; } else { // Get the stream from YT via search IReadOnlyList <YoutubeExplode.Search.VideoSearchResult> searchResult = await youtube.Search.GetVideosAsync(query).CollectAsync(1); YoutubeExplode.Search.VideoSearchResult result = searchResult.GetFirst(); videoInfo.Title = result.Title; videoInfo.Duration = result.Duration.ToString(); videoInfo.Thumbnail = result.Thumbnails.GetFirst().Url; id = result.Id; } // Get the stream from YT via video id StreamManifest streamManifest = await youtube.Videos.Streams.GetManifestAsync(id); AudioOnlyStreamInfo streamInfo = streamManifest.GetAudioOnlyStreams().GetFirst(); videoInfo.Stream = streamInfo; // If song currently playing, add to playlist if (audioClient.CurrentStream != null) { audioClient.PlayList.Add(videoInfo); // Delete calling command await message.DeleteAsync(); } else { // Play song audioClient.CurrentSong = videoInfo; this.StartStream(youtube, audioClient, streamInfo, message); } } }