mirror of
https://github.com/marcopiovanello/yt-dlp-web-ui.git
synced 2026-07-25 06:54:30 +00:00
added external js runtime, metadata scraping refactor
This commit is contained in:
Vendored
+5
-1
@@ -9,7 +9,11 @@
|
|||||||
"type": "go",
|
"type": "go",
|
||||||
"request": "launch",
|
"request": "launch",
|
||||||
"mode": "debug",
|
"mode": "debug",
|
||||||
"program": "main.go"
|
"program": "main.go",
|
||||||
|
"args": [
|
||||||
|
"--conf",
|
||||||
|
"./config.yml"
|
||||||
|
]
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"type": "chrome",
|
"type": "chrome",
|
||||||
|
|||||||
+6
-7
@@ -1,4 +1,3 @@
|
|||||||
# Node (pnpm) ------------------------------------------------------------------
|
|
||||||
FROM node:24-slim AS ui
|
FROM node:24-slim AS ui
|
||||||
ENV PNPM_HOME="/pnpm"
|
ENV PNPM_HOME="/pnpm"
|
||||||
ENV PATH="$PNPM_HOME:$PATH"
|
ENV PATH="$PNPM_HOME:$PATH"
|
||||||
@@ -11,9 +10,9 @@ RUN rm -rf node_modules
|
|||||||
|
|
||||||
RUN pnpm install
|
RUN pnpm install
|
||||||
RUN pnpm build
|
RUN pnpm build
|
||||||
# -----------------------------------------------------------------------------
|
|
||||||
|
|
||||||
# Go --------------------------------------------------------------------------
|
|
||||||
|
|
||||||
FROM golang AS build
|
FROM golang AS build
|
||||||
|
|
||||||
WORKDIR /usr/src/yt-dlp-webui
|
WORKDIR /usr/src/yt-dlp-webui
|
||||||
@@ -22,14 +21,14 @@ COPY . .
|
|||||||
COPY --from=ui /usr/src/yt-dlp-webui/frontend /usr/src/yt-dlp-webui/frontend
|
COPY --from=ui /usr/src/yt-dlp-webui/frontend /usr/src/yt-dlp-webui/frontend
|
||||||
|
|
||||||
RUN CGO_ENABLED=0 GOOS=linux go build -o yt-dlp-webui
|
RUN CGO_ENABLED=0 GOOS=linux go build -o yt-dlp-webui
|
||||||
# -----------------------------------------------------------------------------
|
|
||||||
|
|
||||||
# Runtime ---------------------------------------------------------------------
|
|
||||||
|
|
||||||
FROM python:3-alpine3.22
|
FROM python:3-alpine3.22
|
||||||
|
|
||||||
RUN apk update && \
|
RUN apk update && \
|
||||||
apk add ffmpeg ca-certificates curl wget gnutls deno --no-cache && \
|
apk add ffmpeg ca-certificates curl wget gnutls deno --no-cache && \
|
||||||
pip install "yt-dlp[default,curl-cffi,mutagen,pycryptodomex,phantomjs,secretstorage]"
|
pip install "yt-dlp[default,curl-cffi,mutagen,pycryptodomex,phantomjs,secretstorage]"
|
||||||
|
|
||||||
VOLUME /downloads /config
|
VOLUME /downloads /config
|
||||||
|
|
||||||
|
|||||||
@@ -27,13 +27,13 @@
|
|||||||
},
|
},
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
"@modyfi/vite-plugin-yaml": "^1.1.0",
|
"@modyfi/vite-plugin-yaml": "^1.1.0",
|
||||||
"@types/node": "^20.14.2",
|
"@types/node": "^24.0.0",
|
||||||
"@types/react": "^19.0.1",
|
"@types/react": "^19.0.1",
|
||||||
"@types/react-dom": "^19.0.2",
|
"@types/react-dom": "^19.0.2",
|
||||||
"@types/react-helmet": "^6.1.11",
|
"@types/react-helmet": "^6.1.11",
|
||||||
"@types/react-router-dom": "^5.3.3",
|
"@types/react-router-dom": "^5.3.3",
|
||||||
"@vitejs/plugin-react-swc": "^3.7.2",
|
"@vitejs/plugin-react": "^6.0.3",
|
||||||
"typescript": "^5.7.2",
|
"typescript": "^6.0.3",
|
||||||
"vite": "^6.0.3"
|
"vite": "^8.1.0"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
Generated
+443
-613
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,3 @@
|
|||||||
|
allowBuilds:
|
||||||
|
'@swc/core': true
|
||||||
|
esbuild: true
|
||||||
@@ -1,37 +0,0 @@
|
|||||||
// import { PaginatedResponse } from '../types'
|
|
||||||
|
|
||||||
export type Subscription = {
|
|
||||||
id: string
|
|
||||||
url: string
|
|
||||||
params: string
|
|
||||||
cron_expression: string
|
|
||||||
}
|
|
||||||
|
|
||||||
// class SubscriptionService {
|
|
||||||
// private _baseURL: string = ''
|
|
||||||
|
|
||||||
// public set baseURL(v: string) {
|
|
||||||
// this._baseURL = v
|
|
||||||
// }
|
|
||||||
|
|
||||||
// public async delete(id: string): Promise<void> {
|
|
||||||
|
|
||||||
// }
|
|
||||||
|
|
||||||
// public async listPaginated(start: number, limit: number = 50): Promise<PaginatedResponse<Subscription[]>> {
|
|
||||||
// const res = await fetch(`${this._baseURL}/subscriptions?id=${start}&limit=${limit}`)
|
|
||||||
// const data: PaginatedResponse<Subscription[]> = await res.json()
|
|
||||||
|
|
||||||
// return data
|
|
||||||
// }
|
|
||||||
|
|
||||||
// public async submit(sub: Subscription): Promise<void> {
|
|
||||||
|
|
||||||
// }
|
|
||||||
|
|
||||||
// public async edit(sub: Subscription): Promise<void> {
|
|
||||||
|
|
||||||
// }
|
|
||||||
// }
|
|
||||||
|
|
||||||
// export default SubscriptionService
|
|
||||||
@@ -1,7 +1,7 @@
|
|||||||
{
|
{
|
||||||
"compilerOptions": {
|
"compilerOptions": {
|
||||||
"jsx": "react-jsx",
|
"jsx": "react-jsx",
|
||||||
"target": "ES2018",
|
"target": "es2020",
|
||||||
"lib": [
|
"lib": [
|
||||||
"dom",
|
"dom",
|
||||||
"dom.iterable",
|
"dom.iterable",
|
||||||
@@ -15,7 +15,7 @@
|
|||||||
"forceConsistentCasingInFileNames": true,
|
"forceConsistentCasingInFileNames": true,
|
||||||
"noFallthroughCasesInSwitch": true,
|
"noFallthroughCasesInSwitch": true,
|
||||||
"module": "esnext",
|
"module": "esnext",
|
||||||
"moduleResolution": "node",
|
"moduleResolution": "bundler",
|
||||||
"resolveJsonModule": true,
|
"resolveJsonModule": true,
|
||||||
"isolatedModules": true,
|
"isolatedModules": true,
|
||||||
"noEmit": true
|
"noEmit": true
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
import react from '@vitejs/plugin-react-swc'
|
import react from '@vitejs/plugin-react'
|
||||||
import ViteYaml from '@modyfi/vite-plugin-yaml'
|
import ViteYaml from '@modyfi/vite-plugin-yaml'
|
||||||
import { defineConfig } from 'vite'
|
import { defineConfig } from 'vite'
|
||||||
|
|
||||||
|
|||||||
@@ -64,7 +64,7 @@ func main() {
|
|||||||
cfg.Server.QueueSize = 2
|
cfg.Server.QueueSize = 2
|
||||||
}
|
}
|
||||||
|
|
||||||
// 6. Frontend FS
|
// Frontend FS
|
||||||
var appFS fs.FS
|
var appFS fs.FS
|
||||||
if fp := v.GetString("frontend_path"); fp != "" {
|
if fp := v.GetString("frontend_path"); fp != "" {
|
||||||
appFS = os.DirFS(fp)
|
appFS = os.DirFS(fp)
|
||||||
|
|||||||
+31
-30
@@ -7,58 +7,59 @@ import (
|
|||||||
)
|
)
|
||||||
|
|
||||||
type Config struct {
|
type Config struct {
|
||||||
Server ServerConfig `yaml:"server"`
|
Server ServerConfig `mapstructure:"server"`
|
||||||
Logging LoggingConfig `yaml:"logging"`
|
Logging LoggingConfig `mapstructure:"logging"`
|
||||||
Paths PathsConfig `yaml:"paths"`
|
Paths PathsConfig `mapstructure:"paths"`
|
||||||
Authentication AuthConfig `yaml:"authentication"`
|
Authentication AuthConfig `mapstructure:"authentication"`
|
||||||
OpenId OpenIdConfig `yaml:"openid"`
|
OpenId OpenIdConfig `mapstructure:"openid"`
|
||||||
Frontend FrontendConfig `yaml:"frontend"`
|
Frontend FrontendConfig `mapstructure:"frontend"`
|
||||||
AutoArchive bool `yaml:"auto_archive"`
|
AutoArchive bool `mapstructure:"auto_archive"`
|
||||||
Twitch TwitchConfig `yaml:"twitch"`
|
Twitch TwitchConfig `mapstructure:"twitch"`
|
||||||
path string
|
path string
|
||||||
}
|
}
|
||||||
|
|
||||||
type ServerConfig struct {
|
type ServerConfig struct {
|
||||||
BaseURL string `yaml:"base_url"`
|
BaseURL string `mapstructure:"base_url"`
|
||||||
Host string `yaml:"host"`
|
Host string `mapstructure:"host"`
|
||||||
Port int `yaml:"port"`
|
Port int `mapstructure:"port"`
|
||||||
QueueSize int `yaml:"queue_size"`
|
QueueSize int `mapstructure:"queue_size"`
|
||||||
}
|
}
|
||||||
|
|
||||||
type LoggingConfig struct {
|
type LoggingConfig struct {
|
||||||
LogPath string `yaml:"log_path"`
|
LogPath string `mapstructure:"log_path"`
|
||||||
EnableFileLogging bool `yaml:"enable_file_logging"`
|
EnableFileLogging bool `mapstructure:"enable_file_logging"`
|
||||||
}
|
}
|
||||||
|
|
||||||
type PathsConfig struct {
|
type PathsConfig struct {
|
||||||
DownloadPath string `yaml:"download_path"`
|
DownloadPath string `mapstructure:"download_path"`
|
||||||
DownloaderPath string `yaml:"downloader_path"`
|
DownloaderPath string `mapstructure:"downloader_path"`
|
||||||
LocalDatabasePath string `yaml:"local_database_path"`
|
LocalDatabasePath string `mapstructure:"local_database_path"`
|
||||||
|
JSRuntimePath string `mapstructure:"js_runtime_path"`
|
||||||
}
|
}
|
||||||
|
|
||||||
type AuthConfig struct {
|
type AuthConfig struct {
|
||||||
RequireAuth bool `yaml:"require_auth"`
|
RequireAuth bool `mapstructure:"require_auth"`
|
||||||
Username string `yaml:"username"`
|
Username string `mapstructure:"username"`
|
||||||
PasswordHash string `yaml:"password"`
|
PasswordHash string `mapstructure:"password_hash"`
|
||||||
}
|
}
|
||||||
|
|
||||||
type OpenIdConfig struct {
|
type OpenIdConfig struct {
|
||||||
UseOpenId bool `yaml:"use_openid"`
|
UseOpenId bool `mapstructure:"use_openid"`
|
||||||
ProviderURL string `yaml:"openid_provider_url"`
|
ProviderURL string `mapstructure:"provider_url"`
|
||||||
ClientId string `yaml:"openid_client_id"`
|
ClientId string `mapstructure:"client_id"`
|
||||||
ClientSecret string `yaml:"openid_client_secret"`
|
ClientSecret string `mapstructure:"client_secret"`
|
||||||
RedirectURL string `yaml:"openid_redirect_url"`
|
RedirectURL string `mapstructure:"redirect_url"`
|
||||||
EmailWhitelist []string `yaml:"openid_email_whitelist"`
|
EmailWhitelist []string `mapstructure:"email_whitelist"`
|
||||||
}
|
}
|
||||||
|
|
||||||
type FrontendConfig struct {
|
type FrontendConfig struct {
|
||||||
FrontendPath string `yaml:"frontend_path"`
|
FrontendPath string `mapstructure:"frontend_path"`
|
||||||
}
|
}
|
||||||
|
|
||||||
type TwitchConfig struct {
|
type TwitchConfig struct {
|
||||||
ClientId string `yaml:"client_id"`
|
ClientId string `mapstructure:"client_id"`
|
||||||
ClientSecret string `yaml:"client_secret"`
|
ClientSecret string `mapstructure:"client_secret"`
|
||||||
CheckInterval time.Duration `yaml:"check_interval"`
|
CheckInterval time.Duration `mapstructure:"check_interval"`
|
||||||
}
|
}
|
||||||
|
|
||||||
var (
|
var (
|
||||||
|
|||||||
@@ -8,7 +8,7 @@ import (
|
|||||||
type Downloader interface {
|
type Downloader interface {
|
||||||
Start() error
|
Start() error
|
||||||
Stop() error
|
Stop() error
|
||||||
Status() *internal.ProcessSnapshot
|
Status() internal.ProcessSnapshot
|
||||||
|
|
||||||
SetOutput(output internal.DownloadOutput)
|
SetOutput(output internal.DownloadOutput)
|
||||||
SetProgress(progress internal.DownloadProgress)
|
SetProgress(progress internal.DownloadProgress)
|
||||||
|
|||||||
@@ -54,6 +54,9 @@ func NewGenericDownload(url string, params []string) Downloader {
|
|||||||
// in base
|
// in base
|
||||||
g.Id = uuid.NewString()
|
g.Id = uuid.NewString()
|
||||||
g.URL = url
|
g.URL = url
|
||||||
|
g.Params = params
|
||||||
|
g.Completed = false
|
||||||
|
|
||||||
return g
|
return g
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -89,6 +92,10 @@ func (g *GenericDownloader) Start() error {
|
|||||||
"--progress-template",
|
"--progress-template",
|
||||||
templateReplacer.Replace(postprocessTemplate),
|
templateReplacer.Replace(postprocessTemplate),
|
||||||
"--no-exec",
|
"--no-exec",
|
||||||
|
"--js-runtimes",
|
||||||
|
config.Instance().Paths.JSRuntimePath,
|
||||||
|
"--remote-components",
|
||||||
|
"ejs:github",
|
||||||
}
|
}
|
||||||
|
|
||||||
// if user asked to manually override the output path...
|
// if user asked to manually override the output path...
|
||||||
@@ -164,8 +171,8 @@ func (g *GenericDownloader) Stop() error {
|
|||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (g *GenericDownloader) Status() *internal.ProcessSnapshot {
|
func (g *GenericDownloader) Status() internal.ProcessSnapshot {
|
||||||
return &internal.ProcessSnapshot{
|
return internal.ProcessSnapshot{
|
||||||
Id: g.Id,
|
Id: g.Id,
|
||||||
Info: g.Metadata,
|
Info: g.Metadata,
|
||||||
Progress: g.progress,
|
Progress: g.progress,
|
||||||
|
|||||||
@@ -41,6 +41,7 @@ func NewLiveStreamDownloader(url string, pipes []pipes.Pipe) Downloader {
|
|||||||
// in base
|
// in base
|
||||||
l.Id = uuid.NewString()
|
l.Id = uuid.NewString()
|
||||||
l.URL = url
|
l.URL = url
|
||||||
|
l.pipes = pipes
|
||||||
return l
|
return l
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -87,7 +88,7 @@ func (l *LiveStreamDownloader) Start() error {
|
|||||||
cancel()
|
cancel()
|
||||||
}()
|
}()
|
||||||
|
|
||||||
// --- costruisci pipeline ---
|
// build pipeline
|
||||||
reader := io.Reader(media)
|
reader := io.Reader(media)
|
||||||
for _, pipe := range l.pipes {
|
for _, pipe := range l.pipes {
|
||||||
nr, err := pipe.Connect(reader)
|
nr, err := pipe.Connect(reader)
|
||||||
@@ -98,7 +99,6 @@ func (l *LiveStreamDownloader) Start() error {
|
|||||||
reader = nr
|
reader = nr
|
||||||
}
|
}
|
||||||
|
|
||||||
// --- fallback: se nessun FileWriter, scrivi su file ---
|
|
||||||
if !l.hasFileWriter() {
|
if !l.hasFileWriter() {
|
||||||
go func() {
|
go func() {
|
||||||
filepath.Join(
|
filepath.Join(
|
||||||
@@ -122,7 +122,6 @@ func (l *LiveStreamDownloader) Start() error {
|
|||||||
}()
|
}()
|
||||||
}
|
}
|
||||||
|
|
||||||
// --- logs consumer ---
|
|
||||||
logs := make(chan []byte)
|
logs := make(chan []byte)
|
||||||
go produceLogs(stderr, logs)
|
go produceLogs(stderr, logs)
|
||||||
go consumeLogs(ctx, logs, l.logConsumer, l)
|
go consumeLogs(ctx, logs, l.logConsumer, l)
|
||||||
@@ -156,8 +155,8 @@ func (l *LiveStreamDownloader) Stop() error {
|
|||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (l *LiveStreamDownloader) Status() *internal.ProcessSnapshot {
|
func (l *LiveStreamDownloader) Status() internal.ProcessSnapshot {
|
||||||
return &internal.ProcessSnapshot{
|
return internal.ProcessSnapshot{
|
||||||
Id: l.Id,
|
Id: l.Id,
|
||||||
Info: l.Metadata,
|
Info: l.Metadata,
|
||||||
Progress: l.progress,
|
Progress: l.progress,
|
||||||
|
|||||||
@@ -100,7 +100,7 @@ func (m *Store) All() *[]internal.ProcessSnapshot {
|
|||||||
|
|
||||||
m.mu.RLock()
|
m.mu.RLock()
|
||||||
for _, v := range m.table {
|
for _, v := range m.table {
|
||||||
running = append(running, *(v.Status()))
|
running = append(running, v.Status())
|
||||||
}
|
}
|
||||||
m.mu.RUnlock()
|
m.mu.RUnlock()
|
||||||
|
|
||||||
|
|||||||
@@ -50,7 +50,7 @@ func (m *MessageQueue) Publish(d downloaders.Downloader) {
|
|||||||
// Workers: download + metadata
|
// Workers: download + metadata
|
||||||
func (m *MessageQueue) SetupConsumers() {
|
func (m *MessageQueue) SetupConsumers() {
|
||||||
// N parallel workers for downloadQueue
|
// N parallel workers for downloadQueue
|
||||||
for i := 0; i < m.concurrency; i++ {
|
for i := 1; i < m.concurrency+1; i++ {
|
||||||
go m.downloadWorker(i)
|
go m.downloadWorker(i)
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -60,6 +60,8 @@ func (m *MessageQueue) SetupConsumers() {
|
|||||||
|
|
||||||
// Worker dei download
|
// Worker dei download
|
||||||
func (m *MessageQueue) downloadWorker(workerId int) {
|
func (m *MessageQueue) downloadWorker(workerId int) {
|
||||||
|
slog.Info("download worker spawned", slog.Int("worker", workerId))
|
||||||
|
|
||||||
for {
|
for {
|
||||||
select {
|
select {
|
||||||
case <-m.ctx.Done():
|
case <-m.ctx.Done():
|
||||||
@@ -72,25 +74,22 @@ func (m *MessageQueue) downloadWorker(workerId int) {
|
|||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
|
|
||||||
slog.Info("download worker started",
|
slog.Info("download worker starting download",
|
||||||
slog.Int("worker", workerId),
|
slog.Int("worker", workerId),
|
||||||
slog.String("id", p.GetId()),
|
slog.String("id", p.GetId()),
|
||||||
)
|
)
|
||||||
|
|
||||||
p.Start()
|
m.metadataQueue <- p
|
||||||
|
slog.Info("queued for metadata", slog.String("id", p.GetId()))
|
||||||
|
|
||||||
// after the download starts succesfully we pass it to the metadata queue
|
p.Start()
|
||||||
select {
|
|
||||||
case m.metadataQueue <- p:
|
|
||||||
slog.Info("queued for metadata", slog.String("id", p.GetId()))
|
|
||||||
case <-m.ctx.Done():
|
|
||||||
return
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (m *MessageQueue) metadataWorker() {
|
func (m *MessageQueue) metadataWorker() {
|
||||||
|
slog.Info("metadata worker spawned", slog.Int("worker", 1))
|
||||||
|
|
||||||
for {
|
for {
|
||||||
select {
|
select {
|
||||||
case <-m.ctx.Done():
|
case <-m.ctx.Done():
|
||||||
@@ -111,6 +110,7 @@ func (m *MessageQueue) metadataWorker() {
|
|||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
|
|
||||||
|
slog.Info("metadata worker started", slog.String("id", p.GetId()))
|
||||||
p.SetMetadata(metadata.DefaultFetcher)
|
p.SetMetadata(metadata.DefaultFetcher)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -10,11 +10,11 @@ import (
|
|||||||
/*
|
/*
|
||||||
Applicable modifiers
|
Applicable modifiers
|
||||||
|
|
||||||
full | short | description
|
full | short | description
|
||||||
---------------------------------------------------------------------------------
|
---------------------------------------------------------------------------------
|
||||||
--playlist-start NUMBER | -I NUMBER: | discard first N entries
|
--playlist-start NUMBER | -I NUMBER: | discard first N entries
|
||||||
--playlist-end NUMBER | -I :NUMBER | discard last N entries
|
--playlist-end NUMBER | -I :NUMBER | discard last N entries
|
||||||
--playlist-reverse | -I ::-1 | self explanatory
|
--playlist-reverse | -I ::-1 | self explanatory
|
||||||
--max-downloads NUMBER | | stops after N completed downloads
|
--max-downloads NUMBER | | stops after N completed downloads
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
|||||||
@@ -172,7 +172,7 @@ func (s *Service) DeleteTemplate(ctx context.Context, id string) error {
|
|||||||
|
|
||||||
func (s *Service) GetVersion(ctx context.Context) (string, string, error) {
|
func (s *Service) GetVersion(ctx context.Context) (string, string, error) {
|
||||||
//TODO: load from realease properties file, or anything else outside code
|
//TODO: load from realease properties file, or anything else outside code
|
||||||
const CURRENT_RPC_VERSION = "3.2.6"
|
const CURRENT_RPC_VERSION = "4.0.0"
|
||||||
|
|
||||||
result := make(chan string, 1)
|
result := make(chan string, 1)
|
||||||
|
|
||||||
|
|||||||
@@ -139,12 +139,13 @@ func (s *Service) Kill(args string, killed *string) error {
|
|||||||
return errors.New("nil process")
|
return errors.New("nil process")
|
||||||
}
|
}
|
||||||
|
|
||||||
|
s.db.Delete(download.GetId())
|
||||||
|
|
||||||
if err := download.Stop(); err != nil {
|
if err := download.Stop(); err != nil {
|
||||||
slog.Info("failed killing process", slog.String("id", download.GetId()), slog.Any("err", err))
|
slog.Info("failed killing process", slog.String("id", download.GetId()), slog.Any("err", err))
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
s.db.Delete(download.GetId())
|
|
||||||
slog.Info("succesfully killed process", slog.String("id", download.GetId()))
|
slog.Info("succesfully killed process", slog.String("id", download.GetId()))
|
||||||
|
|
||||||
return nil
|
return nil
|
||||||
|
|||||||
@@ -69,7 +69,6 @@ func Run(ctx context.Context, rc *RunConfig) error {
|
|||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
// ---- LOGGING ---------------------------------------------------
|
|
||||||
logWriters := []io.Writer{
|
logWriters := []io.Writer{
|
||||||
os.Stdout,
|
os.Stdout,
|
||||||
observableLogger, // for web-ui
|
observableLogger, // for web-ui
|
||||||
@@ -102,7 +101,6 @@ func Run(ctx context.Context, rc *RunConfig) error {
|
|||||||
|
|
||||||
// make the new logger the default one with all the new writers
|
// make the new logger the default one with all the new writers
|
||||||
slog.SetDefault(logger)
|
slog.SetDefault(logger)
|
||||||
// ----------------------------------------------------------------
|
|
||||||
|
|
||||||
mq, err := queue.NewMessageQueue()
|
mq, err := queue.NewMessageQueue()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
|||||||
@@ -0,0 +1,100 @@
|
|||||||
|
time=2026-06-29T12:10:42.936+02:00 level=INFO msg="download worker spawned" worker=3
|
||||||
|
time=2026-06-29T12:10:42.936+02:00 level=INFO msg="metadata worker spawned" worker=1
|
||||||
|
time=2026-06-29T12:10:42.936+02:00 level=INFO msg="download worker spawned" worker=1
|
||||||
|
time=2026-06-29T12:10:42.936+02:00 level=INFO msg="download worker spawned" worker=4
|
||||||
|
time=2026-06-29T12:10:42.936+02:00 level=INFO msg="download worker spawned" worker=2
|
||||||
|
time=2026-06-29T12:10:42.936+02:00 level=INFO msg="published download" id=98c62f5e-0fda-4dc3-b59f-f6e8e4d9c7a2
|
||||||
|
time=2026-06-29T12:10:42.936+02:00 level=INFO msg="published download" id=cd696a78-21a9-41d4-9a3f-47b75ed0cb38
|
||||||
|
time=2026-06-29T12:10:42.936+02:00 level=INFO msg="download worker starting download" worker=1 id=cd696a78-21a9-41d4-9a3f-47b75ed0cb38
|
||||||
|
time=2026-06-29T12:10:42.936+02:00 level=INFO msg="queued for metadata" id=cd696a78-21a9-41d4-9a3f-47b75ed0cb38
|
||||||
|
time=2026-06-29T12:10:42.936+02:00 level=INFO msg="download worker starting download" worker=3 id=98c62f5e-0fda-4dc3-b59f-f6e8e4d9c7a2
|
||||||
|
time=2026-06-29T12:10:42.936+02:00 level=INFO msg="queued for metadata" id=98c62f5e-0fda-4dc3-b59f-f6e8e4d9c7a2
|
||||||
|
time=2026-06-29T12:10:42.936+02:00 level=INFO msg="requesting download" url="https://www.youtube.com/watch?v=-fZM9wOvbh0" params="[https://www.youtube.com/watch?v=-fZM9wOvbh0 --newline --no-colors --no-playlist --progress-template download:{\"eta\":%(progress.eta)s,\"percentage\":\"%(progress._percent_str)s\",\"speed\":%(progress.speed)s} --progress-template postprocess:{\"filepath\":\"%(info.filepath)s\"} --no-exec --js-runtimes deno:/home/marco/.deno/bin/deno --remote-components ejs:github -o ./downloads/%(title)s.%(ext)s -o ./downloads/%(title)s.%(ext)s]"
|
||||||
|
time=2026-06-29T12:10:42.936+02:00 level=INFO msg="metadata worker started" id=cd696a78-21a9-41d4-9a3f-47b75ed0cb38
|
||||||
|
time=2026-06-29T12:10:42.936+02:00 level=INFO msg="metadata worker started" id=cd696a78-21a9-41d4-9a3f-47b75ed0cb38
|
||||||
|
time=2026-06-29T12:10:42.936+02:00 level=INFO msg="requesting download" url="https://www.youtube.com/watch?v=-fZM9wOvbh0" params="[https://www.youtube.com/watch?v=-fZM9wOvbh0 --newline --no-colors --no-playlist --progress-template download:{\"eta\":%(progress.eta)s,\"percentage\":\"%(progress._percent_str)s\",\"speed\":%(progress.speed)s} --progress-template postprocess:{\"filepath\":\"%(info.filepath)s\"} --no-exec --js-runtimes deno:/home/marco/.deno/bin/deno --remote-components ejs:github -r 50K -o ./downloads/%(title)s.%(ext)s -o ./downloads/%(title)s.%(ext)s -o ./downloads/%(title)s.%(ext)s]"
|
||||||
|
time=2026-06-29T12:10:42.936+02:00 level=INFO msg="retrieving metadata" url="https://www.youtube.com/watch?v=-fZM9wOvbh0"
|
||||||
|
time=2026-06-29T12:10:42.945+02:00 level=INFO msg="yt-dlp-webui started" address=0.0.0.0:3033
|
||||||
|
time=2026-06-29T12:10:43.031+02:00 level=ERROR msg="yt-dlp process error" id=cd696a78-21a9-41d4-9a3f-47b75ed0cb38 url="https://www.youtube.com/watch?v=-fZM9wOvbh0" err="WARNING: Your yt-dlp version (2026.03.17) is older than 90 days!"
|
||||||
|
time=2026-06-29T12:10:43.031+02:00 level=ERROR msg="yt-dlp process error" id=cd696a78-21a9-41d4-9a3f-47b75ed0cb38 url="https://www.youtube.com/watch?v=-fZM9wOvbh0" err=" It is strongly recommended to always use the latest version."
|
||||||
|
time=2026-06-29T12:10:43.031+02:00 level=ERROR msg="yt-dlp process error" id=cd696a78-21a9-41d4-9a3f-47b75ed0cb38 url="https://www.youtube.com/watch?v=-fZM9wOvbh0" err=" As yt-dlp has been installed via apt, you should use that to update. If you're on a stable release, also check backports.."
|
||||||
|
time=2026-06-29T12:10:43.031+02:00 level=ERROR msg="yt-dlp process error" id=cd696a78-21a9-41d4-9a3f-47b75ed0cb38 url="https://www.youtube.com/watch?v=-fZM9wOvbh0" err=" To suppress this warning, add --no-update to your command/config."
|
||||||
|
time=2026-06-29T12:10:43.033+02:00 level=ERROR msg="yt-dlp process error" id=98c62f5e-0fda-4dc3-b59f-f6e8e4d9c7a2 url="https://www.youtube.com/watch?v=-fZM9wOvbh0" err="WARNING: Your yt-dlp version (2026.03.17) is older than 90 days!"
|
||||||
|
time=2026-06-29T12:10:43.033+02:00 level=ERROR msg="yt-dlp process error" id=98c62f5e-0fda-4dc3-b59f-f6e8e4d9c7a2 url="https://www.youtube.com/watch?v=-fZM9wOvbh0" err=" It is strongly recommended to always use the latest version."
|
||||||
|
time=2026-06-29T12:10:43.033+02:00 level=ERROR msg="yt-dlp process error" id=98c62f5e-0fda-4dc3-b59f-f6e8e4d9c7a2 url="https://www.youtube.com/watch?v=-fZM9wOvbh0" err=" As yt-dlp has been installed via apt, you should use that to update. If you're on a stable release, also check backports.."
|
||||||
|
time=2026-06-29T12:10:43.033+02:00 level=ERROR msg="yt-dlp process error" id=98c62f5e-0fda-4dc3-b59f-f6e8e4d9c7a2 url="https://www.youtube.com/watch?v=-fZM9wOvbh0" err=" To suppress this warning, add --no-update to your command/config."
|
||||||
|
time=2026-06-29T12:10:44.859+02:00 level=INFO msg="metadata worker started" id=98c62f5e-0fda-4dc3-b59f-f6e8e4d9c7a2
|
||||||
|
time=2026-06-29T12:10:44.859+02:00 level=INFO msg="metadata worker started" id=98c62f5e-0fda-4dc3-b59f-f6e8e4d9c7a2
|
||||||
|
time=2026-06-29T12:10:44.860+02:00 level=INFO msg="retrieving metadata" url="https://www.youtube.com/watch?v=-fZM9wOvbh0"
|
||||||
|
time=2026-06-29T12:10:45.115+02:00 level=INFO msg=progress id=cd696a78 url="https://www.youtube.com/watch?v=-fZM9wOvbh0" percentage=" 94.5%"
|
||||||
|
time=2026-06-29T12:10:45.115+02:00 level=INFO msg=progress id=cd696a78 url="https://www.youtube.com/watch?v=-fZM9wOvbh0" percentage=" 94.5%"
|
||||||
|
time=2026-06-29T12:10:45.135+02:00 level=INFO msg=progress id=cd696a78 url="https://www.youtube.com/watch?v=-fZM9wOvbh0" percentage=" 94.5%"
|
||||||
|
time=2026-06-29T12:10:45.153+02:00 level=INFO msg=progress id=cd696a78 url="https://www.youtube.com/watch?v=-fZM9wOvbh0" percentage=" 94.5%"
|
||||||
|
time=2026-06-29T12:10:45.172+02:00 level=INFO msg=progress id=cd696a78 url="https://www.youtube.com/watch?v=-fZM9wOvbh0" percentage=" 94.5%"
|
||||||
|
time=2026-06-29T12:10:45.196+02:00 level=INFO msg=progress id=cd696a78 url="https://www.youtube.com/watch?v=-fZM9wOvbh0" percentage=" 94.5%"
|
||||||
|
time=2026-06-29T12:10:45.229+02:00 level=INFO msg=progress id=cd696a78 url="https://www.youtube.com/watch?v=-fZM9wOvbh0" percentage=" 94.5%"
|
||||||
|
time=2026-06-29T12:10:45.234+02:00 level=INFO msg=progress id=98c62f5e url="https://www.youtube.com/watch?v=-fZM9wOvbh0" percentage=" 94.5%"
|
||||||
|
time=2026-06-29T12:10:45.263+02:00 level=INFO msg=progress id=cd696a78 url="https://www.youtube.com/watch?v=-fZM9wOvbh0" percentage=" 94.6%"
|
||||||
|
time=2026-06-29T12:10:45.274+02:00 level=INFO msg=progress id=98c62f5e url="https://www.youtube.com/watch?v=-fZM9wOvbh0" percentage=" 94.5%"
|
||||||
|
time=2026-06-29T12:10:45.305+02:00 level=INFO msg=progress id=cd696a78 url="https://www.youtube.com/watch?v=-fZM9wOvbh0" percentage=" 94.6%"
|
||||||
|
time=2026-06-29T12:10:45.348+02:00 level=INFO msg=progress id=cd696a78 url="https://www.youtube.com/watch?v=-fZM9wOvbh0" percentage=" 94.7%"
|
||||||
|
time=2026-06-29T12:10:45.354+02:00 level=INFO msg=progress id=98c62f5e url="https://www.youtube.com/watch?v=-fZM9wOvbh0" percentage=" 94.5%"
|
||||||
|
time=2026-06-29T12:10:45.394+02:00 level=INFO msg=progress id=cd696a78 url="https://www.youtube.com/watch?v=-fZM9wOvbh0" percentage=" 95.0%"
|
||||||
|
time=2026-06-29T12:10:45.407+02:00 level=INFO msg=progress id=cd696a78 url="https://www.youtube.com/watch?v=-fZM9wOvbh0" percentage=" 95.0%"
|
||||||
|
time=2026-06-29T12:10:45.428+02:00 level=INFO msg=progress id=cd696a78 url="https://www.youtube.com/watch?v=-fZM9wOvbh0" percentage=" 95.0%"
|
||||||
|
time=2026-06-29T12:10:45.428+02:00 level=INFO msg=progress id=cd696a78 url="https://www.youtube.com/watch?v=-fZM9wOvbh0" percentage=" 95.0%"
|
||||||
|
time=2026-06-29T12:10:45.428+02:00 level=INFO msg=progress id=cd696a78 url="https://www.youtube.com/watch?v=-fZM9wOvbh0" percentage=" 95.0%"
|
||||||
|
time=2026-06-29T12:10:45.429+02:00 level=INFO msg=progress id=cd696a78 url="https://www.youtube.com/watch?v=-fZM9wOvbh0" percentage=" 95.0%"
|
||||||
|
time=2026-06-29T12:10:45.429+02:00 level=INFO msg=progress id=cd696a78 url="https://www.youtube.com/watch?v=-fZM9wOvbh0" percentage=" 95.0%"
|
||||||
|
time=2026-06-29T12:10:45.429+02:00 level=INFO msg=progress id=cd696a78 url="https://www.youtube.com/watch?v=-fZM9wOvbh0" percentage=" 95.0%"
|
||||||
|
time=2026-06-29T12:10:45.429+02:00 level=INFO msg=progress id=cd696a78 url="https://www.youtube.com/watch?v=-fZM9wOvbh0" percentage=" 95.0%"
|
||||||
|
time=2026-06-29T12:10:45.430+02:00 level=INFO msg=progress id=cd696a78 url="https://www.youtube.com/watch?v=-fZM9wOvbh0" percentage=" 95.1%"
|
||||||
|
time=2026-06-29T12:10:45.433+02:00 level=INFO msg=progress id=cd696a78 url="https://www.youtube.com/watch?v=-fZM9wOvbh0" percentage=" 95.1%"
|
||||||
|
time=2026-06-29T12:10:45.437+02:00 level=INFO msg=progress id=cd696a78 url="https://www.youtube.com/watch?v=-fZM9wOvbh0" percentage=" 95.1%"
|
||||||
|
time=2026-06-29T12:10:45.446+02:00 level=INFO msg=progress id=cd696a78 url="https://www.youtube.com/watch?v=-fZM9wOvbh0" percentage=" 95.2%"
|
||||||
|
time=2026-06-29T12:10:45.475+02:00 level=INFO msg=progress id=cd696a78 url="https://www.youtube.com/watch?v=-fZM9wOvbh0" percentage=" 95.3%"
|
||||||
|
time=2026-06-29T12:10:45.504+02:00 level=INFO msg=progress id=cd696a78 url="https://www.youtube.com/watch?v=-fZM9wOvbh0" percentage=" 95.5%"
|
||||||
|
time=2026-06-29T12:10:45.514+02:00 level=INFO msg=progress id=98c62f5e url="https://www.youtube.com/watch?v=-fZM9wOvbh0" percentage=" 94.5%"
|
||||||
|
time=2026-06-29T12:10:45.525+02:00 level=INFO msg=progress id=cd696a78 url="https://www.youtube.com/watch?v=-fZM9wOvbh0" percentage=" 95.6%"
|
||||||
|
time=2026-06-29T12:10:45.549+02:00 level=INFO msg=progress id=cd696a78 url="https://www.youtube.com/watch?v=-fZM9wOvbh0" percentage=" 95.6%"
|
||||||
|
time=2026-06-29T12:10:45.551+02:00 level=INFO msg=progress id=cd696a78 url="https://www.youtube.com/watch?v=-fZM9wOvbh0" percentage=" 95.6%"
|
||||||
|
time=2026-06-29T12:10:45.556+02:00 level=INFO msg=progress id=cd696a78 url="https://www.youtube.com/watch?v=-fZM9wOvbh0" percentage=" 95.6%"
|
||||||
|
time=2026-06-29T12:10:45.565+02:00 level=INFO msg=progress id=cd696a78 url="https://www.youtube.com/watch?v=-fZM9wOvbh0" percentage=" 95.7%"
|
||||||
|
time=2026-06-29T12:10:45.583+02:00 level=INFO msg=progress id=cd696a78 url="https://www.youtube.com/watch?v=-fZM9wOvbh0" percentage=" 95.8%"
|
||||||
|
time=2026-06-29T12:10:45.619+02:00 level=INFO msg=progress id=cd696a78 url="https://www.youtube.com/watch?v=-fZM9wOvbh0" percentage=" 96.0%"
|
||||||
|
time=2026-06-29T12:10:45.633+02:00 level=INFO msg=progress id=cd696a78 url="https://www.youtube.com/watch?v=-fZM9wOvbh0" percentage=" 96.1%"
|
||||||
|
time=2026-06-29T12:10:45.687+02:00 level=INFO msg=progress id=cd696a78 url="https://www.youtube.com/watch?v=-fZM9wOvbh0" percentage=" 96.1%"
|
||||||
|
time=2026-06-29T12:10:45.687+02:00 level=INFO msg=progress id=cd696a78 url="https://www.youtube.com/watch?v=-fZM9wOvbh0" percentage=" 96.1%"
|
||||||
|
time=2026-06-29T12:10:45.689+02:00 level=INFO msg=progress id=cd696a78 url="https://www.youtube.com/watch?v=-fZM9wOvbh0" percentage=" 96.1%"
|
||||||
|
time=2026-06-29T12:10:45.691+02:00 level=INFO msg=progress id=cd696a78 url="https://www.youtube.com/watch?v=-fZM9wOvbh0" percentage=" 96.1%"
|
||||||
|
time=2026-06-29T12:10:45.696+02:00 level=INFO msg=progress id=cd696a78 url="https://www.youtube.com/watch?v=-fZM9wOvbh0" percentage=" 96.2%"
|
||||||
|
time=2026-06-29T12:10:45.705+02:00 level=INFO msg=progress id=cd696a78 url="https://www.youtube.com/watch?v=-fZM9wOvbh0" percentage=" 96.2%"
|
||||||
|
time=2026-06-29T12:10:45.723+02:00 level=INFO msg=progress id=cd696a78 url="https://www.youtube.com/watch?v=-fZM9wOvbh0" percentage=" 96.3%"
|
||||||
|
time=2026-06-29T12:10:45.759+02:00 level=INFO msg=progress id=cd696a78 url="https://www.youtube.com/watch?v=-fZM9wOvbh0" percentage=" 96.6%"
|
||||||
|
time=2026-06-29T12:10:45.772+02:00 level=INFO msg=progress id=cd696a78 url="https://www.youtube.com/watch?v=-fZM9wOvbh0" percentage=" 96.6%"
|
||||||
|
time=2026-06-29T12:10:45.829+02:00 level=INFO msg=progress id=cd696a78 url="https://www.youtube.com/watch?v=-fZM9wOvbh0" percentage=" 96.7%"
|
||||||
|
time=2026-06-29T12:10:45.831+02:00 level=INFO msg=progress id=cd696a78 url="https://www.youtube.com/watch?v=-fZM9wOvbh0" percentage=" 96.7%"
|
||||||
|
time=2026-06-29T12:10:45.834+02:00 level=INFO msg=progress id=98c62f5e url="https://www.youtube.com/watch?v=-fZM9wOvbh0" percentage=" 94.5%"
|
||||||
|
time=2026-06-29T12:10:45.835+02:00 level=INFO msg=progress id=cd696a78 url="https://www.youtube.com/watch?v=-fZM9wOvbh0" percentage=" 96.7%"
|
||||||
|
time=2026-06-29T12:10:45.844+02:00 level=INFO msg=progress id=cd696a78 url="https://www.youtube.com/watch?v=-fZM9wOvbh0" percentage=" 96.8%"
|
||||||
|
time=2026-06-29T12:10:45.864+02:00 level=INFO msg=progress id=cd696a78 url="https://www.youtube.com/watch?v=-fZM9wOvbh0" percentage=" 96.9%"
|
||||||
|
time=2026-06-29T12:10:45.899+02:00 level=INFO msg=progress id=cd696a78 url="https://www.youtube.com/watch?v=-fZM9wOvbh0" percentage=" 97.1%"
|
||||||
|
time=2026-06-29T12:10:45.915+02:00 level=INFO msg=progress id=cd696a78 url="https://www.youtube.com/watch?v=-fZM9wOvbh0" percentage=" 97.2%"
|
||||||
|
time=2026-06-29T12:10:45.969+02:00 level=INFO msg=progress id=cd696a78 url="https://www.youtube.com/watch?v=-fZM9wOvbh0" percentage=" 97.2%"
|
||||||
|
time=2026-06-29T12:10:45.969+02:00 level=INFO msg=progress id=cd696a78 url="https://www.youtube.com/watch?v=-fZM9wOvbh0" percentage=" 97.2%"
|
||||||
|
time=2026-06-29T12:10:45.969+02:00 level=INFO msg=progress id=cd696a78 url="https://www.youtube.com/watch?v=-fZM9wOvbh0" percentage=" 97.2%"
|
||||||
|
time=2026-06-29T12:10:45.969+02:00 level=INFO msg=progress id=cd696a78 url="https://www.youtube.com/watch?v=-fZM9wOvbh0" percentage=" 97.2%"
|
||||||
|
time=2026-06-29T12:10:45.970+02:00 level=INFO msg=progress id=cd696a78 url="https://www.youtube.com/watch?v=-fZM9wOvbh0" percentage=" 97.2%"
|
||||||
|
time=2026-06-29T12:10:45.970+02:00 level=INFO msg=progress id=cd696a78 url="https://www.youtube.com/watch?v=-fZM9wOvbh0" percentage=" 97.2%"
|
||||||
|
time=2026-06-29T12:10:45.970+02:00 level=INFO msg=progress id=cd696a78 url="https://www.youtube.com/watch?v=-fZM9wOvbh0" percentage=" 97.2%"
|
||||||
|
time=2026-06-29T12:10:45.971+02:00 level=INFO msg=progress id=cd696a78 url="https://www.youtube.com/watch?v=-fZM9wOvbh0" percentage=" 97.2%"
|
||||||
|
time=2026-06-29T12:10:45.974+02:00 level=INFO msg=progress id=cd696a78 url="https://www.youtube.com/watch?v=-fZM9wOvbh0" percentage=" 97.2%"
|
||||||
|
time=2026-06-29T12:10:45.978+02:00 level=INFO msg=progress id=cd696a78 url="https://www.youtube.com/watch?v=-fZM9wOvbh0" percentage=" 97.2%"
|
||||||
|
time=2026-06-29T12:10:45.987+02:00 level=INFO msg=progress id=cd696a78 url="https://www.youtube.com/watch?v=-fZM9wOvbh0" percentage=" 97.3%"
|
||||||
|
time=2026-06-29T12:10:46.005+02:00 level=INFO msg=progress id=cd696a78 url="https://www.youtube.com/watch?v=-fZM9wOvbh0" percentage=" 97.4%"
|
||||||
|
time=2026-06-29T12:10:46.041+02:00 level=INFO msg=progress id=cd696a78 url="https://www.youtube.com/watch?v=-fZM9wOvbh0" percentage=" 97.6%"
|
||||||
|
time=2026-06-29T12:10:46.055+02:00 level=INFO msg=progress id=cd696a78 url="https://www.youtube.com/watch?v=-fZM9wOvbh0" percentage=" 97.7%"
|
||||||
|
time=2026-06-29T12:10:46.109+02:00 level=INFO msg=progress id=cd696a78 url="https://www.youtube.com/watch?v=-fZM9wOvbh0" percentage=" 97.7%"
|
||||||
|
time=2026-06-29T12:10:46.111+02:00 level=INFO msg=progress id=cd696a78 url="https://www.youtube.com/watch?v=-fZM9wOvbh0" percentage=" 97.7%"
|
||||||
|
time=2026-06-29T12:10:46.114+02:00 level=INFO msg=progress id=cd696a78 url="https://www.youtube.com/watch?v=-fZM9wOvbh0" percentage=" 97.7%"
|
||||||
|
time=2026-06-29T12:10:46.119+02:00 level=INFO msg=progress id=cd696a78 url="https://www.youtube.com/watch?v=-fZM9wOvbh0" percentage=" 97.8%"
|
||||||
Reference in New Issue
Block a user