YouTube Transkription i Ruby: Net::HTTP och noll juveler

Ruby-reflexen är bundle add något innan du skriver en kodrad. Motstå den i fem minuter: att hämta en YouTube-transkription i Ruby behöver ingenting utanför standardbiblioteket, för API:t är ett HTTPS GET som returnerar JSON, och net/http plus json har suttit i varje Ruby-installation sedan evigt. I slutet av det här inlägget har du ett skript som tar valfri YouTube URL och skriver ut videotiteln och transkriptionen, med ett case-uttalande som täcker varje fel API:t returnerar — och en tom Gemfile.
Ja, Net::HTTP:s gränssnitt är så skrynkligt som sitt rykte. Det är fortfarande bara tjugo rader.
Skriptet
require "net/http"
require "json"
require "uri"
uri = URI("https://youtube2text.org/api/transcribe")
uri.query = URI.encode_www_form(
url: "https://www.youtube.com/watch?v=dQw4w9WgXcQ"
)
req = Net::HTTP::Get.new(uri)
req["x-api-key"] = ENV.fetch("YT2TEXT_KEY")
res = Net::HTTP.start(uri.hostname, uri.port,
use_ssl: true, read_timeout: 60) do |http|
http.request(req)
end
data = JSON.parse(res.body)
if res.is_a?(Net::HTTPSuccess)
transcript = data["result"]
puts transcript["title"]
puts "#{transcript['contentSize']} chars, truncated: #{transcript['truncated']}"
puts transcript["content"][0, 400]
else
err = data["error"]
case err["code"]
when "RATE_LIMIT_EXCEEDED"
puts "Rate limited. Retry in #{err['retryAfterSeconds']}s."
when "TRANSCRIPT_UNAVAILABLE"
puts "No captions on this video. Skip it."
when "VIDEO_NOT_FOUND", "INVALID_URL"
puts "Bad video reference: #{err['message']}"
else
abort "#{err['code']}: #{err['message']}"
end
end
Parametern url är förlåtande — fullständiga watch-URL:er, youtu.be korta länkar, shorts, eller ett enkelt 11-tecken video-id alla fungerar. Lägg till maxChars: 20000 till encode_www_form om transkriptionen är på väg in i en LLM-prompt och du snarare inte vill betala för en tre-timmars poddcasts värd tokens; 150000 är standard och maximum.
Om din kodbase redan har Faraday eller httparty, bra, använd dem — begäran är samma tre ingredienser: slutpunkten, en frågesträng och en header. Talat om vilket, req["Authorization"] = "Bearer #{key}" fungerar identiskt till x-api-key om bärtokens passar din inställning bättre.
En nyckel i ett kommando
curl https://youtube2text.org/api/demo-key
Det returnerar {"success":true,"apiKey":"yt_..."} utan konto, utan e-post, ingenting. Fångsten: det är en delad nyckel för alla anonyma användare, begränsad till 5 videor per månad per IP. Bra för att verifiera skriptet fungerar, fel för allt du skulle distribuera.
Vad transkriptionen faktiskt är
Värt att vara klarsynt här: texten kommer från Youtubes bildtextsspår. Manuellt uppladdade bildtexter läser vackert; automatiskt genererade månglar ibland jargong och produktnamn, och det finns ingenting något API kan göra om det strömuppströms. Engelska spår föredraget, med återgång till det första tillgängliga språket. Och en video med inaktiverad bildtexter returnerar TRANSCRIPT_UNAVAILABLE — case-grenen ovan behandlar det som ett hopp, inte ett försök igen, för att försöka igen en video som har inga bildtexter är ett mycket tålmodig sätt att åstadkomma ingenting.
Vart Rubyists tar det här
Mönstret jag ser mest är batch-bearbetning: slinga över en kanals video-id:n, hämta varje transkription, mata dem till något nedströms. Studenter förvandlar föreläsningsvideos till studieanteckningar; om nedströms är Claude, fria transkriptioner i Claude genomgång förbinder de två utan anpassad lim. Samma slutpunkt från PHP är nästan rad-för-rad identisk — jämförelse här om ditt team kör båda.
När den delade demo-nyckeln torkade, logga in med Google på youtube2text.org/app/keys — ingen telefon, inget kort. Du får din egen gratis nyckel på 5 videor per månad, med betalda nivåer från $5,99 för 50 upp till $19,99 unlimited. Skriptet förändras inte; ENV["YT2TEXT_KEY"] gör.