dndmusicbot/ambiance.go

230 lines
4.0 KiB
Go

package main
import (
"bufio"
"fmt"
"io"
"log"
"math"
"os"
"os/exec"
"path/filepath"
"strconv"
"strings"
"time"
"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(config.GetString("ambiance.path"), 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(config.GetString("ambiance.path"))
if err != nil {
return nil, err
}
for _, file := range files {
title, err := xattr.Getxattr(filepath.Join(config.GetString("ambiance.path"), 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(config.GetString("ambiance.path"), file.Name()),
})
}
return
}
func AddAmbiance(uri, title string) (Ambiance, error) {
var amb Ambiance
ev := Event{"ambiance_add_start", map[string]string{
"name": title,
}}
go ws.SendEvent(ev)
defer func() {
ev = Event{"ambiance_add_finish", map[string]string{
"name": title,
}}
go ws.SendEvent(ev)
}()
tmpfile, err := exec.Command("mktemp", "/tmp/dnd_XXXXXXXXXXXX.opus").Output()
if err != nil {
return amb, err
}
tmpfile = tmpfile[:len(tmpfile)-1]
log.Printf("Parsing vid from %s", uri)
vid, err := YTUrl(uri)
if err != nil {
return amb, err
}
vinfo, err := app.youtube.GetVideoFromID(vid)
if err != nil {
return amb, err
}
log.Printf("Start ffmpeg for %s (%s)", vid, vinfo.VideoDetails.Title)
ff := exec.Command(
"ffmpeg",
"-y",
"-i", vinfo.GetHLSPlaylist("234"),
"-vn",
//"-acodec", "copy",
"-movflags", "+faststart",
"-t", "01:00:00",
"-ar", "48000",
"-v", "quiet",
// "-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
err = ff.Start()
if err != nil {
return amb, err
}
log.Printf("Start ffmpeg to extract audio to %s", string(tmpfile))
ev = Event{"ambiance_encode_start", map[string]string{
"name": title,
}}
go ws.SendEvent(ev)
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() {
out_time, ok := data["out_time_ms"]
if ok {
out_time_ms, _ := strconv.Atoi(out_time)
percent := fmt.Sprintf("%.0f", math.Floor((float64(out_time_ms)/float64(time.Hour.Microseconds()))*100))
data["percent"] = percent
}
go ws.SendEvent(Event{"ambiance_encode_progress", data})
})
}
if err := scanner.Err(); err != nil {
return amb, err
}
err = ff.Wait()
if err != nil {
return amb, err
}
ev = Event{"ambiance_encode_complete", map[string]string{
"name": title,
}}
go ws.SendEvent(ev)
id := uuid.New()
fn := filepath.Join(config.GetString("ambiance.path"), fmt.Sprintf("%s.aac", 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
}