/// <summary> /// Plays the audio. /// </summary> /// <param name="voiceNextCon">The voice next con.</param> /// <param name="filename">The filename.</param> /// <returns>Completed Task once the audio finishes playing</returns> public async Task PlayAudio(VoiceNextConnection voiceNextCon, string filename) { // wait for current playback to finish while (voiceNextCon.IsPlaying) { Program.Client.DebugLogger.Info($"Waiting for current audio to finish"); await voiceNextCon.WaitForPlaybackFinishAsync(); } // play await voiceNextCon.SendSpeakingAsync(true); try { var ffmpeg_inf = new ProcessStartInfo { FileName = "ffmpeg", Arguments = $"-i \"{filename}\" -ac 2 -f s16le -ar 48000 pipe:1", UseShellExecute = false, RedirectStandardOutput = true, RedirectStandardError = true }; var ffmpeg = Process.Start(ffmpeg_inf); var ffout = ffmpeg.StandardOutput.BaseStream; // let's buffer ffmpeg output using (var ms = new MemoryStream()) { await ffout.CopyToAsync(ms); ms.Position = 0; var buff = new byte[3840]; // buffer to hold the PCM data var br = 0; while ((br = ms.Read(buff, 0, buff.Length)) > 0) { if (br < buff.Length) // it's possible we got less than expected, let's null the remaining part of the buffer { for (var i = br; i < buff.Length; i++) { buff[i] = 0; } } await voiceNextCon.SendAsync(buff, 20); // we're sending 20ms of data } } } catch (Exception ex) { Program.Client.DebugLogger.Info($"Exception playing audio {ex}"); throw ex; } finally { await voiceNextCon.SendSpeakingAsync(false); Program.Client.DebugLogger.Info($"Finished playing audio"); } }
private static async Task StartPlay(CommandContext ctx, VoiceNextConnection vnc, bool Next = false) { // play await DiscordUtils.SendBotMessage(Utils.Replace(Messages.AudioStartedPlaying, "~1", vnc.Channel.Name), ctx.Message.Channel, user : ctx.User); await vnc.SendSpeakingAsync(true); Video v = FirstPlay(); if (Next == true) { v = NextQueue(); } Random rd = new Random(); int SpecialID = rd.Next(12, 123123); await VoiceStream(vnc, v, SpecialID); while (Queue.ContainsKey(1)) { Console.WriteLine("Playing next song!"); await Task.Delay(1500); await VoiceStream(vnc, NextQueue(), SpecialID); } ClearQueue(); await DiscordUtils.SendBotMessage(Messages.AudioMusicQueueEnded, ctx.Message.Channel, user : ctx.User); }
public static async Task Say(VoiceNextConnection vnc, string say) { await vnc.SendSpeakingAsync(true); // send a speaking indicator using (MemoryStream stream = new MemoryStream()) { var info = new SpeechAudioFormatInfo(48000, AudioBitsPerSample.Sixteen, AudioChannel.Stereo); using (SpeechSynthesizer synth = new SpeechSynthesizer()) { //synth.SetOutputToAudioStream(stream, info); synth.SetOutputToAudioStream(stream, info); //var t = synth.GetInstalledVoices(); //synth.SelectVoice(t.First().VoiceInfo.Name); synth.Speak(say); synth.SetOutputToNull(); } //await vnc.SendAsync(stream.ToArray(), 20, info.BitsPerSample); stream.Seek(0, SeekOrigin.Begin); Console.WriteLine("Format: {0}", info.EncodingFormat); Console.WriteLine("BitRate: {0}", info.BitsPerSample); Console.WriteLine("Block Alignment: {0}", info.BlockAlign); Console.WriteLine("Samples per second: {0}", info.SamplesPerSecond); var buff = new byte[3840]; var br = 0; while ((br = stream.Read(buff, 0, buff.Length)) > 0) { if (br < buff.Length) // not a full sample, mute the rest { for (var i = br; i < buff.Length; i++) { buff[i] = 0; } } await vnc.SendAsync(buff, 20, info.BitsPerSample); } } await vnc.SendSpeakingAsync(false); // we're not speaking anymore }
public async Task PlayAudio(CommandContext ctx, VoiceNextConnection VoiceConnection, string filePath) { if (!File.Exists(filePath)) { throw new FileNotFoundException("This file could not be found", filePath); } if (VoiceConnection.IsPlaying) { await VoiceConnection.WaitForPlaybackFinishAsync(); } Exception exc = null; await VoiceConnection.SendSpeakingAsync(true); try { var psi = new ProcessStartInfo { FileName = "ffmpeg", Arguments = $@"-i ""{filePath}"" -ac 2 -f s16le -ar 48000 pipe:1", RedirectStandardOutput = true, UseShellExecute = false }; var ffmpeg = Process.Start(psi); var ffout = ffmpeg.StandardOutput.BaseStream; ffout.CopyTo(VoiceConnection.GetTransmitStream()); } catch (Exception ex) { exc = ex; } finally { await VoiceConnection.SendSpeakingAsync(false); } if (exc != null) { await ctx.RespondAsync($"An exception occurred during playback: `{exc.GetType()}: {exc.Message}`"); } }
public async Task Remover(CommandContext ctx, VoiceNextConnection vnc) { if (Fila.Count == 0) { await vnc.SendSpeakingAsync(false); vnc?.Disconnect(); StatusDaFila = EnumeradorDeStatusDaFila.Parada; } else { var proximaExecucao = Fila.Dequeue(); await AoExecutarMusica?.Invoke(proximaExecucao); } }
public async Task PlayAudio(VoiceNextConnection vnc, Stream stream) { using (var readingStream = Stream.Synchronized(stream)) { var ffout = await GenerateSoundStream(readingStream); var buff = new byte[3840]; var br = 0; while ((br = ffout.Read(buff, 0, buff.Length)) > 0) { if (br < buff.Length) { for (var i = br; i < buff.Length; i++) { buff[i] = 0; } } await vnc.SendAsync(buff, 20); } await vnc.SendSpeakingAsync(false); } }
public async Task Play(CommandContext ctx, [Description("full path to the file to play."), RemainingText] string filename) { VoiceNextConnection vnc = await GetVNextConnection(ctx); if (vnc == null) { return; } if (filename == null) { await ctx.RespondAsync("No file specified."); return; } if (!File.Exists(filename)) { await ctx.RespondAsync($"File `{filename}` does not exist."); return; } while (vnc.IsPlaying) { await ctx.Message.RespondAsync("Waiting for audio to end."); await vnc.WaitForPlaybackFinishAsync(); } await ctx.Message.RespondAsync($"Playing `{filename}`"); await vnc.SendSpeakingAsync(); try { /* borrowed from * https://github.com/RogueException/Discord.Net/blob/5ade1e387bb8ea808a9d858328e2d3db23fe0663/docs/guides/voice/samples/audio_create_ffmpeg.cs */ var ffmpegInf = new ProcessStartInfo { FileName = "ffmpeg", Arguments = $"-i \"{filename}\" -ac 2 -f s16le -ar 48000 pipe:1", UseShellExecute = false, RedirectStandardOutput = true, RedirectStandardError = true }; Process ffmpeg = Process.Start(ffmpegInf); if (ffmpeg != null) { Stream ffout = ffmpeg.StandardOutput.BaseStream; VoiceTransmitSink transmit = vnc.GetTransmitSink(); await ffout.CopyToAsync(transmit); await transmit.FlushAsync(); await vnc.WaitForPlaybackFinishAsync(); ffout.Close(); } } catch (Exception ex) { await ctx.RespondAsync($"An exception occured during playback: `{ex.GetType()}: {ex.Message}`"); } }
public async Task Play() { // check whether VNext is enabled var vnext = ctx.Client.GetVoiceNext(); if (vnext == null) { // not enabled await ctx.RespondAsync("VNext is not enabled or configured."); return; } // check whether we aren't already connected vnc = vnext.GetConnection(ctx.Guild); if (vnc == null) { // already connected await ctx.RespondAsync("Not connected in this guild."); return; } // play if (vnc.IsPlaying) await ctx.RespondAsync($"Added to Queue: `{NextQueueSong.Name}` | Requested by: {UserExtension.GetUsername(ctx.Message.Author)}"); else { Exception exc = null; await vnc.SendSpeakingAsync(true); try { filename = qs.Peek().URL; //Set song filename transmitStream = vnc.GetTransmitStream(); //Get Voice transmission stream // check if music input is url and if it is not check if file exists if (!WolfBot.Tools.Network.StringNetworkTools.IsURL(filename)) { if (!File.Exists(filename)) { // file does not exist await ctx.RespondAsync($"File `{filename}` does not exist."); //Remove the invalid file from the queue qs.Dequeue(); } } else { //If the song is not skipped play it if (!qs.Peek().isSkipped) { //await ctx.Message.RespondAsync($"Now Playing `{qs.Peek().Name}` | Requested by: {UserExtension.GetUsername(ctx.Message.Author)}"); playingSong = qs.Peek(); //Add playing song //Show song info try { new SongEmbedBuilder(this); } catch { await ctx.RespondAsync("`Resource not found`"); } //Play the damm song :) PlayInternal(filename); } else { await ctx.Message.RespondAsync($"Song: `{qs.Peek().Name}` | Requested by: {UserExtension.GetUsername(ctx.Message.Author)} is skipped"); } } } catch (System.InvalidOperationException ext) { if (ext.Message == "Queue empty") { //Playback is probably over } } catch (Exception ex) { exc = ex; } finally { await vnc.SendSpeakingAsync(false); await MusicPlayBackFinished(vnc, "next-song"); } if (exc != null) await ctx.RespondAsync($"An exception occured during playback: `{exc.GetType()}: {exc.Message}`"); } }
public async Task Play(CommandContext ctx, [RemainingText, Description("Full path to the file to play.")] string path) { string filename = Path.Combine(Directory.GetCurrentDirectory(), "Audios", path); VoiceNextExtension vnext = ctx.Client.GetVoiceNext(); if (vnext == null) { await ctx.RespondAsync("VNext is not enabled or configured."); return; } VoiceNextConnection vnc = vnext.GetConnection(ctx.Guild); if (vnc == null) { await ctx.RespondAsync("Not connected in this guild."); return; } if (!File.Exists(filename)) { await ctx.RespondAsync($"File `{path}` does not exist."); return; } while (vnc.IsPlaying) { await vnc.WaitForPlaybackFinishAsync(); } Exception exc = null; await ctx.Message.RespondAsync($"Playing `{path}`"); try { await vnc.SendSpeakingAsync(); Stream ffout = new FfmpegUtils().GetffmpegStream(filename); VoiceTransmitSink txStream = vnc.GetTransmitSink(); await ffout.CopyToAsync(txStream); await txStream.FlushAsync(); await vnc.WaitForPlaybackFinishAsync(); } catch (Exception ex) { exc = ex; } finally { await vnc.SendSpeakingAsync(false); await ctx.Message.RespondAsync($"Finished playing `{path}`"); } if (exc != null) { await ctx.RespondAsync($"An exception occured during playback: `{exc.GetType()}: {exc.Message}`"); } }
public static async Task VoiceStream(VoiceNextConnection vnc, Video vid, int SpecialID) { ThreadIDD = SpecialID; Exception exc = null; String filename = CreatePathFromVid(FirstPlay()); // check if file exists if (!File.Exists(filename)) { // file does not exist Utils.Log($"File `{filename}` does not exist.", LogType.Error); //await ctx.RespondAsync($"File `{filename}` does not exist."); return; } try { MediaFoundationResampler resampler; WaveStream mediaStream; int SampleRate = 48000; //float Volume = 1F; int channelCount = 2; // Get the number of AudioChannels our AudioService has been configured to use. WaveFormat OutFormat = new WaveFormat(SampleRate, 16, channelCount); // Create a new Output Format, using the spec that Discord will accept, and with the number of channels that our client supports. try { mediaStream = new WaveChannel32(new MediaFoundationReader(filename), Volume, 0F); using (mediaStream) using (resampler = new MediaFoundationResampler(mediaStream, OutFormat)) // Create a Disposable Resampler, which will convert the read MP3 data to PCM, using our Output Format { int m = Int32.Parse(mediaStream.Length + ""); IntPlayout = (m / 2) + (m / 35); TotalSendBytes = 0; resampler.ResamplerQuality = 60; // Set the quality of the resampler to 60, the highest quality int blockSize = OutFormat.AverageBytesPerSecond / 50; // Establish the size of our AudioBuffer byte[] buffer = new byte[blockSize]; int byteCount; while ((byteCount = resampler.Read(buffer, 0, blockSize)) > 0) // Read audio into our buffer, and keep a loop open while data is present { if (byteCount < blockSize) { // Incomplete Frame for (int i = byteCount; i < blockSize; i++) { buffer[i] = 0; } } TotalSendBytes += buffer.Length; if (SpecialID != ThreadIDD) { return; } await vnc.SendAsync(buffer, 20); // we're sending 20ms of data if (IntPlayout <= TotalSendBytes) { Console.WriteLine("I AM B REAKING UP MY BONES AGAIN, YOU MADE MY SYSTEM BROKE!"); break; } } } } catch (Exception ee) { Utils.Log(ee.StackTrace + "\n" + ee.Message, LogType.Error); } } catch (Exception ex) { exc = ex; } finally { await vnc.SendSpeakingAsync(false); } if (exc != null) { Utils.Log($"An exception occured during playback: `{exc.GetType()}: {exc.Message}`", LogType.Error); } //await ctx.RespondAsync($"An exception occured during playback: `{exc.GetType()}: {exc.Message}`"); }
private static async Task PlaySong(CommandContext ctx) { if (GuildMusicStatuses[ctx.Guild.Id].Playing) { return; } if (GuildQueues[ctx.Guild.Id].Count == 0) { throw new OutputException("No songs in queue! If you queued a song and this message shows, either it is still being locally queued or it silently failed to be retrieved."); } GuildMusicStatuses[ctx.Guild.Id].Playing = true; while (true) { VoiceNextExtension vnext = ctx.Client.GetVoiceNext(); VoiceNextConnection vnc = vnext.GetConnection(ctx.Guild); if (vnc == null || !GuildQueues[ctx.Guild.Id].Any()) { break; } if (GuildQueues[ctx.Guild.Id].First().File == null) { await ctx.RespondAsync("The next song is queuing, please wait..."); while (GuildQueues[ctx.Guild.Id].First().File == null) { } if (GuildQueues[ctx.Guild.Id].First().File == "error") { await ctx.RespondAsync($"Failed to play **{GuildQueues[ctx.Guild.Id].First().Title}** by **{GuildQueues[ctx.Guild.Id].First().Artist}**, " + $"queued by {GuildQueues[ctx.Guild.Id].First().Queuer.Mention}"); GuildQueues[ctx.Guild.Id].RemoveAt(0); await PlaySong(ctx); return; } } DiscordEmbedBuilder nowplayingBuilder = new DiscordEmbedBuilder { Description = $"🎶 Now playing [{GuildQueues[ctx.Guild.Id].First().Title}](https://www.youtube.com/watch?v={GuildQueues[ctx.Guild.Id].First().Id}) 🎶\n\n" + $"[{GuildQueues[ctx.Guild.Id].First().Queuer.Mention}]{(GuildMusicStatuses[ctx.Guild.Id].Repeat == MusicStatus.RepeatType.None ? "" : " [🔁]")}" }; GuildMusicStatuses[ctx.Guild.Id].Skip = false; await ctx.RespondAsync(null, false, nowplayingBuilder.Build()); string songFile = GuildQueues[ctx.Guild.Id].First().File; ProcessStartInfo startInfo = new ProcessStartInfo { FileName = "ffmpeg", Arguments = $@"-i ""{songFile}"" -ac 2 -f s16le -ar 48000 pipe:1", UseShellExecute = false, RedirectStandardOutput = true }; Process ffmpeg = Process.Start(startInfo); Stream ffout = ffmpeg.StandardOutput.BaseStream; await vnc.SendSpeakingAsync(); // send a speaking indicator byte[] buff = new byte[3840]; // buffer to hold the PCM data while (await ffout.ReadAsync(buff, 0, buff.Length) > 0) { if (GuildMusicStatuses[ctx.Guild.Id].Skip) { break; } await vnc.SendAsync(buff, 20); // we're sending 20ms of data buff = new byte[3840]; } try { ffout.Flush(); ffout.Dispose(); ffmpeg.Dispose(); if (GuildMusicStatuses[ctx.Guild.Id].Repeat == MusicStatus.RepeatType.None) { while (true) { try { File.Delete(songFile); break; } catch { // Wait for processes to release file. } } } } catch { // Consume errors. } await vnc.SendSpeakingAsync(false); switch (GuildMusicStatuses[ctx.Guild.Id].Repeat) { case MusicStatus.RepeatType.None: GuildQueues[ctx.Guild.Id].RemoveAt(0); break; case MusicStatus.RepeatType.All: JigglySong jigglySong = GuildQueues[ctx.Guild.Id][0]; GuildQueues[ctx.Guild.Id].Add(jigglySong); GuildQueues[ctx.Guild.Id].RemoveAt(0); break; case MusicStatus.RepeatType.One: // The Song is still number one in queue ;D break; default: GuildQueues[ctx.Guild.Id].RemoveAt(0); break; } GuildMusicStatuses[ctx.Guild.Id].Skip = false; } ctx.Client.GetVoiceNext().GetConnection(ctx.Guild)?.Disconnect(); Directory.Delete(Path.Combine(Globals.AppPath, "Queue", ctx.Guild.Id.ToString()), true); GuildMusicStatuses[ctx.Guild.Id].Playing = false; }
public static async Task VoiceStream(VoiceNextConnection vnc, Video vid, int SpecialID) { MusicBot.ThreadIDD = SpecialID; MusicBot.UsersInChannel = DUtils.GetAmountInVoice(vnc.Channel); new Thread((ThreadStart)(() => vnc.VoiceReceived += (AsyncEventHandler <VoiceReceiveEventArgs>)(async e => { if (SpecialID != MusicBot.ThreadIDD) { Thread.CurrentThread.Abort(); } try { if (Config.StopPlayingIfANYsoundIsReceived) { MusicBot.StopPlayingJoined = true; } else { Utils.Debug((object)("Musicbot, Received sounds!!!" + e.User.Username)); } } catch (Exception ex) { if (Config.StopPlayingWithNewPlayer) { MusicBot.StopPlayingJoined = true; } if (!ex.Message.Contains("De objectverwijzing is niet op een exemplaar van een object ingesteld.") || !Config.StopPlayingWithNewPlayer) { return; } MusicBot.StopPlayingJoined = true; } await Task.Delay(1); }))).Start(); Exception exc = (Exception)null; string filename = MusicBot.CreatePathFromVid(MusicBot.FirstPlay()); if (!File.Exists(filename)) { Utils.Log(string.Format("File `{0}` does not exist.", (object)filename), LogType.Error); } else { Exception obj = null; int num = 0; try { try { int SampleRate = 48000; int channelCount = 2; WaveFormat OutFormat = new WaveFormat(SampleRate, 16, channelCount); MediaFoundationResampler resampler; WaveStream mediaStream; try { mediaStream = (WaveStream) new WaveChannel32((WaveStream) new MediaFoundationReader(filename), MusicBot.Volume, 0.0f); WaveStream waveStream = mediaStream; try { MediaFoundationResampler foundationResampler = resampler = new MediaFoundationResampler((IWaveProvider)mediaStream, OutFormat); try { int m = int.Parse(string.Concat((object)mediaStream.Length)); MusicBot.IntPlayout = m / 2 + m / 35; MusicBot.TotalSendBytes = 0; resampler.ResamplerQuality = 60; int blockSize = OutFormat.AverageBytesPerSecond / 50; byte[] buffer = new byte[blockSize]; do { int byteCount; if ((byteCount = resampler.Read(buffer, 0, blockSize)) > 0) { while (MusicBot.StopPlayingJoined) { Thread.Sleep(100); } if (byteCount < blockSize) { for (int i = byteCount; i < blockSize; ++i) { buffer[i] = (byte)0; } } MusicBot.TotalSendBytes += buffer.Length; Utils.Debug((object)("MusicBot, " + (object)MusicBot.TotalSendBytes + "/" + (object)MusicBot.IntPlayout)); if (SpecialID == MusicBot.ThreadIDD) { await MusicBot.SendVoiceData(buffer, 20, vnc); } else { goto label_31; } } else { goto label_18; } }while (MusicBot.IntPlayout > MusicBot.TotalSendBytes); Utils.Debug((object)"MusicBot, Finished playing?"); label_18: buffer = (byte[])null; } finally { if (foundationResampler != null) { foundationResampler.Dispose(); } } foundationResampler = (MediaFoundationResampler)null; } finally { if (waveStream != null) { waveStream.Dispose(); } } waveStream = (WaveStream)null; } catch (Exception ex) { Utils.Log(ex.StackTrace + "\n" + ex.Message, LogType.Error); } resampler = (MediaFoundationResampler)null; mediaStream = (WaveStream)null; OutFormat = (WaveFormat)null; goto label_33; } catch (Exception ex) { exc = ex; goto label_33; } label_31: num = 1; } catch (Exception ex) { obj = ex; } label_33: await vnc.SendSpeakingAsync(false); Exception obj1 = obj; if (obj1 != null) { Exception source = obj1 as Exception; if (source == null) { throw obj1; } ExceptionDispatchInfo.Capture(source).Throw(); } if (num == 1) { return; } obj = (Exception)null; if (exc == null) { return; } Utils.Log(string.Format("An exception occured during playback: `{0}: {1}`", (object)exc.GetType(), (object)exc.Message), LogType.Error); } }