Saltar a contenido

Obtener Subtítulo

Recupera información detallada sobre un subtítulo específico por su ID.

Endpoint

GET /api/subtitles/{subtitle_id}

Autenticación

Autenticación requerida - Incluye tu clave de API en el header Authorization.

Descripción

Este endpoint recupera información completa sobre un único subtítulo usando su UUID único. Úsalo cuando ya tengas un ID de subtítulo de un resultado de búsqueda y quieras obtener sus detalles completos.

Parámetros de Path

Parámetro Tipo Requerido Descripción
subtitle_id string (UUID) Identificador único del subtítulo

Ejemplos de Solicitud

=== "cURL"

curl -X GET "https://subx-api.duckdns.org/api/subtitles/550e8400-e29b-41d4-a716-446655440000" \
  -H "Authorization: Bearer {TU_CLAVE_API}"
import requests

subtitle_id = "550e8400-e29b-41d4-a716-446655440000"
headers = {"Authorization": "Bearer {TU_CLAVE_API}"}

response = requests.get(
    f"https://subx-api.duckdns.org/api/subtitles/{subtitle_id}",
    headers=headers
)

subtitle = response.json()
print(f"Title: {subtitle['title']}")
print(f"Downloads: {subtitle['downloads']}")
package main

import (
    "encoding/json"
    "fmt"
    "net/http"
)

func main() {
    apiKey := "{TU_CLAVE_API}"
    subtitleID := "550e8400-e29b-41d4-a716-446655440000"
    url := fmt.Sprintf("https://subx-api.duckdns.org/api/subtitles/%s", subtitleID)

    req, _ := http.NewRequest("GET", url, nil)
    req.Header.Set("Authorization", "Bearer "+apiKey)

    client := &http.Client{}
    resp, _ := client.Do(req)
    defer resp.Body.Close()

    var subtitle map[string]interface{}
    json.NewDecoder(resp.Body).Decode(&subtitle)

    fmt.Printf("Title: %v\n", subtitle["title"])
    fmt.Printf("Downloads: %v\n", subtitle["downloads"])
}
using System;
using System.Net.Http;
using System.Net.Http.Headers;
using System.Text.Json;
using System.Threading.Tasks;

var subtitleId = "550e8400-e29b-41d4-a716-446655440000";
var client = new HttpClient();

client.DefaultRequestHeaders.Authorization =
    new AuthenticationHeaderValue("Bearer", "{TU_CLAVE_API}");

var url = $"https://subx-api.duckdns.org/api/subtitles/{subtitleId}";
var response = await client.GetAsync(url);
var json = await response.Content.ReadAsStringAsync();

var subtitle = JsonSerializer.Deserialize<JsonElement>(json);
Console.WriteLine($"Title: {subtitle.GetProperty("title")}");
Console.WriteLine($"Downloads: {subtitle.GetProperty("downloads")}");
const subtitleId = '550e8400-e29b-41d4-a716-446655440000';

const response = await fetch(
  `https://subx-api.duckdns.org/api/subtitles/${subtitleId}`,
  {
    headers: {
      'Authorization': 'Bearer {TU_CLAVE_API}'
    }
  }
);

const subtitle = await response.json();
console.log(`Title: ${subtitle.title}`);
console.log(`Downloads: ${subtitle.downloads}`);

Respuesta

Respuesta Exitosa (200 OK)

{
  "id": "550e8400-e29b-41d4-a716-446655440000",
  "video_type": "episode",
  "title": "Dexter",
  "season": 1,
  "episode": 1,
  "year": 2006,
  "imdb_id": "tt0773262",
  "description": "Dexter S01E01 - Dexter\nRelease: HDTV.XviD-LOL\nBlu-ray rip version also available",
  "uploader_name": "user123",
  "posted_at": "2024-01-15T10:30:00Z",
  "downloads": 1250
}

Campos de Respuesta

Campo Tipo Descripción
id string (UUID) Identificador único del subtítulo
video_type string Tipo: movie o episode
title string Título de la película/serie
season integer | null Número de temporada (para episodios)
episode integer | null Número de episodio (para episodios)
year integer | null Año de estreno de película o de la serie principal
imdb_id string | null Identificador de IMDb (ej., tt0773262)
description string | null Descripción del subtítulo/info de release
uploader_name string | null Nombre de usuario del subidor original
posted_at string Timestamp ISO 8601
downloads integer Contador total de descargas (fuente + API)

Códigos de Estado

Código Descripción
200 Éxito - Subtítulo encontrado
401 No Autorizado - Clave de API inválida o faltante
404 No Encontrado - El subtítulo no existe o está inactivo
429 Demasiadas Solicitudes - Límite de tasa excedido
500 Error Interno del Servidor

Respuestas de Error

404 No Encontrado

{
  "detail": "Subtitle not found"
}

Este error ocurre cuando: - El ID del subtítulo no existe en la base de datos - El subtítulo existe pero ha sido desactivado (is_active=false) - El formato del ID es inválido (no es un UUID válido)

401 No Autorizado

{
  "detail": "Invalid authentication credentials"
}

Casos de Uso

1. Obtener Detalles del Subtítulo Después de Búsqueda

import requests

