dndmusicbot/ambiance.go

217 lines
3.6 KiB
Go

package main
import (
"bufio"
"fmt"
"io"
"log"
"net/http"
"os"
"os/exec"
"path/filepath"
"strings"
"github.com/davecheney/xattr"
"github.com/google/uuid"
)
var httpClient = new(http.Client)
type Ambiance struct {
Id string
Title string
Path string
}
func GetAmbiance(id string) (amb Ambiance, err error) {
fp := filepath.Join("./ambiance", id+".opus")
_, err = os.Stat(fp)
if err != nil {
return
}
title, err := xattr.Getxattr(fp, "title")
if err != nil {
return
}
return Ambiance{
Id: id,
Title: string(title),
Path: fp,
}, nil
}
func GetAmbiances() (amb []Ambiance, err error) {
files, err := os.ReadDir("./ambiance")
if err != nil {
return nil, err
}
for _, file := range files {
title, err := xattr.Getxattr(filepath.Join("./ambiance", file.Name()), "title")
if err != nil {
return nil, err
}
amb = append(amb, Ambiance{
Id: file.Name()[:len(file.Name())-len(filepath.Ext(file.Name()))],
Title: string(title),
Path: filepath.Join("./ambiance", file.Name()),
})
}
return
}
func AddAmbiance(uri, title string) (Ambiance, error) {
var amb Ambiance
tmpfile, err := exec.Command("mktemp", "/tmp/dnd_XXXXXXXXXXXX.opus").Output()
if err != nil {
return amb, err
}
tmpfile = tmpfile[:len(tmpfile)-1]
vid, err := YTUrl(uri)
if err != nil {
return amb, err
}
log.Printf("Start YTdl for %s", uri)
dluri, err := NewYTdl(vid)
if err != nil {
return amb, err
}
log.Printf("Start download.. %s", uri)
resp, err := httpClient.Get(string(dluri))
if err != nil {
return amb, err
}
defer resp.Body.Close()
ff := exec.Command(
"ffmpeg",
"-y",
"-i", "-",
"-vn",
"-acodec", "copy",
"-movflags", "+faststart",
"-t", "01:00:00",
"-v", "error",
// "-stats",
"-progress", "pipe:1",
// "-af", "loudnorm=I=-16:LRA=11:TP=-1.5",
string(tmpfile),
)
ffprogress, err := ff.StdoutPipe()
if err != nil {
return amb, err
}
ff.Stderr = os.Stderr
ff.Stdin = resp.Body
err = ff.Start()
if err != nil {
return amb, err
}
log.Printf("Start ffmpeg to extract audio to %s", string(tmpfile))
msg := make(map[string]interface{})
msg["event"] = "ambiance_encode_start"
data := make(map[string]string)
data["name"] = title
msg["payload"] = data
ws_msg <- msg
msg = make(map[string]interface{})
msg["event"] = "ambiance_encode_progress"
data = make(map[string]string)
data["name"] = title
scanner := bufio.NewScanner(ffprogress)
for scanner.Scan() {
p := strings.Split(scanner.Text(), "=")
if len(p) == 2 {
data[p[0]] = strings.TrimSpace(p[1])
}
prate.Do(func() {
msg["payload"] = data
ws_msg <- msg
})
}
if err := scanner.Err(); err != nil {
return amb, err
}
err = ff.Wait()
if err != nil {
return amb, err
}
msg = make(map[string]interface{})
msg["event"] = "ambiance_encode_complete"
data = make(map[string]string)
data["name"] = title
msg["payload"] = data
ws_msg <- msg
id := uuid.New()
fn := filepath.Join("./ambiance", fmt.Sprintf("%s.opus", id.String()))
log.Printf("Moving to %s", fn)
in, err := os.Open(string(tmpfile))
if err != nil {
return amb, err
}
of, err := os.Create(fn)
if err != nil {
return amb, err
}
_, err = io.Copy(of, in)
if err != nil {
return amb, err
}
err = of.Sync()
if err != nil {
return amb, err
}
err = of.Close()
if err != nil {
return amb, err
}
err = in.Close()
if err != nil {
return amb, err
}
err = os.Remove(string(tmpfile))
if err != nil {
return amb, err
}
log.Println("Setting xattr")
err = xattr.Setxattr(fn, "title", []byte(title))
if err != nil {
return amb, err
}
amb.Id = id.String()
amb.Title = title
log.Println("Return info.")
return amb, nil
}