HomeBlogTranscribePlansAPI Keys

Transcripción de YouTube en Golang: net/http y Tres Estructuras

Programa Go decodificando una respuesta API de transcripción de YouTube en estructuras

Aquí está el programa completo. La explicación a continuación.

package main

import (
	"encoding/json"
	"fmt"
	"net/http"
	"net/url"
	"os"
	"time"
)

type Transcript struct {
	VideoID     string `json:"videoId"`
	Title       string `json:"title"`
	PubDate     string `json:"pubDate"`
	Content     string `json:"content"`
	ContentSize int    `json:"contentSize"`
	Truncated   bool   `json:"truncated"`
}

type APIError struct {
	Code              string `json:"code"`
	Message           string `json:"message"`
	Status            int    `json:"status"`
	RetryAfterSeconds int    `json:"retryAfterSeconds"`
}

type envelope struct {
	Result *Transcript `json:"result"`
	Error  *APIError   `json:"error"`
}

func main() {
	q := url.Values{}
	q.Set("url", "https://www.youtube.com/watch?v=dQw4w9WgXcQ")

	req, err := http.NewRequest(http.MethodGet,
		"https://youtube2text.org/api/transcribe?"+q.Encode(), nil)
	if err != nil {
		fmt.Fprintln(os.Stderr, err)
		os.Exit(1)
	}
	req.Header.Set("x-api-key", os.Getenv("YT2TEXT_KEY"))

	client := &http.Client{Timeout: 60 * time.Second}
	resp, err := client.Do(req)
	if err != nil {
		fmt.Fprintln(os.Stderr, err)
		os.Exit(1)
	}
	defer resp.Body.Close()

	var env envelope
	if err := json.NewDecoder(resp.Body).Decode(&env); err != nil {
		fmt.Fprintln(os.Stderr, "decode:", err)
		os.Exit(1)
	}

	if env.Error != nil {
		fmt.Fprintf(os.Stderr, "%s: %s\n", env.Error.Code, env.Error.Message)
		os.Exit(1)
	}

	fmt.Println(env.Result.Title)
	fmt.Printf("%d chars, truncated=%v\n",
		env.Result.ContentSize, env.Result.Truncated)
}

go run main.go, listo. Sin módulos de terceros, que es cómo obtener una transcripción de YouTube en Golang debería verse — la API es HTTPS simple devolviendo JSON, así que net/http y encoding/json cubren todo. No hay biblioteca oficial de Go para esto, y yo diría que eso es una característica.

El truco del sobre

Las respuestas exitosas ponen datos bajo result; las fallas ponen un objeto estructurado bajo error. Decodificar ambos en una estructura con dos campos de puntero significa una única llamada a Decode maneja cada respuesta — el puntero no nulo es tu respuesta. Sin releer el cuerpo, sin inspeccionar Content-Type, y env.Error.Status coincide con el estado HTTP si quieres verificar dos veces.

Códigos que merecen una declaración switch

APIError.Code es estable, así que ramifica en lugar de cadenas de mensajes:

switch env.Error.Code {
case "RATE_LIMIT_EXCEEDED":
	wait := time.Duration(env.Error.RetryAfterSeconds) * time.Second
	time.Sleep(wait) // then retry the request
case "TRANSCRIPT_UNAVAILABLE":
	// video exists but has no caption track — skip permanently
case "VIDEO_NOT_FOUND", "INVALID_URL":
	// bad input; log and move on
default:
	// UNAUTHORIZED, VALIDATION_ERROR, YOUTUBE_ERROR
}

TRANSCRIPT_UNAVAILABLE es el que la gente maneja mal. Las transcripciones provienen de las pistas de subtítulos de YouTube — manuales o generadas automáticamente, inglés preferido, primer idioma disponible de otra manera. Si un video tiene los subtítulos desactivados, no hay transcripción para obtener, y reintentar con retroceso exponencial no hará que aparezcan subtítulos. Trátalo como un salto permanente en trabajos por lotes, o tu cola de trabajadores se llenará de zombis.

Parámetros y claves

Dos parámetros de consulta en total. url acepta cualquier forma de URL de YouTube o un id de 11 caracteres desnudo. maxChars limita la longitud de salida (150000 es el predeterminado y máximo) — útil cuando la transcripción alimenta un LLM y estás pagando por token, que es la mayoría de casos de uso de Go que escucho, generalmente RAG sobre un canal completo.

Para una clave sin ningún registro, curl https://youtube2text.org/api/demo-key devuelve una funcional — compartida entre todos los usuarios anónimos a 5 videos por mes por IP, así que es estrictamente para probar cosas. Si estás comparando esto con pagar a yt-dlp por archivos de subtítulos, escribí una comparación de yt-dlp subtítulos versus la API; y si parte de tu stack es Node, la misma llamada en JavaScript es aún más corta.

Para uso real, inicia sesión con Google en youtube2text.org/app/keys — sin tarjeta, sin teléfono, nivel gratuito de 5 videos al mes, niveles pagados desde $5.99 por 50 hasta $19.99 ilimitado. El código de Go anterior no cambia; solo la variable de entorno cambia.