diff --git a/web/formats.go b/web/formats.go
index b1d8342..007f6e1 100644
--- a/web/formats.go
+++ b/web/formats.go
@@ -11,7 +11,7 @@ type Video struct {
}
func GetVideos(meta *metadata.Metadata) []Video {
- if meta.Type == "playlist" {
+ if meta.IsPlaylist() {
return lo.Map(meta.Entries, func(video metadata.Metadata, _ int) Video {
return GetVideos(&video)[0]
})
diff --git a/web/routes.go b/web/routes.go
index 7f7f19e..d737e24 100644
--- a/web/routes.go
+++ b/web/routes.go
@@ -92,7 +92,15 @@ func (r *routes) DownloadProxyHandler(c *fiber.Ctx) error {
return fiber.ErrInternalServerError
}
- format, ok := lo.Find(meta.Formats, func(format metadata.Format) bool {
+ videos := GetVideos(meta)
+ index := c.QueryInt("index")
+
+ if index < 0 || index >= len(videos) {
+ return fiber.ErrBadRequest
+ }
+
+ video := videos[index]
+ format, ok := lo.Find(video.Formats, func(format metadata.Format) bool {
return format.FormatID == formatId
})
if !ok {
@@ -106,5 +114,9 @@ func (r *routes) DownloadProxyHandler(c *fiber.Ctx) error {
c.Set("Content-Length", fmt.Sprint(*format.FilesizeApprox))
}
- return r.ytdl.Download(c.Response().BodyWriter(), url, format.FormatID)
+ if len(videos) == 1 {
+ index = -1
+ }
+
+ return r.ytdl.Download(c.Response().BodyWriter(), url, format.FormatID, index)
}
diff --git a/web/views/download.html b/web/views/download.html
index f9da057..a55660c 100644
--- a/web/views/download.html
+++ b/web/views/download.html
@@ -9,20 +9,6 @@
{{$root := .}}
-{{define "download"}}
-
{{.Format.Format}}
-
-{{end}}
-
{{range $vidIndex, $video := .Videos}}
{{if not (eq $vidIndex 0)}}
@@ -40,7 +26,7 @@
Download (direct)
+ href="{{$root.BasePath}}/download/proxy?url={{queryEscape $root.Url}}&format={{$format.FormatID}}&index={{$vidIndex}}">
Download (proxied)
diff --git a/ytdl/cmdopts.go b/ytdl/cmdopts.go
index 5080bd0..314f7ac 100644
--- a/ytdl/cmdopts.go
+++ b/ytdl/cmdopts.go
@@ -3,6 +3,7 @@ package ytdl
import (
"bytes"
"encoding/json"
+ "fmt"
"io"
"strings"
@@ -99,3 +100,10 @@ func WithDebug() Option {
return nil
}
}
+
+func WithPlaylistIndex(index int) Option {
+ return func(opts *Options) error {
+ opts.args = append(opts.args, "--playlist-items", fmt.Sprint(index+1))
+ return nil
+ }
+}
diff --git a/ytdl/metadata/metadata.go b/ytdl/metadata/metadata.go
index 3e4bac0..9545ed6 100644
--- a/ytdl/metadata/metadata.go
+++ b/ytdl/metadata/metadata.go
@@ -176,3 +176,7 @@ type Metadata struct {
Chapters []Chapter `json:"chapters"`
}
+
+func (m Metadata) IsPlaylist() bool {
+ return m.Type == "playlist"
+}
diff --git a/ytdl/ytdl.go b/ytdl/ytdl.go
index 310017d..1404304 100644
--- a/ytdl/ytdl.go
+++ b/ytdl/ytdl.go
@@ -11,7 +11,7 @@ import (
type Ytdl interface {
GetMetadata(url string) (*metadata.Metadata, error)
- Download(w io.Writer, url, format string) error
+ Download(w io.Writer, url, format string, index int) error
}
type ytdlImpl struct {
@@ -82,13 +82,17 @@ func (y *ytdlImpl) GetMetadata(url string) (*metadata.Metadata, error) {
}
// Download implements Ytdl
-func (y *ytdlImpl) Download(w io.Writer, url, format string) error {
+func (y *ytdlImpl) Download(w io.Writer, url, format string, index int) error {
options := append(
y.baseOptions(url),
WithFormat(format),
WithStreamOutput(w),
)
+ if index >= 0 {
+ options = append(options, WithPlaylistIndex(index))
+ }
+
if err := Exec(y.cfg.Ytdlp.BinaryPath, url, options...); err != nil {
return err
}