// Plays this sound over the specified VoiceConnection func (s *Sound) Play(vc *discordgo.VoiceConnection) { vc.Speaking(true) defer vc.Speaking(false) for _, buff := range s.buffer { vc.OpusSend <- buff } }
// PlayAudioFile will play the given filename to the already connected // Discord voice server/channel. voice websocket and udp socket // must already be setup before this will work. func PlayAudioFile(v *discordgo.VoiceConnection, filename string) { // Create a shell command "object" to run. run = exec.Command("ffmpeg", "-i", filename, "-f", "s16le", "-ar", strconv.Itoa(frameRate), "-ac", strconv.Itoa(channels), "pipe:1") ffmpegout, err := run.StdoutPipe() if err != nil { fmt.Println("StdoutPipe Error:", err) return } ffmpegbuf := bufio.NewReaderSize(ffmpegout, 16384) // Starts the ffmpeg command err = run.Start() if err != nil { fmt.Println("RunStart Error:", err) return } // Send "speaking" packet over the voice websocket v.Speaking(true) // Send not "speaking" packet over the websocket when we finish defer v.Speaking(false) // will actually only spawn one instance, a bit hacky. if send == nil { send = make(chan []int16, 2) } go SendPCM(v, send) for { // read data from ffmpeg stdout audiobuf := make([]int16, frameSize*channels) err = binary.Read(ffmpegbuf, binary.LittleEndian, &audiobuf) if err == io.EOF || err == io.ErrUnexpectedEOF { return } if err != nil { fmt.Println("error reading from ffmpeg stdout :", err) return } // Send received PCM to the sendPCM channel send <- audiobuf } }
// Takes inbound audio and sends it right back out. func Echo(v *discordgo.VoiceConnection) { recv := make(chan *discordgo.Packet, 2) go dgvoice.ReceivePCM(v, recv) send := make(chan []int16, 2) go dgvoice.SendPCM(v, send) v.Speaking(true) defer v.Speaking(false) for { p, ok := <-recv if !ok { return } send <- p.PCM } }