public async Task <bool> JoinAudioAsync(IVoiceChannel voiceChannel) { bool joinedAudio = false; var currentUser = await voiceChannel.Guild.GetCurrentUserAsync(); if (!audioInstances.TryGetValue(voiceChannel.GuildId, out AudioInstance audioInstance) || currentUser.VoiceChannel == null) { audioInstance = new AudioInstance { GuildId = voiceChannel.GuildId, AudioClient = await voiceChannel.ConnectAsync().ConfigureAwait(false) }; audioInstances[voiceChannel.GuildId] = audioInstance; audioInstance.Stream = audioInstance.AudioClient.CreatePCMStream(Discord.Audio.AudioApplication.Voice, null, 250); joinedAudio = true; } else { Log.Information($"{{Indicator}} Already in a voice channel for {voiceChannel.GuildId}", "[audio]"); } if (audioInstance.AudioClient.ConnectionState == ConnectionState.Connected && audioInstance.Stream.CanWrite) { await this.SendAudioAsync(audioInstance, PhrasesConfig.Instance.GetVoiceFileNames(VoicePhraseType.BotJoin).Random()); } else { audioInstance.AudioClient.Connected += async() => { await this.SendAudioAsync(audioInstance, PhrasesConfig.Instance.GetVoiceFileNames(VoicePhraseType.BotJoin).Random()); }; audioInstance.AudioClient.Disconnected += (Exception ex) => { Log.Error(ex, "{{Indicator}} Disconnected from audio", "[audio]"); return(Task.CompletedTask); }; } return(joinedAudio); }
public async Task JoinAudioAsync(IVoiceChannel voiceChannel) { var currentUser = await voiceChannel.Guild.GetCurrentUserAsync(); if (!audioInstances.TryGetValue(voiceChannel.GuildId, out AudioInstance audioInstance) || currentUser.VoiceChannel == null) { audioInstance = new AudioInstance { GuildId = voiceChannel.GuildId, AudioClient = await voiceChannel.ConnectAsync().ConfigureAwait(false) }; audioInstances[voiceChannel.GuildId] = audioInstance; audioInstance.Stream = audioInstance.AudioClient.CreatePCMStream(Discord.Audio.AudioApplication.Voice, null, 250); } else { Console.WriteLine($"Already in a voice channel for {voiceChannel.GuildId}"); } if (audioInstance.AudioClient.ConnectionState == ConnectionState.Connected && audioInstance.Stream.CanWrite) { await this.SendAudioAsync(audioInstance, PhrasesConfig.Instance.GetVoiceFileNames(VoicePhraseType.BotJoin).Random()); } else { audioInstance.AudioClient.Connected += async() => { await this.SendAudioAsync(audioInstance, PhrasesConfig.Instance.GetVoiceFileNames(VoicePhraseType.BotJoin).Random()); }; audioInstance.AudioClient.Disconnected += async(Exception ex) => { await this.LeaveAudioAsync(voiceChannel.GuildId); Console.WriteLine(ex); }; } }
private async Task SendAudioAsyncInternalAsync(AudioInstance audioInstance, string filePath) { var filename = Path.GetFileName(filePath); Process p = null; if (!audioBytes.ContainsKey(filename)) { Console.WriteLine($"[audio] [{filename}] reading data"); p = Process.Start(new ProcessStartInfo { FileName = "c:\\audio\\ffmpeg", Arguments = $"-i {filePath} -f s16le -ar 48000 -ac 2 pipe:1 -loglevel error", UseShellExecute = false, RedirectStandardOutput = true, RedirectStandardInput = true, }); } else { Console.WriteLine($"[audio] [{filename}] using cached bytes"); } await audioInstance.streamLock.WaitAsync(); Console.WriteLine($"[audio] [{filename}] lock obtained"); try { if (audioInstance.Stream != null) { Console.WriteLine($"[audio] [{filename}] stream copy"); if (p != null) { using (var memoryStream = new MemoryStream()) { await p.StandardOutput.BaseStream.CopyToAsync(memoryStream); byte[] data; using (var binaryReader = new BinaryReader(memoryStream)) { binaryReader.BaseStream.Position = 0; data = binaryReader.ReadBytes((int)memoryStream.Length); } if (!audioBytes.ContainsKey(filename)) { audioBytes[filename] = AdjustVolume(data, .8f); } } } using (var memoryStream = new MemoryStream(audioBytes[filename])) { await memoryStream.CopyToAsync(audioInstance.Stream); } p?.WaitForExit(8000); var flushTask = audioInstance.Stream.FlushAsync(); var timeoutTask = Task.Delay(8000); if (await Task.WhenAny(flushTask, timeoutTask) == timeoutTask) { Console.WriteLine($"[audio] [{filename}] timeout occurred"); throw new TimeoutException(); } } } catch (Exception ex) { Console.WriteLine(ex); p?.Dispose(); } finally { if (audioInstance != null && !audioInstance.isDisposed) { audioInstance?.streamLock?.Release(); } } }
public async Task SendAudioAsync(AudioInstance audioInstance, string filename) { await this.SendAudioAsyncInternalAsync(audioInstance, filename); }