HomeBlogTranscribePlansAPI Keys

Go での YouTube 文字起こし: net/http と 3 つの構造体

YouTube トランスクリプト API レスポンスを構造体にデコードするGo プログラム

ここにプログラム全体があります。説明の後に。

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、完了。サードパーティのモジュールなし。これはGolangでYouTube文字起こしを取得するべき方法です―APIはJSONを返す素のHTTPSであるため、net/httpencoding/jsonがすべてをカバーしています。これのための公式Goライブラリはありません。これは機能であると主張します。

エンベロープトリック

成功レスポンスはresultの下にデータを置きます。失敗は構造化オブジェクトをerrorの下に置きます。2つのポインタフィールドで1つの構造体の両方をデコードすることは、単一のDecode呼び出しがすべてのレスポンスを処理することを意味します―どのポインタが非nilであるかが答えです。本体の再読み込みがなく、Content-Typeのスニッフィングがなく、env.Error.Statusはダブルチェックしたい場合はHTTPステータスと一致します。

スイッチステートメント価値のあるコード

APIError.Codeは安定しているため、メッセージ文字列ではなくそれに分岐します:

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は人々が誤解する1つです。文字起こしはYouTubeの字幕トラックから来ます―手動または自動生成、英語優先、それ以外の言語は最初に利用可能です。ビデオに字幕をオフにしている場合、取得する文字起こしはなく、指数バックオフで再試行することは字幕を成長させません。バッチジョブで永続的なスキップとして扱います。そうしないと、ワーカーキューがゾンビで満たされます。

パラメータとキー

合計2つのクエリパラメータ。urlは任意のYouTube URLの形または裸の11文字IDを取ります。maxCharsはキャップ出力長(150000はデフォルトと最大)―トランスクリプトがLLMにフィードされトークンあたりを支払う場合に便利で、これは私が聞く大多数のGoユースケース、通常チャネル全体でRAGです。

サインアップなしでキーを取得するには、curl https://youtube2text.org/api/demo-keyは機能する1つを返します―すべての匿名ユーザー間で共有、月5ビデオあたりIP。実験のみです。これをyt-dlpに対して字幕ファイルをシェルアウトすることと比較することを検討している場合、yt-dlp字幕とAPIの比較を書きました。スタックの一部がNodeである場合、JavaScriptでの同じ呼び出しはさらに短いです。

実際の使用では、youtube2text.org/app/keysでGoogleサインインしてください―カードなし、電話なし、月5ビデオの無料ティア、50から$5.99から$19.99無制限までの有料ティア。上のGoコードは変わりません。環境変数だけが変わります。