Support swappable transcription methods
Set TRANSCRIBER=whisperx (default) or TRANSCRIBER=sous_chef to pick
the engine. Transcripts go to transcripts/<method>/ so results from
different engines coexist for comparison.
Assisted-by: Claude Opus 4.6 via pi
diff --git a/Rakefile b/Rakefile
index f05de8e..071cefe 100644
--- a/Rakefile
+++ b/Rakefile
@@ -7,12 +7,13 @@ require_relative "lib/download"
CACHE_DIR = Pathname("cache")
AUDIO_DIR = CACHE_DIR / "audio"
TRANSCRIPTS_DIR = Pathname("transcripts")
+SOUS_CHEF = Pathname("sous_chef/.build/release/sous_chef")
HRN_FEED = CACHE_DIR / "hrn_feed.xml"
HRN_FEED_URL = "https://rss.art19.com/cooking-issues"
+TRANSCRIBER = ENV.fetch("TRANSCRIBER", "whisperx")
directory CACHE_DIR.to_s
directory AUDIO_DIR.to_s
-directory TRANSCRIPTS_DIR.to_s
file HRN_FEED.to_s => CACHE_DIR.to_s do
puts "Downloading HRN feed..."
@@ -23,25 +24,44 @@ file HRN_FEED.to_s => CACHE_DIR.to_s do
HRN_FEED.write(response.body)
end
+file SOUS_CHEF.to_s do
+ sh "cd sous_chef && swift build -c release"
+end
+
Rake::Task[HRN_FEED.to_s].invoke
EPISODES = CookingIssues::Feed.parse(HRN_FEED)
-EPISODES.values.each do |ep|
- file ep.audio_path => AUDIO_DIR.to_s do
- puts "Downloading #{ep.slug}..."
- CookingIssues::Download.fetch(ep.audio_url, ep.audio_path)
- end
-
- file ep.transcript_path => [ep.audio_path, TRANSCRIPTS_DIR.to_s] do
+def transcribe(ep, audio_path, transcript_path)
+ case TRANSCRIBER
+ when "whisperx"
hf_token = ENV.fetch("HUGGING_FACE_TOKEN") { abort "Set HUGGING_FACE_TOKEN for diarization." }
- sh "whisperx", ep.audio_path,
+ sh "whisperx", audio_path,
"--model", "large-v3",
"--compute_type", "int8",
"--device", "cpu",
"--diarize", "--hf_token", hf_token,
- "--output_dir", TRANSCRIPTS_DIR.to_s,
+ "--output_dir", File.dirname(transcript_path),
"--output_format", "txt"
+ when "sous_chef"
+ Rake::Task[SOUS_CHEF.to_s].invoke
+ sh SOUS_CHEF.to_s, audio_path, transcript_path
+ else
+ abort "Unknown transcriber: #{TRANSCRIBER}. Use 'whisperx' or 'sous_chef'."
+ end
+end
+
+EPISODES.values.each do |ep|
+ transcript_dir = (TRANSCRIPTS_DIR / TRANSCRIBER).to_s
+ directory transcript_dir
+
+ file ep.audio_path => AUDIO_DIR.to_s do
+ puts "Downloading #{ep.slug}..."
+ CookingIssues::Download.fetch(ep.audio_url, ep.audio_path)
+ end
+
+ file ep.transcript_path(TRANSCRIBER) => [ep.audio_path, transcript_dir] do
+ transcribe(ep, ep.audio_path, ep.transcript_path(TRANSCRIBER))
end
end
@@ -53,14 +73,14 @@ desc "Download and transcribe all episodes"
task :sync do
# The feed is reverse-chronological; process oldest episodes first.
EPISODES.values.sort_by(&:number).each do |ep|
- Rake::Task[ep.transcript_path].invoke
+ Rake::Task[ep.transcript_path(TRANSCRIBER)].invoke
end
end
desc "List all episodes from the feed"
task :episodes do
EPISODES.values.sort_by(&:number).each do |ep|
- status = Pathname(ep.transcript_path).exist? ? "✓" : " "
+ status = Pathname(ep.transcript_path(TRANSCRIBER)).exist? ? "✓" : " "
puts "[#{status}] #{ep.slug} #{ep.title}"
end
end
@@ -72,7 +92,7 @@ task :transcribe, [:number] do |_t, args|
ep = EPISODES[args[:number].to_i]
abort "Episode #{args[:number]} not found in feed." unless ep
- Rake::Task[ep.transcript_path].invoke
+ Rake::Task[ep.transcript_path(TRANSCRIBER)].invoke
end
desc "Re-transcribe an episode (e.g., rake retranscribe[42])"
@@ -82,7 +102,8 @@ task :retranscribe, [:number] do |_t, args|
ep = EPISODES[args[:number].to_i]
abort "Episode #{args[:number]} not found in feed." unless ep
- Pathname(ep.transcript_path).delete if Pathname(ep.transcript_path).exist?
- Rake::Task[ep.transcript_path].reenable
- Rake::Task[ep.transcript_path].invoke
+ path = Pathname(ep.transcript_path(TRANSCRIBER))
+ path.delete if path.exist?
+ Rake::Task[ep.transcript_path(TRANSCRIBER)].reenable
+ Rake::Task[ep.transcript_path(TRANSCRIBER)].invoke
end
diff --git a/lib/feed.rb b/lib/feed.rb
index 1465eb7..0c05623 100644
--- a/lib/feed.rb
+++ b/lib/feed.rb
@@ -20,8 +20,8 @@ module CookingIssues
"cache/audio/#{slug}.mp3"
end
- def transcript_path
- audio_path.pathmap("%{^cache/audio/,transcripts/}X.txt")
+ def transcript_path(method)
+ audio_path.pathmap("%{^cache/audio/,transcripts/#{method}/}X.txt")
end
end