Skip to content

Commit f710a6d

Browse files
author
TubeAgentKit
committed
v0.4.0: getTranscriptLanguages for GET /transcript/languages (free)
1 parent b8b918d commit f710a6d

7 files changed

Lines changed: 61 additions & 1 deletion

File tree

‎README.md‎

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -58,6 +58,15 @@ Each segment is `{ start, duration, text }` with `start` and `duration` in secon
5858
| `cached` | `true` when served from the stored copy rather than fetched from YouTube just now |
5959
| `fetched_at` | ISO 8601 time it was fetched from YouTube |
6060

61+
Not sure which languages a video has? `getTranscriptLanguages` lists them for free, before you spend a credit:
62+
63+
```ts
64+
const { default_language_code, languages } = await client.getTranscriptLanguages({ v: "kJQP7kiw5Fk" });
65+
for (const lang of languages) console.log(lang.language_code, lang.caption_type, lang.name); // "es manual Spanish"
66+
```
67+
68+
An empty `languages` list means the video has captions turned off.
69+
6170
### Batch: many videos at once
6271

6372
Queue up to 100 videos in one call; transcripts are fetched in the background. Submitting is free, each video that returns a transcript costs 1 credit, and failed videos are never charged (10 videos where 2 have no captions = 8 credits).
@@ -163,6 +172,7 @@ try {
163172
| Method | Endpoint | Credits |
164173
| --- | --- | --- |
165174
| `getTranscript(params)` | `GET /transcript` (optional `timestamps: true`) | 1 |
175+
| `getTranscriptLanguages(params)` | `GET /transcript/languages` | free |
166176
| `createBatch(params)` | `POST /batch` (up to 100 videos) | 1 per successful video |
167177
| `getBatch(params)` / `waitForBatch(id)` | `GET /batch` | free |
168178
| `search(params)` | `GET /search` | 1 |

‎package.json‎

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
{
22
"name": "@tubeagentkit/getyoutubetranscript",
3-
"version": "0.3.0",
3+
"version": "0.4.0",
44
"description": "YouTube transcript API for Node.js and TypeScript: get YouTube video transcripts, captions and subtitles with timestamps, search YouTube, and list channel and playlist videos. No proxies or headless browser.",
55
"type": "module",
66
"main": "./dist/index.cjs",

‎src/client.ts‎

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@ import type {
1212
CreditsData,
1313
GetChannelLatestParams,
1414
GetPlaylistParams,
15+
GetTranscriptLanguagesParams,
1516
GetTranscriptParams,
1617
GetYouTubeTranscriptOptions,
1718
ListChannelVideosParams,
@@ -23,6 +24,7 @@ import type {
2324
SearchParams,
2425
SignupResponse,
2526
TranscriptData,
27+
TranscriptLanguagesData,
2628
VerifySignupResponse,
2729
} from "./types.js";
2830

@@ -154,6 +156,14 @@ export class GetYouTubeTranscript {
154156
});
155157
}
156158

159+
/**
160+
* The caption languages a video offers (manual and auto-generated), before
161+
* fetching one. Free. An empty `languages` list means captions are turned off.
162+
*/
163+
getTranscriptLanguages(params: GetTranscriptLanguagesParams): Promise<TranscriptLanguagesData> {
164+
return this.get<TranscriptLanguagesData>("/transcript/languages", { v: params.v });
165+
}
166+
157167
/**
158168
* Queue transcripts for up to 100 videos in one call. Free to submit:
159169
* 1 credit per video that returns a transcript, failed videos are never

‎src/index.ts‎

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@ export type {
1717
GetBatchParams,
1818
GetChannelLatestParams,
1919
GetPlaylistParams,
20+
GetTranscriptLanguagesParams,
2021
GetTranscriptParams,
2122
GetYouTubeTranscriptOptions,
2223
ListChannelVideosParams,
@@ -32,6 +33,8 @@ export type {
3233
SignupResponse,
3334
TranscriptData,
3435
TranscriptFields,
36+
TranscriptLanguage,
37+
TranscriptLanguagesData,
3538
VerifySignupResponse,
3639
VideoResult,
3740
WaitForBatchOptions,

‎src/types.ts‎

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -74,6 +74,30 @@ export interface TranscriptData extends TranscriptFields {
7474
cached: boolean;
7575
}
7676

77+
// ---------------------------------------------------------------------------
78+
// GET /transcript/languages (free)
79+
// ---------------------------------------------------------------------------
80+
81+
export interface GetTranscriptLanguagesParams {
82+
/** YouTube video URL (full or short) or an 11-character video ID. */
83+
v: string;
84+
}
85+
86+
export interface TranscriptLanguage {
87+
language_code: string;
88+
/** YouTube's display name, e.g. "English (auto-generated)". */
89+
name: string;
90+
caption_type: "manual" | "auto";
91+
}
92+
93+
export interface TranscriptLanguagesData {
94+
video_id: string;
95+
/** What `getTranscript` returns with no `language`; `null` when the video has no captions. */
96+
default_language_code: string | null;
97+
/** One per language and caption type. Empty when the video has captions turned off. */
98+
languages: TranscriptLanguage[];
99+
}
100+
77101
// ---------------------------------------------------------------------------
78102
// POST /batch, GET /batch
79103
// ---------------------------------------------------------------------------

‎test/batch.test.ts‎

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,13 @@ describe("batch methods", () => {
2121
client = new GetYouTubeTranscript({ apiKey: "sk_live_test123", fetch: fetchMock as unknown as typeof fetch });
2222
});
2323

24+
it("getTranscriptLanguages sends the video param", async () => {
25+
const data = { video_id: "kJQP7kiw5Fk", default_language_code: "en", languages: [{ language_code: "en", name: "English", caption_type: "manual" }] };
26+
fetchMock.mockResolvedValueOnce(jsonResponse(200, { success: true, data }));
27+
expect(await client.getTranscriptLanguages({ v: "https://youtu.be/kJQP7kiw5Fk" })).toEqual(data);
28+
expect(fetchMock.mock.calls[0][0]).toBe(`${BASE}/transcript/languages?v=https%3A%2F%2Fyoutu.be%2FkJQP7kiw5Fk`);
29+
});
30+
2431
it("createBatch POSTs a JSON body with the Idempotency-Key header", async () => {
2532
fetchMock.mockResolvedValueOnce(jsonResponse(202, batch("queued", { webhook_secret: "whsec_x" })));
2633
const result = await client.createBatch({

‎test/live.integration.test.ts‎

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -36,6 +36,12 @@ describe.skipIf(!apiKey)("live integration", () => {
3636
20_000,
3737
);
3838

39+
it("getTranscriptLanguages lists caption languages (free)", async () => {
40+
const data = await client.getTranscriptLanguages({ v: "jNQXAC9IVRw" });
41+
expect(data.languages.length).toBeGreaterThan(0);
42+
expect(data.languages.map((lang) => lang.language_code)).toContain(data.default_language_code);
43+
}, 20_000);
44+
3945
it("getCredits returns the key's plan and balance (free)", async () => {
4046
const data = await client.getCredits();
4147
expect(typeof data.plan_credits_left).toBe("number");

0 commit comments

Comments
 (0)