HomeBlogTranscribePlansAPI Keys

YouTube Transkription i C# med HttpClient och Records

C# konsolapp som deserialiserargre en YouTube-transkription med System.Text.Json

Från dotnet run till en utskriven transkription tog ungefär två sekunder på min maskin, och det mesta av det var nätverksrundan. Inget NuGet-paket dyker upp någonstans i det här inlägget — att få en YouTube-transkription i C# är en GET-begäran, och HttpClient plus System.Text.Json har levererats i lådan i flera år. I slutet har du en komplett konsolapp med posttyper för svaret, en asynk Main och felhantering som läser API:s strukturerade felobjekt i stället för att gissa från statuskoder.

Tre records

API:t returnerar {"result": {...}} vid framgång och {"error": {...}} vid misslyckande, så modellera kuvertet direkt:

public record Transcript(
    string VideoId,
    string Title,
    string PubDate,
    string Content,
    int ContentSize,
    bool Truncated);

public record ApiError(
    string Code,
    string Message,
    int Status,
    int? RetryAfterSeconds);

public record Envelope(Transcript? Result, ApiError? Error);

Ett Deserialize<Envelope>-anrop hanterar varje svar. Vilken egenskap som helst som inte är null är ditt svar. RetryAfterSeconds är nullable eftersom bara hastighetsbegränsningsfel bär den.

Programmet

Riktar .NET 8, fungerar som på 6 och 7:

using System;
using System.Net.Http;
using System.Text.Json;
using System.Threading.Tasks;

public static class Program
{
    private static readonly HttpClient Http = new();
    private static readonly JsonSerializerOptions Json =
        new(JsonSerializerDefaults.Web);

    public static async Task Main(string[] args)
    {
        var videoUrl = args.Length > 0
            ? args[0]
            : "https://www.youtube.com/watch?v=dQw4w9WgXcQ";

        var request = new HttpRequestMessage(HttpMethod.Get,
            "https://youtube2text.org/api/transcribe" +
            $"?url={Uri.EscapeDataString(videoUrl)}&maxChars=40000");
        request.Headers.Add("x-api-key",
            Environment.GetEnvironmentVariable("YT2TEXT_KEY"));

        var response = await Http.SendAsync(request);
        var envelope = JsonSerializer.Deserialize<Envelope>(
            await response.Content.ReadAsStringAsync(), Json);

        if (envelope?.Error is { } err)
        {
            Console.Error.WriteLine($"{err.Code}: {err.Message}");
            if (err.RetryAfterSeconds is int wait)
                Console.Error.WriteLine($"Retry after {wait}s");
            Environment.Exit(1);
        }

        var t = envelope!.Result!;
        Console.WriteLine($"{t.Title} ({t.ContentSize} chars, truncated: {t.Truncated})");
        Console.WriteLine(t.Content[..Math.Min(t.Content.Length, 400)]);
    }
}

JsonSerializerDefaults.Web mappar API:s camelCase-fält till PascalCase-posters, så det finns ingen enda [JsonPropertyName]-attribut. Parametern url accepterar alla YouTube URL-varianter plus nackna 11-tecken-id:n, och headern kan vara Authorization: Bearer yt_... i stället för x-api-key om det passar din middleware bättre.

Om det maxChars=40000

maxChars begränsar transkriptionslängden; 150000 är både standard och hårt tak. Om en videos bildtexter går förbi din gräns, Truncated kommer tillbaka true och du får de första N-tecknen — så kontrollera flaggan innan du antar att du har den fullständiga texten. Jag satte 40000 i exemplet för att dessa transkriptioner slutligen hamnar i en LLM-prompt, och med ungefär fyra tecken per token är det en 10k-token-budget. Om dina modellanrop går genom OpenAI Responses API finns det ett sätt att hoppa över HTTP-ledningen helt och hållet via MCP-servern med OpenAI; Anthropic-motsvarigheten finns i användning av transkriptioner med Claude API.

Felkoder att grena på

ApiError.Code är en stabil sträng: UNAUTHORIZED (401), VALIDATION_ERROR och INVALID_URL (400), VIDEO_NOT_FOUND och TRANSCRIPT_UNAVAILABLE (404), RATE_LIMIT_EXCEEDED (429), YOUTUBE_ERROR (500). Den som överraskar folk är TRANSCRIPT_UNAVAILABLE: transkriptioner kommer från Youtubes bildtextsspår, och en video vars ägare inaktiverade bildtexter har ingenting att returnera — ingen omprövning av retry-policy fixar det. Mönstermatchning på koden, behandla den som ett permanent hopp.

För en nollsignerings-testknapp, GET https://youtube2text.org/api/demo-key — den delas och begränsas till 5 videor per månad per IP, så det är för experiment bara. Om Go också är i din stack använder samma anrop i Golang det identiska kuverttricket.

Den kompletta maskinläsbara referensen — varje parameter, varje fel, redo att klistra in i en systemprompt — finns på youtube2text.org/api.md.