subtitle
Generate SRT or VTT subtitles from audio or video files. Provide a URL and choose your preferred format.
Instructions
Generate SRT or VTT subtitles from audio or video. Cost: 2 credits.
Input Schema
| Name | Required | Description | Default |
|---|---|---|---|
| audio_url | Yes | URL to audio or video file | |
| format | No | srt or vtt | srt |
Implementation Reference
- src/index.ts:145-152 (schema)Schema definition for the 'subtitle' tool: input schema specifying 'audio_url' (required string) and 'format' (optional, defaults to 'srt', accepts 'srt' or 'vtt').
{ name: "subtitle", description: "Generate SRT or VTT subtitles from audio or video. Cost: 2 credits.", inputSchema: { audio_url: z.string().describe("URL to audio or video file"), format: z.string().optional().default("srt").describe("srt or vtt"), }, }, - src/index.ts:247-259 (registration)Registration of the 'subtitle' tool via the generic loop that iterates over all capabilities. The tool name 'subtitle' is used as the first argument to server.registerTool().
for (const cap of CAPABILITIES) { // Cast inputSchema to avoid TS2589 (excessively deep type instantiation from Zod chains) server.registerTool( cap.name, { description: cap.description, inputSchema: cap.inputSchema as any, }, async (args: any): Promise<CallToolResult> => { return callSuprsonic(cap.name, args as Record<string, unknown>); }, ); } - src/index.ts:183-234 (handler)Handler function for the 'subtitle' tool. It calls the Suprsonic REST API at /v1/agent with capability='subtitle' and the input params (audio_url, format). The response is returned as JSON text.
async function callSuprsonic(capability: string, params: Record<string, unknown>): Promise<CallToolResult> { if (!API_KEY) { return { content: [{ type: "text", text: "Error: SUPRSONIC_API_KEY environment variable is not set. Get your key at https://suprsonic.ai/app/apis" }], isError: true, }; } try { const resp = await fetch(`${BASE_URL}/v1/agent`, { method: "POST", headers: { "Authorization": `Bearer ${API_KEY}`, "Content-Type": "application/json", }, body: JSON.stringify({ capability, params }), }); const result = await resp.json() as any; // Handle non-envelope responses (401, 429, etc. return {"detail": ...}) if (result.detail && result.success === undefined) { const msg = typeof result.detail === "object" ? (result.detail.title || result.detail.detail || JSON.stringify(result.detail)) : String(result.detail); return { content: [{ type: "text", text: `Error (HTTP ${resp.status}): ${msg}` }], isError: true, }; } if (!result.success) { const errMsg = result.error?.detail || result.error?.title || "Request failed"; return { content: [{ type: "text", text: `Error: ${errMsg}` }], isError: true, }; } const text = JSON.stringify(result.data, null, 2); const meta = result.metadata ? `\n\n[Provider: ${(result.metadata as any).provider_used || "unknown"}, ${(result.metadata as any).response_time_ms || 0}ms, ${result.credits_used || 0} credits]` : ""; return { content: [{ type: "text", text: text + meta }], }; } catch (err) { return { content: [{ type: "text", text: `Network error: ${err instanceof Error ? err.message : String(err)}` }], isError: true, }; } }