230 lines
4.0 KiB
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
|
|
}
|