Fix ambiance download

pull/11/head
Stein Ivar Berghei 2023-09-06 22:46:05 +02:00
parent 1888592d07
commit b26b43f163
4 changed files with 170 additions and 21 deletions

View File

@ -5,7 +5,6 @@ import (
"fmt"
"io"
"log"
"net/http"
"os"
"os/exec"
"path/filepath"
@ -15,7 +14,7 @@ import (
"github.com/google/uuid"
)
var httpClient = new(http.Client)
//var httpClient = new(http.Client)
type Ambiance struct {
Id string
@ -67,6 +66,22 @@ func GetAmbiances() (amb []Ambiance, err error) {
func AddAmbiance(uri, title string) (Ambiance, error) {
var amb Ambiance
msg := make(map[string]interface{})
msg["event"] = "ambiance_add_start"
data := make(map[string]string)
data["name"] = title
msg["payload"] = data
ws_msg <- msg
defer func() {
msg = make(map[string]interface{})
msg["event"] = "ambiance_add_finish"
data = make(map[string]string)
data["name"] = title
msg["payload"] = data
ws_msg <- msg
}()
tmpfile, err := exec.Command("mktemp", "/tmp/dnd_XXXXXXXXXXXX.opus").Output()
if err != nil {
return amb, err
@ -74,28 +89,23 @@ func AddAmbiance(uri, title string) (Ambiance, error) {
tmpfile = tmpfile[:len(tmpfile)-1]
log.Printf("Parsing vid from %s", uri)
vid, err := YTUrl(uri)
if err != nil {
return amb, err
}
log.Printf("Start YTdl for %s", uri)
dluri, err := NewYTdl(vid)
log.Printf("Start download with YTdl for %s", uri)
ytfile, 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()
log.Printf("Start ffmpeg for %s", string(ytfile))
ff := exec.Command(
"ffmpeg",
"-y",
"-i", "-",
"-i", string(ytfile),
"-vn",
"-acodec", "copy",
"-movflags", "+faststart",
@ -113,7 +123,6 @@ func AddAmbiance(uri, title string) (Ambiance, error) {
}
ff.Stderr = os.Stderr
ff.Stdin = resp.Body
err = ff.Start()
if err != nil {
@ -121,9 +130,10 @@ func AddAmbiance(uri, title string) (Ambiance, error) {
}
log.Printf("Start ffmpeg to extract audio to %s", string(tmpfile))
msg := make(map[string]interface{})
msg = make(map[string]interface{})
msg["event"] = "ambiance_encode_start"
data := make(map[string]string)
data = make(map[string]string)
data["name"] = title
msg["payload"] = data
ws_msg <- msg
@ -146,6 +156,7 @@ func AddAmbiance(uri, title string) (Ambiance, error) {
ws_msg <- msg
})
}
if err := scanner.Err(); err != nil {
return amb, err
}
@ -197,6 +208,11 @@ func AddAmbiance(uri, title string) (Ambiance, error) {
return amb, err
}
err = os.Remove(string(ytfile))
if err != nil {
return amb, err
}
err = os.Remove(string(tmpfile))
if err != nil {
return amb, err

View File

@ -147,6 +147,39 @@ window.onload = function () {
avol.value = data.payload.ambiance
avol.nextElementSibling.value = data.payload.ambiance
break
case "ambiance_download_start":
var progress = document.querySelector("#progressambiance progress")
progress.style.display = "initial"
progress.style.width = "100%"
progress.value = 0
break
case "ambiance_download_progress":
var progress = document.querySelector("#progressambiance progress")
progress.style.display = "initial"
progress.value = data.payload.percent
console.log(data)
break
case "ambiance_download_complete":
var progress = document.querySelector("#progressambiance progress")
progress.style.display = "initial"
progress.value = 100
break
case "ambiance_add_finish":
var title = document.querySelector("#inputambiance > input[name='title']")
var url = document.querySelector("#inputambiance > input[name='url']")
var submit = document.querySelector("#inputambiance > input[name='submit']")
var progress = document.querySelector("#progressambiance progress")
title.value = ""
url.value = ""
title.disabled = false
url.disabled = false
submit.disabled = false
progress.value = 0
progress.style.display = "none"
break
case "ambiance_add":
const container = document.querySelector("#ambiance")
var newdiv = document.createElement('div');
@ -164,6 +197,21 @@ window.onload = function () {
})
container.insertBefore(newdiv, document.querySelector("#ambiance div:last-child"))
var title = document.querySelector("#inputambiance > input[name='title']")
var url = document.querySelector("#inputambiance > input[name='url']")
var submit = document.querySelector("#inputambiance > input[name='submit']")
var progress = document.querySelector("#progressambiance progress")
title.value = ""
url.value = ""
title.disabled = false
url.disabled = false
submit.disabled = false
progress.value = 0
progress.style.display = "none"
break
case "ambiance_play":
document.querySelectorAll("#ambiance > div").forEach((e) => {e.style.removeProperty("background-color")})
@ -218,6 +266,7 @@ window.onload = function () {
//output.innerText = ""
var title = document.querySelector("#inputambiance > input[name='title']")
var url = document.querySelector("#inputambiance > input[name='url']")
var submit = document.querySelector("#inputambiance > input[name='submit']")
if (title.value == "" || url.value == "") {
console.log("Title or Url is empty!")
return
@ -231,8 +280,9 @@ window.onload = function () {
}
}))
title.value = ""
url.value = ""
title.disabled = true
url.disabled = true
submit.disabled = true
})
addInteractHandler(submit, (e, isTouch) => {

View File

@ -59,6 +59,12 @@
</div>
</section>
<section>
<div id="progressambiance" class="input-container">
<progress max="100" value="0" style="display:none">0%</progress>
</div>
</section>
<section>
<div id="inputambiance" class="input-container">
<input class="u-full-width" name="title" type="text" placeholder="Enter name..">

85
ytdl.go
View File

@ -1,10 +1,15 @@
package main
import (
"bufio"
"encoding/json"
"fmt"
"log"
"math"
"net/url"
"os"
"os/exec"
"strconv"
"time"
"golang.org/x/time/rate"
@ -14,28 +19,92 @@ var prate = rate.Sometimes{Interval: 1 * time.Second}
var yturl = "https://youtu.be/%s"
func NewYTdl(vid string) ([]byte, error) {
tmpfile, err := exec.Command("mktemp", "/tmp/dnd_ytdlp_XXXXXXXXXXXX.m4a").Output()
if err != nil {
return nil, err
}
tmpfile = tmpfile[:len(tmpfile)-1]
ytdl := config.GetString("youtube.ytdl")
yt := exec.Command(
ytdl,
fmt.Sprintf(yturl, vid),
"-q",
"--cookies", "./cookies.txt",
"--no-call-home",
"--no-cache-dir",
"--ignore-errors",
"--newline",
"--restrict-filenames",
"--force-overwrites",
"--progress",
"--progress-template", "download:{ \"dl_bytes\": \"%(progress.downloaded_bytes)s\", \"total_bytes\": \"%(progress.total_bytes)s\" }",
"-f", "251",
"--get-url",
"-o", string(tmpfile),
)
yt.Stderr = os.Stderr
uri, err := yt.Output()
ytprogress, err := yt.StdoutPipe()
if err != nil {
return nil, err
}
return uri[:len(uri)-1], nil
err = yt.Start()
if err != nil {
return nil, err
}
log.Printf("Start ffmpeg to extract audio to %s", string(tmpfile))
msg := make(map[string]interface{})
msg["event"] = "ambiance_download_start"
data := make(map[string]string)
data["name"] = fmt.Sprintf(yturl, vid)
msg["payload"] = data
ws_msg <- msg
msg = make(map[string]interface{})
msg["event"] = "ambiance_download_progress"
data = make(map[string]string)
data["name"] = fmt.Sprintf(yturl, vid)
scanner := bufio.NewScanner(ytprogress)
for scanner.Scan() {
err := json.Unmarshal(scanner.Bytes(), &data)
if err != nil {
log.Println(err)
continue
}
dl, _ := strconv.ParseFloat(data["dl_bytes"], 64)
total, _ := strconv.ParseFloat(data["total_bytes"], 64)
percent := math.Floor((dl / total) * 100)
data["percent"] = strconv.FormatInt(int64(percent), 10)
prate.Do(func() {
msg["payload"] = data
ws_msg <- msg
})
}
if err := scanner.Err(); err != nil {
return nil, err
}
err = yt.Wait()
if err != nil {
return nil, err
}
msg = make(map[string]interface{})
msg["event"] = "ambiance_download_complete"
data = make(map[string]string)
data["name"] = fmt.Sprintf(yturl, vid)
msg["payload"] = data
ws_msg <- msg
return tmpfile, nil
}
func YTUrl(uri string) (vid string, err error) {
@ -47,10 +116,18 @@ func YTUrl(uri string) (vid string, err error) {
switch u.Host {
case "youtu.be":
vid = u.Path[1:]
case "m.youtube.com":
fallthrough
case "youtube.com":
fallthrough
case "www.youtube.com":
vid = u.Query().Get("v")
}
if vid == "" {
return vid, fmt.Errorf("unable to parse vid")
}
return
}