用Java下载Wizard&Cat音频
- 2026-10-24 18:42:21
import java.io.*;
import java.util.concurrent.TimeUnit;
publicclass BatchBilibiliAudioDownloader {
// ==================== 配置区 ====================
privatestaticfinal String BASE_URL = "https://www.bilibili.com/video/BV1nv421y7Zs/";
privatestaticfinalintSTART_P = 1;
privatestaticfinalintEND_P = 72;
privatestaticfinal String OUTPUT_DIR = "BilibiliAudio";
// yt-dlp 可执行文件绝对路径(终端执行 which yt-dlp 获取)
privatestaticfinal String YT_DLP_PATH = "/usr/local/bin/yt-dlp";
// 读取 Cookie 的浏览器:safari / chrome / firefox / edge
privatestaticfinal String BROWSER_FOR_COOKIE = "safari";
// ffmpeg/ffprobe 所在目录(Homebrew 安装通常为 /opt/homebrew/bin)
privatestaticfinal String FFMPEG_LOCATION = "/opt/homebrew/bin";
// ==================== 主方法 ====================
publicstaticvoid main(String[] args) {
File dir = new File(OUTPUT_DIR);
if (!dir.exists()) dir.mkdirs();
intsuccess = 0, fail = 0, skip = 0;
for (intp = START_P; p <= END_P; p++) {
// 断点续传:检查 xxWizzard.mp3 是否已存在
String expectedName = String.format("%02dWizzard.mp3", p);
File existing = new File(dir, expectedName);
if (existing.exists()) {
System.out.println("⏭️ P" + p + " 已存在,跳过: " + expectedName);
skip++;
continue;
}
String videoUrl = BASE_URL + "?p=" + p;
System.out.println("\n========== 正在处理 P" + p + " ==========");
System.out.println("URL: " + videoUrl);
booleanok = downloadAudio(videoUrl, p);
if (ok) {
success++;
System.out.println("✅ P" + p + " 完成 -> " + expectedName);
} else {
fail++;
System.err.println("❌ P" + p + " 失败");
}
try {
TimeUnit.SECONDS.sleep(2);
} catch (InterruptedException e) {
Thread.currentThread().interrupt();
break;
}
}
System.out.println("\n========== 全部任务结束 ==========");
System.out.println("成功: " + success + " 失败: " + fail + " 跳过: " + skip);
}
// ==================== 单个 P 的音频下载 ====================
privatestaticboolean downloadAudio(String videoUrl, intp) {
// 输出文件名固定为 01Wizzard、02Wizzard ...
String outputTemplate = String.format("%s/%02dWizzard.%%(ext)s", OUTPUT_DIR, p);
ProcessBuilder pb = new ProcessBuilder(
YT_DLP_PATH,
"-x",
"--audio-format", "mp3",
"--audio-quality", "0",
"-o", outputTemplate,
"--cookies-from-browser", BROWSER_FOR_COOKIE,
"--no-update",
"--ffmpeg-location", FFMPEG_LOCATION,
videoUrl
);
pb.redirectErrorStream(true);
String currentPath = pb.environment().getOrDefault("PATH", "");
pb.environment().put("PATH",
FFMPEG_LOCATION + ":/usr/local/bin:/usr/bin:/bin:" + currentPath);
try {
Process process = pb.start();
try (BufferedReader reader = new BufferedReader(
new InputStreamReader(process.getInputStream()))) {
String line;
while ((line = reader.readLine()) != null) {
System.out.println("[yt-dlp] " + line);
}
}
booleanfinished = process.waitFor(30, TimeUnit.MINUTES);
if (!finished) {
process.destroyForcibly();
System.err.println("P" + p + " 下载超时");
returnfalse;
}
returnprocess.exitValue() == 0;
} catch (IOException | InterruptedException e) {
System.err.println("执行 yt-dlp 异常: " + e.getMessage());
returnfalse;
}
}
}