Documentation
¶
Overview ¶
Package downloader wraps YouTube stream extraction, format selection and file writing for the chunder CLI.
Index ¶
- func CaptionLanguages(video *youtube.Video) []string
- func ConvertToMP3(ctx context.Context, in, out string) error
- func EmbedSubtitles(ctx context.Context, videoPath, srtPath, lang string) error
- func Extension(format *youtube.Format) string
- func FFmpegAvailable() bool
- func FFplayAvailable() bool
- func HumanBytes(n int64) string
- func IsPlaylistURL(raw string) bool
- func Mux(ctx context.Context, videoPath, audioPath, out string) error
- func ParseTimestamp(s string) (time.Duration, error)
- func SanitizeFilename(name string) string
- func SelectPlayback(video *youtube.Video) (vf, af *youtube.Format, muxed bool, err error)
- func UniquePath(path string) string
- type Client
- func (c *Client) DownloadSubtitles(ctx context.Context, video *youtube.Video, lang, dir, basename string) (string, error)
- func (c *Client) GetVideo(ctx context.Context, url string) (*youtube.Video, error)
- func (c *Client) Run(ctx context.Context, opts Options, ev Events) (string, error)
- func (c *Client) RunClip(ctx context.Context, opts Options, ev Events) (string, error)
- func (c *Client) RunPlaylist(ctx context.Context, opts Options, plOpts PlaylistOptions, ev PlaylistEvents) (done, failed int, err error)
- func (c *Client) StreamURL(ctx context.Context, video *youtube.Video, format *youtube.Format) (string, error)
- type Events
- type Options
- type PlaylistEvents
- type PlaylistOptions
- type Selection
Constants ¶
This section is empty.
Variables ¶
This section is empty.
Functions ¶
func CaptionLanguages ¶
CaptionLanguages lists the language codes a video has captions for, auto-generated ones marked with "(auto)".
func ConvertToMP3 ¶
ConvertToMP3 re-encodes an audio file to mp3 with ffmpeg. -q:a 2 is LAME VBR at roughly 190 kbps — transparent for YouTube-quality sources.
func EmbedSubtitles ¶
EmbedSubtitles muxes an SRT file into an mp4 as a soft subtitle track (mov_text), replacing the file in place. Streams are copied, not re-encoded.
func FFmpegAvailable ¶
func FFmpegAvailable() bool
FFmpegAvailable reports whether ffmpeg is on PATH (needed to mux 1080p+).
func FFplayAvailable ¶
func FFplayAvailable() bool
FFplayAvailable reports whether ffplay is on PATH (used for watch audio).
func IsPlaylistURL ¶
IsPlaylistURL reports whether a URL points at a whole playlist rather than a single video. Watch links that merely carry playlist context (watch?v=…&list=…) count as single videos.
func Mux ¶
Mux combines a video-only and audio-only file into out using stream copy (no re-encoding), so it is fast and lossless.
func ParseTimestamp ¶
ParseTimestamp reads clip positions in any of the common shapes: "1:23" (m:ss), "1:02:03" (h:mm:ss), "83" (seconds), "1m23s" (Go duration).
func SanitizeFilename ¶
SanitizeFilename makes a video title safe to use as a filename.
func SelectPlayback ¶
SelectPlayback picks a lightweight format pair for terminal playback. Terminal "screens" are ~200×112 pixels, so 360p is plenty; muxed formats are preferred because one URL then carries both video and audio.
func UniquePath ¶
UniquePath returns path, or path with " (n)" inserted before the extension if a file already exists there, so downloads never overwrite silently.
Types ¶
type Client ¶
type Client struct {
// contains filtered or unexported fields
}
Client fetches video metadata and streams from YouTube.
func (*Client) DownloadSubtitles ¶
func (c *Client) DownloadSubtitles(ctx context.Context, video *youtube.Video, lang, dir, basename string) (string, error)
DownloadSubtitles fetches the lang caption track and writes it as an SRT file named "<basename>.<lang>.srt" in dir, returning the file path.
func (*Client) Run ¶
Run executes a full download: resolve metadata, pick formats, fetch the stream(s), and mux if needed. It returns the final file path.
func (*Client) RunClip ¶
RunClip downloads just the [From, To] segment of a video by letting ffmpeg seek into the stream URL(s) with HTTP range requests — only the clip's bytes are transferred. Cutting is stream-copy, so it lands on keyframes: the clip may start up to a couple of seconds before the requested time.
func (*Client) RunPlaylist ¶
func (c *Client) RunPlaylist(ctx context.Context, opts Options, plOpts PlaylistOptions, ev PlaylistEvents) (done, failed int, err error)
RunPlaylist downloads every selected entry of a playlist sequentially into a folder named after the playlist. It returns counts of succeeded and failed items; err is only non-nil when the whole run couldn't proceed.
type Events ¶
type Events interface {
// Info fires once metadata is resolved and formats are chosen.
Info(video *youtube.Video, sel *Selection)
// StreamStart fires before each stream download. label is "video" or
// "audio"; size is the expected byte count (0 if unknown).
StreamStart(label string, size int64)
// StreamProgress reports newly downloaded bytes for the active stream.
StreamProgress(label string, delta int64)
// StreamDone fires when a stream finishes.
StreamDone(label string)
// MuxStart fires before ffmpeg combines video and audio.
MuxStart()
// ConvertStart fires before ffmpeg re-encodes audio (e.g. to mp3).
ConvertStart(format string)
// ClipStart fires before ffmpeg extracts a clip segment.
ClipStart(from, to time.Duration)
// SubsStart fires before subtitles are fetched (only when requested).
SubsStart(lang string)
// SubsDone fires after the subtitle attempt: path on success, err on
// failure. Subtitle failures never fail the download itself.
SubsDone(path string, err error)
}
Events receives progress callbacks while Run executes. Implementations drive the UI — the fancy TUI and the plain fallback both implement this.
type Options ¶
type Options struct {
URL string
Quality string
OutputDir string
Filename string
AudioOnly bool
// AudioFormat converts audio downloads: "" or "m4a" keeps the native
// stream, "mp3" re-encodes with ffmpeg.
AudioFormat string
SubsLang string // e.g. "en": also download subtitles as .srt
EmbedSubs bool // mux subtitles into the mp4 (needs ffmpeg)
// ClipFrom/ClipTo select a segment instead of the whole video (ClipTo
// zero means "until the end"). Requires ffmpeg.
ClipFrom time.Duration
ClipTo time.Duration
}
Options describes a single download request.
type PlaylistEvents ¶
type PlaylistEvents interface {
Events
// PlaylistInfo fires once the playlist is resolved. items is the queue
// after applying Limit/Reverse; dest is the folder files land in.
PlaylistInfo(pl *youtube.Playlist, items []*youtube.PlaylistEntry, dest string)
// ItemStart fires before each queue item is fetched.
ItemStart(index int, entry *youtube.PlaylistEntry)
// ItemDone fires after each queue item: path on success, err on failure.
// One bad video does not stop the queue.
ItemDone(index int, path string, err error)
}
PlaylistEvents extends Events with playlist-level lifecycle callbacks. The embedded Events fire for whichever item is currently downloading.
type PlaylistOptions ¶
type PlaylistOptions struct {
Limit int // 0 = every video
Reverse bool // download oldest-first on playlists sorted newest-first
}
PlaylistOptions controls how much of a playlist is downloaded.
type Selection ¶
type Selection struct {
Video *youtube.Format // nil for audio-only downloads
Audio *youtube.Format // set when muxing or audio-only; nil when Video is already muxed
// NeedsMux is true when Video and Audio are separate streams that must
// be combined with ffmpeg.
NeedsMux bool
// FellBack is a human-readable note set when the requested quality was
// unavailable and a lower one was chosen instead.
FellBack string
}
Selection describes which stream(s) will be downloaded for a request.
func SelectFormats ¶
SelectFormats picks the streams to download for the requested quality.
YouTube serves low resolutions (usually ≤720p) as single "muxed" files with audio included, and higher resolutions as separate video-only and audio-only streams. When the target quality only exists as a separate stream, ffmpeg is required to mux; without it we fall back to the best muxed format.