forked from jonas747/dca
/
main.go
136 lines (111 loc) · 3.09 KB
/
main.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
package main
import (
"flag"
"fmt"
"github.com/bwmarrin/discordgo"
"github.com/jonas747/dca"
"io"
"io/ioutil"
//"io/ioutil"
"log"
"os/exec"
"runtime"
"time"
)
var (
run *exec.Cmd
)
func main() {
// NOTE: All of the below fields are required for this example to work correctly.
var (
Token = flag.String("t", "", "Discord token.")
GuildID = flag.String("g", "", "Guild ID")
ChannelID = flag.String("c", "", "Channel ID")
Folder = flag.String("f", "sounds", "Folder of files to play.")
err error
)
flag.Parse()
if *GuildID == "" {
log.Fatal("No guild specified")
}
if *ChannelID == "" {
log.Println("No channdlid specified, using guildid (default voice channel if not deleted)")
ChannelID = GuildID
}
if *Token == "" {
log.Fatal("No token specified!")
}
log.SetFlags(log.LstdFlags | log.Lshortfile)
// Connect to Discord
discord, err := discordgo.New(*Token)
if err != nil {
log.Fatal(err)
}
discord.LogLevel = discordgo.LogWarning
// Open Websocket
err = discord.Open()
if err != nil {
log.Fatal(err)
}
// Connect to voice channel.
// NOTE: Setting mute to false, deaf to true.
voice, err := discord.ChannelVoiceJoin(*GuildID, *ChannelID, false, true)
if err != nil {
log.Fatal(err)
}
voice.LogLevel = discordgo.LogWarning
// Hacky loop to prevent sending on a nil channel.
// TODO: Find a better way.
for voice.Ready == false {
runtime.Gosched()
}
// Start loop and attempt to play all files in the given folder
fmt.Println("Reading Folder: ", *Folder)
files, _ := ioutil.ReadDir(*Folder)
for _, f := range files {
fmt.Println("PlayAudioFile:", f.Name())
discord.UpdateStatus(0, f.Name())
PlayAudioFile(voice, fmt.Sprintf("%s/%s", *Folder, f.Name()))
}
// Close connections
voice.Close()
discord.Close()
return
}
// 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) {
// Send "speaking" packet over the voice websocket
err := v.Speaking(true)
if err != nil {
log.Fatal("Failed setting speaking", err)
}
// Send not "speaking" packet over the websocket when we finish
defer v.Speaking(false)
opts := dca.StdEncodeOptions
opts.RawOutput = true
opts.Bitrate = 120
encodeSession, err := dca.EncodeFile(filename, opts)
if err != nil {
log.Fatal("Failed creating an encoding session: ", err)
}
done := make(chan error)
stream := dca.NewStream(encodeSession, v, done)
ticker := time.NewTicker(time.Second)
for {
select {
case err := <-done:
if err != nil && err != io.EOF {
log.Fatal("An error occured", err)
}
// Clean up incase something happened and ffmpeg is still running
encodeSession.Truncate()
return
case <-ticker.C:
stats := encodeSession.Stats()
playbackPosition := stream.PlaybackPosition()
fmt.Printf("Playback: %10s, Transcode Stats: Time: %5s, Size: %5dkB, Bitrate: %6.2fkB, Speed: %5.1fx\r", playbackPosition, stats.Duration.String(), stats.Size, stats.Bitrate, stats.Speed)
}
}
}