From 9b1ac11ff090e396631468c54e6e21e84e44a6d7 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?S=CA=9C=C9=AA=C9=B4=E1=B4=87=C9=AA=20N=E1=B4=8F=E1=B4=9C?= =?UTF-8?q?=E1=B4=A2=E1=B4=87=C9=B4?= <157171073+Shineii86@users.noreply.github.com> Date: Thu, 25 Jun 2026 01:43:11 +0530 Subject: [PATCH] feat: improve subtitle extraction, quality fallback, and documentation --- CHANGELOG.md | 20 ++++++++++++++++++++ README.md | 3 ++- docs/endpoints.md | 28 +++++++++++++++++++++++++++- package.json | 2 +- public/openapi.json | 45 ++++++++++++++++++++++++++++++++++++++++++--- src/helpers/pipe.js | 42 ++++++++++++++++++++++++++++++------------ test.js | 4 ++-- 7 files changed, 124 insertions(+), 20 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 7621ebc..3ffd31a 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,25 @@ # Changelog +## v2.0.1 +### Streaming Improvements — Better subtitle extraction, quality fallback + +#### Streaming Enhancements +- Improved `extractSubtitles` — now handles multiple provider formats (bonk: file/label/kind/language, others: url/name/lang) +- Updated `getBestStream` — falls back to first active HLS stream when quality metadata is missing +- Updated `getDownloadUrl` — now returns subtitles and bestStream in response +- Added subtitle fields: url, label, language, kind, format, encoding, isDefault + +#### Provider Improvements +- Bonk provider confirmed to return subtitles (English, VTT format, captions kind) +- Better handling of providers without quality metadata (bonk, ally, bee return undefined quality) + +#### Verified +- Subtitle extraction working: bonk provider returns 1 English subtitle per episode +- Download URL working: bonk provider returns direct download link +- Batch sources: subtitles included in batch responses + +--- + ## v2.0.0 ### Major Release — 35 endpoints, streaming improvements, new features diff --git a/README.md b/README.md index 81d046c..f0a4f07 100644 --- a/README.md +++ b/README.md @@ -19,7 +19,7 @@ AniList GraphQL Vercel License - Version + Version Endpoints Providers

