nix/modules/yt-dlp.nix
2025-09-16 18:06:06 +02:00

301 lines
9.6 KiB
Nix

{ config, pkgs, lib, ... }:
with lib;
let
cfg = config.programs.yt-dlp-custom;
in
{
options.programs.yt-dlp-custom = {
enable = mkEnableOption "yt-dlp video downloader configuration";
package = mkOption {
type = types.package;
default = pkgs.yt-dlp;
example = "pkgs.yt-dlp";
description = "yt-dlp package to use";
};
downloadDir = mkOption {
type = types.str;
default = "~/Downloads/Videos";
example = "/mnt/storage/videos";
description = "Base directory for downloaded videos";
};
};
config = mkIf cfg.enable {
# Install yt-dlp and ffmpeg
home.packages = with pkgs; [
cfg.package
ffmpeg
];
# Cookie files - managed by Nix (read-only)
# The download function copies these to temp files when needed
home.file.".config/yt-dlp/cookies-youtube.txt" = {
source = ../config/yt-dlp/cookies-youtube.txt;
};
home.file.".config/yt-dlp/cookies-bilibili.txt" = {
source = ../config/yt-dlp/cookies-bilibili.txt;
};
# Create yt-dlp configuration file
home.file.".config/yt-dlp/config".text = ''
# Quality settings
--format "bestvideo[ext=mp4]+bestaudio[ext=m4a]/best[ext=mp4]/best"
--merge-output-format mp4
# Download options
--no-playlist
--embed-thumbnail
--write-thumbnail
--embed-subs
--sub-langs "en,zh-CN,zh-TW"
--write-auto-subs
--write-description
--write-info-json
# File naming and organization
# Allow unicode characters in filenames for Chinese/Japanese content
# Performance
--concurrent-fragments 4
--retries 10
--fragment-retries 10
# SponsorBlock for YouTube
--sponsorblock-mark all
# User agent
--user-agent "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/120.0.0.0 Safari/537.36"
'';
# Shell aliases for different download types
programs.zsh.shellAliases = {
# YouTube downloads
dl-yt = "download-youtube";
dl-yt-p = "download-youtube-playlist";
# Bilibili downloads
dl-bili = "download-bilibili";
dl-bili-p = "download-bilibili-playlist";
# Help
dl-help = "download-help";
};
programs.zsh.initContent = ''
# Base download directory
DOWNLOAD_DIR="${cfg.downloadDir}"
DOWNLOAD_DIR="''${DOWNLOAD_DIR/#\~/$HOME}"
# Helper function to create writable cookie file
_setup_temp_cookies() {
local cookies_file="$1"
if [[ -f "$cookies_file" ]]; then
local temp_cookies="/tmp/yt-dlp-cookies-$$.txt"
cp "$cookies_file" "$temp_cookies" 2>/dev/null
chmod 644 "$temp_cookies" 2>/dev/null
echo "$temp_cookies"
else
echo ""
fi
}
# YouTube single video download
download-youtube() {
local url="$*"
if [[ -z "$url" ]]; then
echo "Usage: dl-yt <url>"
return 1
fi
local cookies_file="$HOME/.config/yt-dlp/cookies-youtube.txt"
local temp_cookies=$(_setup_temp_cookies "$cookies_file")
local output_template="$DOWNLOAD_DIR/YouTube/%(uploader|)s%(channel|)s%(uploader_id|)s/%(upload_date>%Y%m%d|)s-%(title)s.%(ext)s"
local archive_file="$DOWNLOAD_DIR/.archive.txt"
mkdir -p "$DOWNLOAD_DIR"
echo "Downloading YouTube video..."
echo "Output directory: $DOWNLOAD_DIR/YouTube"
local cmd="yt-dlp"
[[ -n "$temp_cookies" ]] && cmd="$cmd --cookies '$temp_cookies'" || cmd="$cmd --no-cookies"
cmd="$cmd --download-archive '$archive_file' -o '$output_template' '$url'"
eval $cmd
local result=$?
# Clean up temp cookies
[[ -n "$temp_cookies" ]] && rm -f "$temp_cookies"
if [[ $result -eq 0 ]]; then
echo " Download completed successfully"
else
echo " Download failed"
return 1
fi
}
# YouTube playlist download
download-youtube-playlist() {
local url="$*"
if [[ -z "$url" ]]; then
echo "Usage: dl-yt-p <playlist-url>"
return 1
fi
local cookies_file="$HOME/.config/yt-dlp/cookies-youtube.txt"
local temp_cookies=$(_setup_temp_cookies "$cookies_file")
local output_template="$DOWNLOAD_DIR/YouTube/%(playlist_title|)s%(playlist|)s/%(playlist_index|)03d-%(title)s.%(ext)s"
local archive_file="$DOWNLOAD_DIR/.archive.txt"
mkdir -p "$DOWNLOAD_DIR"
echo "Downloading YouTube playlist..."
echo "Output directory: $DOWNLOAD_DIR/YouTube"
local cmd="yt-dlp --yes-playlist"
[[ -n "$temp_cookies" ]] && cmd="$cmd --cookies '$temp_cookies'" || cmd="$cmd --no-cookies"
cmd="$cmd --download-archive '$archive_file' -o '$output_template' '$url'"
eval $cmd
local result=$?
# Clean up temp cookies
[[ -n "$temp_cookies" ]] && rm -f "$temp_cookies"
if [[ $result -eq 0 ]]; then
echo " Playlist download completed successfully"
else
echo " Playlist download failed"
return 1
fi
}
# Bilibili single video download
download-bilibili() {
local url="$*"
if [[ -z "$url" ]]; then
echo "Usage: dl-bili <url>"
return 1
fi
local cookies_file="$HOME/.config/yt-dlp/cookies-bilibili.txt"
local temp_cookies=$(_setup_temp_cookies "$cookies_file")
local output_template="$DOWNLOAD_DIR/Bilibili/%(uploader|)s%(channel|)s%(uploader_id|)s/%(upload_date>%Y%m%d|)s-%(title)s.%(ext)s"
local archive_file="$DOWNLOAD_DIR/.archive.txt"
mkdir -p "$DOWNLOAD_DIR"
echo "Downloading Bilibili video..."
echo "Output directory: $DOWNLOAD_DIR/Bilibili"
local cmd="yt-dlp --referer https://www.bilibili.com/"
[[ -n "$temp_cookies" ]] && cmd="$cmd --cookies '$temp_cookies'" || cmd="$cmd --no-cookies"
cmd="$cmd --download-archive '$archive_file' -o '$output_template' '$url'"
eval $cmd
local result=$?
# Clean up temp cookies
[[ -n "$temp_cookies" ]] && rm -f "$temp_cookies"
if [[ $result -eq 0 ]]; then
echo " Download completed successfully"
else
echo " Download failed"
return 1
fi
}
# Bilibili playlist/collection download
download-bilibili-playlist() {
local url="$*"
if [[ -z "$url" ]]; then
echo "Usage: dl-bili-p <playlist-url>"
return 1
fi
local cookies_file="$HOME/.config/yt-dlp/cookies-bilibili.txt"
local temp_cookies=$(_setup_temp_cookies "$cookies_file")
local output_template="$DOWNLOAD_DIR/Bilibili/%(playlist_title|)s%(playlist|)s/%(playlist_index|)03d-%(title)s.%(ext)s"
local archive_file="$DOWNLOAD_DIR/.archive.txt"
mkdir -p "$DOWNLOAD_DIR"
echo "Downloading Bilibili playlist..."
echo "Output directory: $DOWNLOAD_DIR/Bilibili"
local cmd="yt-dlp --yes-playlist --referer https://www.bilibili.com/"
[[ -n "$temp_cookies" ]] && cmd="$cmd --cookies '$temp_cookies'" || cmd="$cmd --no-cookies"
cmd="$cmd --download-archive '$archive_file' -o '$output_template' '$url'"
eval $cmd
local result=$?
# Clean up temp cookies
[[ -n "$temp_cookies" ]] && rm -f "$temp_cookies"
if [[ $result -eq 0 ]]; then
echo " Playlist download completed successfully"
else
echo " Playlist download failed"
return 1
fi
}
# Function to show help and instructions
download-help() {
cat << 'EOF'
Video Download Commands:
YouTube:
dl-yt <url> - Download single YouTube video
dl-yt-p <url> - Download YouTube playlist
Bilibili:
dl-bili <url> - Download single Bilibili video
dl-bili-p <url> - Download Bilibili playlist/collection
Other commands:
dl-clear-archive - Clear download history (allows re-downloading)
dl-help - Show this help message
Cookies Update Instructions:
1. Install a browser extension:
- Chrome/Edge: "Get cookies.txt LOCALLY"
- Firefox: "cookies.txt"
2. Log in to the website (youtube.com or bilibili.com)
3. Click the extension and export cookies
4. Save the cookies:
- YouTube: ~/.config/yt-dlp/cookies-youtube.txt
- Bilibili: ~/.config/yt-dlp/cookies-bilibili.txt
Alternative method using yt-dlp:
yt-dlp --cookies-from-browser firefox --cookies cookies-youtube.txt "https://youtube.com"
yt-dlp --cookies-from-browser firefox --cookies cookies-bilibili.txt "https://bilibili.com"
EOF
}
# Function to clear download archive
dl-clear-archive() {
local archive_file="$DOWNLOAD_DIR/.archive.txt"
if [[ -f "$archive_file" ]]; then
echo "Clearing download archive: $archive_file"
rm -f "$archive_file"
echo " Archive cleared. Videos can now be re-downloaded."
else
echo "No archive file found at: $archive_file"
fi
}
# Alias for backward compatibility
alias dlv-clear-archive='dl-clear-archive'
'';
};
}