def search_and_get_details(title):
    """Search for subtitles and get details of first result."""
    headers = {"Authorization": "Bearer {TU_CLAVE_API}"}

    # Search
    search_response = requests.get(
        "https://subx-api.duckdns.org/api/subtitles/search",
        headers=headers,
        params={"title": title, "limit": 1}
    )

    results = search_response.json()
    if not results['items']:
        print(f"No subtitles found for '{title}'")
        return None

    # Get detailed info
    subtitle_id = results['items'][0]['id']
    detail_response = requests.get(
        f"https://subx-api.duckdns.org/api/subtitles/{subtitle_id}",
        headers=headers
    )

    return detail_response.json()

# Usage
subtitle = search_and_get_details("Breaking Bad")
if subtitle:
    print(f"Title: {subtitle['title']}")
    print(f"Description: {subtitle['description']}")

2. Validar que el Subtítulo Existe Antes de Descargar

import requests

def download_if_exists(subtitle_id):
    """Check if subtitle exists before attempting download."""
    headers = {"Authorization": "Bearer {TU_CLAVE_API}"}

    # First, verify subtitle exists
    try:
        response = requests.get(
            f"https://subx-api.duckdns.org/api/subtitles/{subtitle_id}",
            headers=headers
        )
        response.raise_for_status()
    except requests.exceptions.HTTPError as e:
        if e.response.status_code == 404:
            print("Subtitle not found")
            return False
        raise

    # Subtitle exists, proceed with download
    download_response = requests.get(
        f"https://subx-api.duckdns.org/api/subtitles/{subtitle_id}/download",
        headers=headers
    )

    with open("subtitle.srt", "wb") as f:
        f.write(download_response.content)

    return True

3. Recuperación por Lotes de Múltiples Subtítulos

import requests
from concurrent.futures import ThreadPoolExecutor

def get_subtitle_details(subtitle_id, headers):
    """Get details for a single subtitle."""
    response = requests.get(
        f"https://subx-api.duckdns.org/api/subtitles/{subtitle_id}",
        headers=headers
    )
    if response.status_code == 200:
        return response.json()
    return None

def get_multiple_subtitles(subtitle_ids):
    """Fetch details for multiple subtitles concurrently."""
    headers = {"Authorization": "Bearer {TU_CLAVE_API}"}

    with ThreadPoolExecutor(max_workers=5) as executor:
        futures = [
            executor.submit(get_subtitle_details, sub_id, headers)
            for sub_id in subtitle_ids
        ]

        results = [f.result() for f in futures]

    # Filter out None values (failed requests)
    return [r for r in results if r is not None]

# Usage
ids = [
    "550e8400-e29b-41d4-a716-446655440000",
    "660e9500-f39c-52e5-b827-557766551111",
    "770fa611-g40d-63f6-c938-668877662222"
]

subtitles = get_multiple_subtitles(ids)
print(f"Retrieved {len(subtitles)} subtitles")

4. Mostrar Información del Subtítulo

import requests
from datetime import datetime

def display_subtitle_info(subtitle_id):
    """Fetch and display formatted subtitle information."""
    headers = {"Authorization": "Bearer {TU_CLAVE_API}"}

    response = requests.get(
        f"https://subx-api.duckdns.org/api/subtitles/{subtitle_id}",
        headers=headers
    )

    if response.status_code != 200:
        print(f"Error: {response.status_code}")
        return

    sub = response.json()

    print("=" * 60)
    print(f"Title: {sub['title']}")

    if sub['video_type'] == 'episode':
        print(f"Type: TV Episode (S{sub['season']:02d}E{sub['episode']:02d})")
    else:
        print(f"Type: Movie")

    if sub.get('imdb_id'):
        print(f"IMDb: https://www.imdb.com/title/{sub['imdb_id']}/")

    print(f"Uploader: {sub.get('uploader_name', 'Unknown')}")
    print(f"Downloads: {sub['downloads']}")

    posted = datetime.fromisoformat(sub['posted_at'].replace('Z', '+00:00'))
    print(f"Posted: {posted.strftime('%Y-%m-%d %H:%M UTC')}")

    if sub.get('description'):
        print(f"\nDescription:\n{sub['description']}")

    print("=" * 60)

# Usage
display_subtitle_info("550e8400-e29b-41d4-a716-446655440000")

Notas

  • Este endpoint devuelve un único objeto de subtítulo (no envuelto en array items como búsqueda)
  • Los subtítulos inactivos (is_active=false) devuelven errores 404
  • El campo downloads combina tanto descargas de la fuente como descargas de la API
  • El campo id en la respuesta es el UUID (igual que el parámetro subtitle_id)
  • Para episodios, prefiere usar el ID de IMDb de la respuesta (puede ser específico del episodio)

Relación con Otros Endpoints

graph LR
    A[Search] --> B[Get Subtitle]
    B --> C[Download]
    A --> C
  1. Search → Get Subtitle: Usa búsqueda para encontrar IDs, luego obtiene detalles
  2. Get Subtitle → Download: Verifica que el subtítulo existe antes de descargar
  3. Search → Download: Puede omitir "Get Subtitle" si la búsqueda proporciona suficiente información

Próximos Pasos