@@ -1408,6 +1408,7 @@ docker run -p 3000:3000 miruroapi | Version | Date | Key Changes | |:---|:---|:---| +| **2.0.1** | 2026-06-24 | Streaming improvements — better subtitle extraction, quality fallback for providers without metadata | | **2.0.0** | 2026-06-25 | Major upgrade — 35 endpoints, compression, streaming improvements, new features | | **1.4.0** | 2026-06-25 | Creator attribution middleware, Vercel deployment fix, security headers | | **1.3.0** | 2026-06-25 | Full landing page upgrade with premium design | diff --git a/docs/endpoints.md b/docs/endpoints.md index a14e6aa..14f3dfb 100644 --- a/docs/endpoints.md +++ b/docs/endpoints.md @@ -1,6 +1,6 @@ # API Endpoints Reference -Complete documentation for all 35 MiruroAPI v2.0.0 endpoints. +Complete documentation for all 35 MiruroAPI v2.0.1 endpoints. --- @@ -498,6 +498,32 @@ Streaming sources via URL path (recommended). | category | string | sub or dub | | slug | string | Episode slug | +### Response Fields + +| Field | Type | Description | +|-------|------|-------------| +| streams | array | Array of stream objects (hls/embed) | +| download | string | Direct download URL (if available) | +| subtitles | array | Subtitle objects (if available) | +| bestStream | object | Best available HLS stream with quality fallback | + +### Subtitle Object + +| Field | Type | Description | +|-------|------|-------------| +| url | string | VTT subtitle file URL | +| label | string | Display name (e.g., "English") | +| language | string | Language code (e.g., "en") | +| kind | string | "subtitles" or "captions" | +| format | string | "vtt" format | +| encoding | string | "utf-8" | +| isDefault | boolean | Is default subtitle | + +### Note +- Bonk provider returns subtitles (English, VTT format) +- Other providers may not return subtitles +- Quality fallback: 1080p → 720p → 480p → 360p + --- ## Compare diff --git a/package.json b/package.json index 1c94540..2f2e8e1 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "miruro-api", - "version": "2.0.0", + "version": "2.0.1", "description": "RESTful API for miruro.tv - Anime streaming data powered by AniList GraphQL and Miruro streaming providers", "main": "server.js", "scripts": { diff --git a/public/openapi.json b/public/openapi.json index b39a75c..80d3cbb 100644 --- a/public/openapi.json +++ b/public/openapi.json @@ -3,7 +3,7 @@ "info": { "title": "MiruroAPI", "description": "Free RESTful API for anime streaming data. Powered by AniList GraphQL and Miruro streaming providers.", - "version": "2.0.0", + "version": "2.0.1", "contact": { "name": "Shineii86", "url": "https://github.com/Shineii86/MiruroAPI" @@ -339,13 +339,52 @@ "/api/watch/{provider}/{anilistId}/{category}/{slug}": { "get": { "tags": ["Streaming"], - "summary": "Streaming sources (simple)", + "summary": "Streaming sources (simple) with subtitles", + "description": "Returns streaming sources, subtitles (if available), and best stream with quality fallback", "parameters": [ { "name": "provider", "in": "path", "required": true, "schema": { "type": "string" } }, { "name": "anilistId", "in": "path", "required": true, "schema": { "type": "integer" } }, { "name": "category", "in": "path", "required": true, "schema": { "type": "string" } }, { "name": "slug", "in": "path", "required": true, "schema": { "type": "string" } } - ] + ], + "responses": { + "200": { + "description": "Success", + "content": { + "application/json": { + "schema": { + "type": "object", + "properties": { + "success": { "type": "boolean" }, + "results": { + "type": "object", + "properties": { + "streams": { "type": "array" }, + "download": { "type": "string" }, + "subtitles": { + "type": "array", + "items": { + "type": "object", + "properties": { + "url": { "type": "string", "description": "VTT subtitle file URL" }, + "label": { "type": "string", "description": "Display name" }, + "language": { "type": "string", "description": "Language code" }, + "kind": { "type": "string", "description": "subtitles or captions" }, + "format": { "type": "string", "description": "vtt format" }, + "encoding": { "type": "string", "description": "utf-8" }, + "isDefault": { "type": "boolean", "description": "Is default subtitle" } + } + } + }, + "bestStream": { "type": "object" } + } + } + } + } + } + } + } + } } }, "/api/compare/{id1}/{id2}": { diff --git a/src/helpers/pipe.js b/src/helpers/pipe.js index 81384b2..9d5d78b 100644 --- a/src/helpers/pipe.js +++ b/src/helpers/pipe.js @@ -327,19 +327,27 @@ const getWatchSources = async (provider, anilistId, category, slug) => { // ---- FEATURE: Extract subtitle URLs from streaming sources ---- /** * Extracts and formats subtitle URLs from the pipe sources response. - * Subtitles are usually in WebVTT format with language tags. + * Handles multiple subtitle formats from different providers. + * + * Provider formats: + * bonk: { file, label, kind, default, language, format, encoding } + * others: { url, name, lang, format } * * @param {object} sources - The sources response from getSources/getWatchSources - * @returns {Array} Array of subtitle objects { url, label, language, format } + * @returns {Array} Array of subtitle objects { url, label, language, kind, format, isDefault } */ const extractSubtitles = (sources) => { - const subtitles = sources.subtitles || sources.captions || []; - return subtitles.map((sub) => ({ - url: sub.url || sub.file, - label: sub.label || sub.name || "Unknown", - language: sub.lang || sub.language || sub.label || "en", + const raw = sources.subtitles || sources.captions || []; + + return raw.map((sub) => ({ + url: sub.file || sub.url || null, + label: sub.label || sub.name || sub.language || "Unknown", + language: sub.language || sub.lang || sub.label || "en", + kind: sub.kind || "subtitles", format: sub.format || "vtt", - })); + encoding: sub.encoding || "utf-8", + isDefault: sub.default || false, + })).filter((sub) => sub.url); }; // ══════════════════════════════════════════════════════════════ @@ -349,7 +357,8 @@ const extractSubtitles = (sources) => { // ---- FEATURE: Get best available stream with quality fallback ---- /** * Returns the best available HLS stream with automatic quality fallback. - * Tries 1080p → 720p → 360p in order. + * Tries 1080p → 720p → 480p → 360p in order. + * Falls back to first HLS stream if no quality match. * * @param {object} sources - The sources response * @param {string} [preferredQuality="1080p"] - Preferred quality @@ -371,7 +380,10 @@ const getBestStream = (sources, preferredQuality = "1080p") => { if (match) return match; } - // NOTE: Return first available if no quality match + // NOTE: Some providers don't include quality — return first active HLS stream, or first HLS stream + const active = streams.find((s) => s.isActive); + if (active) return active; + return streams[0]; }; @@ -382,23 +394,29 @@ const getBestStream = (sources, preferredQuality = "1080p") => { // ---- FEATURE: Get download URL for an episode ---- /** * Fetches the download URL for a specific episode from the pipe. - * Returns the direct download link if available. + * Returns the direct download link, subtitles, and best stream if available. * * @param {string} provider - Provider name * @param {number} anilistId - The AniList anime ID * @param {string} category - Audio category ("sub" or "dub") * @param {string} slug - Episode slug (e.g., "animepahe-1") - * @returns {Promise} Object with download URL and metadata + * @returns {Promise} Object with download URL, subtitles, best stream, and metadata */ const getDownloadUrl = async (provider, anilistId, category, slug) => { const sources = await getWatchSources(provider, anilistId, category, slug); + const subtitles = extractSubtitles(sources); + const bestStream = getBestStream(sources); + return { download: sources.download || null, + subtitles, + bestStream, provider, anilistId, category, slug, hasDownload: !!sources.download, + hasSubtitles: subtitles.length > 0, }; }; diff --git a/test.js b/test.js index a3824e3..cae57d5 100644 --- a/test.js +++ b/test.js @@ -4,7 +4,7 @@ * Repository: https://github.com/Shineii86/MiruroAPI * * @description - * Integration test suite for MiruroAPI v2.0.0 endpoints. + * Integration test suite for MiruroAPI v2.0.1 endpoints. * Tests all 35 endpoints for correct response format. * * @author Shinei Nouzen @@ -103,7 +103,7 @@ async function runTest(test) { } async function runAll() { - console.log(`\n🧪 MiruroAPI v2.0.0 — Running ${tests.length} tests...\n`); + console.log(`\n🧪 MiruroAPI v2.0.1 — Running ${tests.length} tests...\n`); for (const test of tests) { await runTest(test);