private async Task PlaySong(YoutubeExplode.Videos.Video input) { try { await audioClient.SetSpeakingAsync(true); var streamManifest = await youtube.Videos.Streams.GetManifestAsync(input.Id, Skip.Token); var streamInfo = streamManifest.GetAudioOnlyStreams().GetWithHighestBitrate(); var stream = await youtube.Videos.Streams.GetAsync(streamInfo, Skip.Token); var memoryStream = new MemoryStream(); await Cli.Wrap("ffmpeg") .WithArguments(" -hide_banner -loglevel panic -i pipe:0 -ac 2 -f s16le -ar 48000 pipe:1") .WithStandardInputPipe(PipeSource.FromStream(stream)) .WithStandardOutputPipe(PipeTarget.ToStream(memoryStream)) .ExecuteAsync(Skip.Token); using (var discord = audioClient.CreatePCMStream(AudioApplication.Music)) { try { await discord.WriteAsync(memoryStream.ToArray(), 0, (int)memoryStream.Length, Skip.Token); } finally { await discord.FlushAsync(); } } } catch (Exception) { } }
private async void StartStream(YoutubeClient youtube, AudioClient audioClient, AudioOnlyStreamInfo streamInfo, IMessage?message) { Stream ytStream = await youtube.Videos.Streams.GetAsync(streamInfo); // Convert yt stream MemoryStream memoryStream = new MemoryStream(); await Cli.Wrap("ffmpeg") .WithArguments(" -hide_banner -loglevel panic -i pipe:0 -ac 2 -f s16le -ar 48000 pipe:1") .WithStandardInputPipe(PipeSource.FromStream(ytStream)) .WithStandardOutputPipe(PipeTarget.ToStream(memoryStream)) .ExecuteAsync(); // Clear stream before beginning if (audioClient.CurrentStream != null) { audioClient.CurrentStream.Dispose(); audioClient.CurrentStream = null; } AudioOutStream discord = audioClient.Client.CreatePCMStream(AudioApplication.Mixed); audioClient.CurrentStream = discord; // Delete calling command if (message != null) { await message.DeleteAsync(); } // Start playing music await this.WriteStreamToVoiceChannel(audioClient, discord, memoryStream); }
public async Task SendYTAudioAsync(IGuild guild, IMessageChannel channel, IVoiceChannel target, string path, double volume = 1.0) { volume *= 0.25; CurrentAudioInformation client; if (CurrentAudioClients.TryGetValue(guild.Id, out client)) { await CheckAudioClient(guild, target, client.client); string youtubeID = GetYouTubeVideoIdFromUrl(path); if (youtubeID == null) { await channel.SendMessageAsync("That is not a valid youtube link!"); return; } if (!string.IsNullOrEmpty(client.playing)) { client.queue.Enqueue(path); await channel.SendMessageAsync($"Added {path} to the queue."); return; } client.playing = path; await _log.LogAsync(new LogMessage(LogSeverity.Info, "Audio", $"Starting playback of {path} in {guild.Name}")); if (client.currentStream == null) { client.currentStream = client.client.CreatePCMStream(AudioApplication.Mixed, 98304, 200); } var youtube = new YoutubeClient(); var streamManifest = await youtube.Videos.Streams.GetManifestAsync(youtubeID); var streamInfo = streamManifest.GetAudioOnlyStreams().GetWithHighestBitrate(); var memoryStream = new MemoryStream(); var video = await youtube.Videos.Streams.GetAsync(streamInfo); await Cli.Wrap("ffmpeg") .WithArguments($"-hide_banner -loglevel panic -i pipe:0 -filter:a \"volume = {volume}\" -ac 2 -f s16le -ar 48000 pipe:1") .WithStandardInputPipe(PipeSource.FromStream(video)) .WithStandardOutputPipe(PipeTarget.ToStream(memoryStream)) .ExecuteAsync(); try { client.cancelTokenSource = new CancellationTokenSource(); await client.currentStream.WriteAsync(memoryStream.ToArray(), 0, (int)memoryStream.Length, client.cancelTokenSource.Token); } catch (OperationCanceledException e) { await channel.SendMessageAsync($"Stopped http://youtu.be/{youtubeID}"); } finally { await _log.LogAsync(new LogMessage(LogSeverity.Verbose, "Audio", $"Finished playing {path}.")); await CheckQueue(guild, channel, target); } } else { await JoinAudio(guild, target); await SendYTAudioAsync(guild, channel, target, path, volume); } }