-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathmain.go
239 lines (185 loc) · 5.39 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
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
package main
import (
"fmt"
"html/template"
"log"
"os"
"github.com/spf13/viper"
"encoding/json"
"io/ioutil"
"github.com/maxkulish/hls_create/bitRate"
"github.com/maxkulish/hls_create/templates"
)
// Station structure with all parameters
type Station struct {
ID int
Name string
InputStream string
OutputStream string
Bitrate int
OutputBitRate map[string]int
Volume float32
}
// HLSPlaylist describe Playlist parameters and location
type HLSPlaylist struct {
Station
PlayListPath string // Folder for HLS playlists
ExtPath string // External server adress
FFMPEGPath string // ffmpeg output folder
RunScript string // Folder for bash scripts
}
// DefineBitrate calculate output bitrates for input
func (st Station) DefineBitrate() map[string]int {
var result = map[string]int{}
switch bitrate := st.Bitrate; bitrate {
case 128:
result = bitRate.Input128
case 196:
result = bitRate.Input192
case 256:
result = bitRate.Input256
case 320:
result = bitRate.Input320
default:
log.Printf("Can't define output bit rate: %d\n", bitrate)
}
return result
}
// Creates bash scripts for every station
func createStationScript(plst HLSPlaylist) {
// Check if path /home/user/folder is exists
if _, err := os.Stat(plst.RunScript); os.IsNotExist(err) {
os.MkdirAll(plst.RunScript, 0755)
log.Printf("[+] Creating folder: %s\n", plst.RunScript)
}
t := template.Must(template.New("bash").Parse(templates.BashTemplate))
fileName := fmt.Sprintf("%s/%s.sh", plst.RunScript, plst.Name)
f, err := os.Create(fileName)
defer f.Close()
if err != nil {
log.Printf("[!] Can't create file: %v", err)
os.Exit(1)
}
if err := os.Chmod(fileName, 0644); err != nil {
log.Printf("[!] Can't chmod file: %v", err)
}
err = t.Execute(f, plst)
if err != nil {
log.Printf("[!] Can't execute template: %v", err)
os.Exit(1)
}
}
// createHLSPlaylist - creates stations.m3u8
func createHLSPlaylist(plst HLSPlaylist) {
// Check if path is exists
if _, err := os.Stat(plst.PlayListPath); os.IsNotExist(err) {
os.MkdirAll(plst.PlayListPath, 0755)
log.Printf("[+] Creating folder: %s\n", plst.PlayListPath)
}
t := template.Must(template.New("playlist").Parse(templates.PlaylistTemplate))
f, err := os.Create(fmt.Sprintf("%s/%s.m3u8", plst.PlayListPath, plst.Name))
defer f.Close()
if err != nil {
log.Printf("[!] Can't create file: %v", err)
os.Exit(1)
}
err = t.Execute(f, plst)
if err != nil {
log.Printf("[!] Can't execute template: %v", err)
os.Exit(1)
}
}
// creates reloader.sh
func createReloader(stations []Station, scriptsFolder, reloaderPath string) {
type ReloaderSettings struct {
Stations string
ScriptsPath string
ReloaderPath string
}
parsedStations := func(stns []Station) string {
var joined string
for _, st := range stns {
joined += fmt.Sprintf(" %s", st.Name)
}
return joined
}(stations)
// Check if path is exists
if _, err := os.Stat(reloaderPath); os.IsNotExist(err) {
os.MkdirAll(reloaderPath, 0755)
log.Printf("[+] Creating folder: %s\n", reloaderPath)
}
reloader := ReloaderSettings{
Stations: parsedStations,
ScriptsPath: scriptsFolder,
ReloaderPath: reloaderPath,
}
t := template.Must(template.New("reloader").Parse(templates.ReloaderScript))
fileName := fmt.Sprintf("%s/reloader.sh", reloaderPath)
f, err := os.Create(fileName)
defer f.Close()
if err != nil {
log.Printf("[!] Can't create file: %v", err)
os.Exit(1)
}
if err := os.Chmod(fileName, 0755); err != nil {
log.Printf("[!] Can't chmod file: %v", err)
}
err = t.Execute(f, reloader)
if err != nil {
log.Printf("[!] Can't execute template: %v", err)
os.Exit(1)
}
}
// getStations reads stations from file stations.json
func getStations() []Station {
raw, err := ioutil.ReadFile("./stations.json")
if err != nil {
log.Printf("[!] Can't read stations. Error: %v", err)
os.Exit(1)
}
var stations []Station
json.Unmarshal(raw, &stations)
return stations
}
func main() {
// Read project settings from config.json file
viper.SetConfigFile("./config.json")
err := viper.ReadInConfig()
if err != nil {
log.Fatal("[!] Can't read config file ./config.json")
os.Exit(1)
}
// Folder to save scripts from config.json
scriptsFolder := viper.GetString("scripts_folder")
// ffmpeg output folder example: /hls/station/station-128.m3u8
ffmpegFolder := viper.GetString("ffmpeg_folder")
// External path to hls folder. Example: http://207.154.240.221/hls/
extPath := viper.GetString("ext_path")
// Folder to save HLS Playlist from config.json
playListFolder := viper.GetString("playlist_folder")
// Folder to save reloader.sh
reloaderPath := viper.GetString("reloader_path")
stations := getStations()
if len(stations) == 0 {
log.Fatal("[!] There are no stations in file. Nothing to do.")
os.Exit(1)
}
// Create reloader.sh scripts
createReloader(stations, scriptsFolder, reloaderPath)
for _, st := range stations {
st.OutputBitRate = st.DefineBitrate()
plst := HLSPlaylist{
Station: st,
PlayListPath: playListFolder,
ExtPath: extPath,
FFMPEGPath: ffmpegFolder,
RunScript: scriptsFolder,
}
// Create run bash scripts for every station
createStationScript(plst)
log.Printf("[$]\tscript for station: %s created", st.Name)
// Create station.m3u8 file for every station
createHLSPlaylist(plst)
log.Printf("[$]\tHLS Playlist for station: %s created", st.Name)
}
}