feat: improve auto-generated subtitles support

- Update downloadSubtitles to properly handle auto-generated subtitles
- Update listSubtitles to show all available subtitles including auto-generated ones
- Update tool descriptions to clearly indicate auto-generated subtitles support
- Simplify error handling to show direct yt-dlp messages
- Bump version to 0.6.17
This commit is contained in:
kevin
2025-02-21 15:46:33 +08:00
parent e1d09fc3ca
commit f9c93a0463

View File

@@ -14,7 +14,7 @@ import * as path from "path";
import { spawnPromise } from "spawn-rx";
import { rimraf } from "rimraf";
const VERSION = '0.6.16';
const VERSION = '0.6.17';
/**
* System Configuration
@@ -101,7 +101,7 @@ server.setRequestHandler(ListToolsRequestSchema, async () => {
tools: [
{
name: "list_video_subtitles",
description: "List all available subtitles for a video",
description: "List all available subtitles for a video, including auto-generated captions",
inputSchema: {
type: "object",
properties: {
@@ -112,12 +112,12 @@ server.setRequestHandler(ListToolsRequestSchema, async () => {
},
{
name: "download_video_subtitles",
description: "Download video subtitles in any available format. Supports both regular and auto-generated subtitles.",
description: "Download video subtitles in any available format. Supports both regular and auto-generated subtitles in various languages.",
inputSchema: {
type: "object",
properties: {
url: { type: "string", description: "URL of the video" },
language: { type: "string", description: "Language code (e.g., 'en', 'zh-Hant', 'ja'). Optional, defaults to 'en'" },
language: { type: "string", description: "Language code (e.g., 'en', 'zh-Hant', 'ja'). Will try to get auto-generated subtitles if regular subtitles are not available." },
},
required: ["url"],
},
@@ -157,12 +157,6 @@ class VideoDownloadError extends Error {
}
}
class SubtitleError extends VideoDownloadError {
constructor(message: string, code: string = 'SUBTITLE_ERROR', cause?: Error) {
super(message, code, cause);
this.name = 'SubtitleError';
}
}
/**
* Error code mappings
@@ -239,35 +233,19 @@ async function listSubtitles(url: string): Promise<string> {
const tempDirectory = fs.mkdtempSync(path.join(os.tmpdir(), "ytdlp-"));
try {
validateUrl(url, SubtitleError);
validateUrl(url);
// 列出所有字幕,包括自動生成的
// 同時列出一般字幕和自動生成的字幕
const result = await spawnPromise(
"yt-dlp",
[
"--list-subs",
"--write-auto-sub",
"--list-subs", // 列出一般字幕
"--write-auto-sub", // 包含自動生成的字幕
"--skip-download",
url
],
{ cwd: tempDirectory }
);
// 如果沒有一般字幕,再列出自動生成的字幕
if (result.includes('has no subtitles')) {
const autoSubResult = await spawnPromise(
"yt-dlp",
[
"--list-subs",
"--write-auto-sub",
"--skip-download",
url
],
{ cwd: tempDirectory }
);
return autoSubResult;
}
return result;
} catch (error) {
// 直接傳遞 yt-dlp 的錯誤訊息
@@ -284,21 +262,18 @@ async function downloadSubtitles(url: string, language: string = "en"): Promise<
const tempDirectory = fs.mkdtempSync(path.join(os.tmpdir(), "ytdlp-"));
try {
validateUrl(url, SubtitleError);
validateUrl(url);
if (!/^[a-z]{2,3}(-[A-Z][a-z]{3})?(-[A-Z]{2})?$/i.test(language)) {
throw new SubtitleError(
ERROR_CODES.INVALID_LANGUAGE,
'INVALID_LANGUAGE'
);
throw new Error('Invalid language code');
}
// 首先嘗試下載一般字幕
// 直接嘗試下載自動生成的字幕
try {
await spawnPromise(
"yt-dlp",
[
"--write-sub",
"--write-auto-sub", // 使用自動生成的字幕
"--sub-lang",
language,
"--skip-download",
@@ -307,23 +282,8 @@ async function downloadSubtitles(url: string, language: string = "en"): Promise<
{ cwd: tempDirectory }
);
} catch (error) {
// 如果一般字幕下載失敗,則嘗試下載自動生成的英文字幕
try {
await spawnPromise(
"yt-dlp",
[
"--write-auto-sub",
"--sub-lang",
"en", // 強制使用英文
"--skip-download",
url
],
{ cwd: tempDirectory }
);
} catch (autoSubError) {
// 直接拋出 yt-dlp 的錯誤訊息
throw new Error(autoSubError instanceof Error ? autoSubError.message : String(autoSubError));
}
// 直接拋出 yt-dlp 的錯誤訊息
throw error;
}
// 讀取下載的字幕文件