Move JSON to cache, add site generation, reorganize rake files
Intermediate transcription files now live in cache/<transcriber>/
instead of alongside the rendered text. Rake files moved to
lib/tasks/. Site task generates a static HTML transcript viewer.
Assisted-by: Claude Opus 4.6 via pi
diff --git a/.gitignore b/.gitignore
index f56f3a3..b319076 100644
--- a/.gitignore
+++ b/.gitignore
@@ -1,2 +1,3 @@
/cache/
/sous_chef/.build/
+/site
diff --git a/Rakefile b/Rakefile
index fca577e..a4c4675 100644
--- a/Rakefile
+++ b/Rakefile
@@ -24,9 +24,9 @@ file HRN_FEED.to_s => CACHE_DIR.to_s do
HRN_FEED.write(response.body)
end
-load File.expand_path("transcribers.rake", __dir__)
+load File.expand_path("lib/tasks/transcribers.rake", __dir__)
-TRANSCRIBER = Transcribers.resolve(ENV.fetch("TRANSCRIBER", "whisper-cpp-large"))
+TRANSCRIBER = Transcribers.resolve(ENV.fetch("TRANSCRIBER", "sous_chef"))
TRANSCRIBER.register
Rake::Task[HRN_FEED.to_s].invoke
@@ -37,18 +37,23 @@ def audio_path(ep)
(AUDIO_DIR / "#{ep.slug}.mp3").to_s
end
+TRANSCRIBER_CACHE_DIR = CACHE_DIR / TRANSCRIBER.name
+
+directory TRANSCRIBER_CACHE_DIR.to_s
+
def transcript_path(ep)
- (TRANSCRIPTS_DIR / TRANSCRIBER.name / "#{ep.slug}.json").to_s
+ (TRANSCRIBER_CACHE_DIR / "#{ep.slug}.json").to_s
end
def text_path(ep)
(TRANSCRIPTS_DIR / TRANSCRIBER.name / "#{ep.slug}.txt").to_s
end
-EPISODES.values.each do |ep|
- transcript_dir = (TRANSCRIPTS_DIR / TRANSCRIBER.name).to_s
- directory transcript_dir
+TEXT_DIR = TRANSCRIPTS_DIR / TRANSCRIBER.name
+directory TEXT_DIR.to_s
+
+EPISODES.values.each do |ep|
audio = audio_path(ep)
transcript = transcript_path(ep)
@@ -57,13 +62,13 @@ EPISODES.values.each do |ep|
CookingIssues::Download.fetch(ep.audio_url, audio)
end
- file transcript => [audio, transcript_dir, *TRANSCRIBER.prereqs] do
+ file transcript => [audio, TRANSCRIBER_CACHE_DIR.to_s, *TRANSCRIBER.prereqs] do
TRANSCRIBER.call(audio, transcript)
end
txt = text_path(ep)
- file txt => transcript do
+ file txt => [transcript, TEXT_DIR.to_s] do
TRANSCRIBER.render(transcript, txt)
end
end
@@ -96,6 +101,21 @@ task :transcribe, [:number] do |_t, args|
Rake::Task[text_path(ep)].invoke
end
+desc "Move intermediate files from transcripts/ to cache/"
+task :migrate_cache do
+ EPISODES.values.each do |ep|
+ old_path = TRANSCRIPTS_DIR / TRANSCRIBER.name / "#{ep.slug}.json"
+ new_path = Pathname(transcript_path(ep))
+ next unless old_path.exist?
+
+ new_path.dirname.mkpath
+ FileUtils.mv(old_path.to_s, new_path.to_s)
+ puts "Moved #{old_path} → #{new_path}"
+ end
+end
+
+load File.expand_path("lib/tasks/site.rake", __dir__)
+
desc "Re-transcribe an episode (e.g., rake retranscribe[42])"
task :retranscribe, [:number] do |_t, args|
abort "Usage: rake retranscribe[NUMBER]" unless args[:number]
diff --git a/lib/site.html.erb b/lib/site.html.erb
new file mode 100644
index 0000000..3e336ac
--- /dev/null
+++ b/lib/site.html.erb
@@ -0,0 +1,51 @@
+<!DOCTYPE html>
+<html lang="en">
+<head>
+<meta charset="utf-8">
+<meta name="viewport" content="width=device-width, initial-scale=1">
+<title>Cooking Issues Transcripts</title>
+<style>
+ * { box-sizing: border-box; margin: 0; padding: 0; }
+ body { font-family: system-ui, sans-serif; line-height: 1.6; color: #222; max-width: 50rem; margin: 0 auto; padding: 1rem; }
+ h1 { margin-bottom: 1rem; }
+ .episode { margin: 1.5rem 0; }
+ .episode-header { cursor: pointer; padding: 0.5rem 0; border-bottom: 1px solid #eee; }
+ .episode-header h2 { font-size: 1.1rem; }
+ .episode-header:hover h2 { color: #0066cc; }
+ .episode-body { display: none; padding: 1rem 0; }
+ .episode-body.open { display: block; }
+ .episode-body p { margin-bottom: 1em; }
+ .timestamp { color: #888; font-size: 0.85rem; font-family: monospace; }
+</style>
+</head>
+<body>
+
+<h1>Cooking Issues Transcripts</h1>
+
+<div id="episodes">
+<% transcripts.each do |ep| %>
+ <div class="episode">
+ <div class="episode-header" onclick="toggle(this)">
+ <h2><%= CGI.escapeHTML("#{ep[:number]}. #{ep[:title]}") %></h2>
+ </div>
+ <div class="episode-body">
+ <% ep[:text].split("\n\n").each do |para| %>
+ <% if para =~ /\A\[([^\]]+)\]\s*(.*)/ %>
+ <p><span class="timestamp">[<%= CGI.escapeHTML($1) %>]</span> <%= CGI.escapeHTML($2) %></p>
+ <% else %>
+ <p><%= CGI.escapeHTML(para) %></p>
+ <% end %>
+ <% end %>
+ </div>
+ </div>
+<% end %>
+</div>
+
+<script>
+function toggle(header) {
+ header.nextElementSibling.classList.toggle('open');
+}
+</script>
+
+</body>
+</html>
diff --git a/lib/tasks/site.rake b/lib/tasks/site.rake
new file mode 100644
index 0000000..1a8492f
--- /dev/null
+++ b/lib/tasks/site.rake
@@ -0,0 +1,25 @@
+require "cgi"
+require "erb"
+
+SITE_DIR = Pathname("site")
+
+desc "Generate an HTML page of transcripts"
+task :site do
+ episodes = EPISODES.values.sort_by(&:number).select { |ep| Pathname(text_path(ep)).exist? }
+
+ transcripts = episodes.map do |ep|
+ {
+ number: ep.number,
+ title: ep.title,
+ slug: ep.slug,
+ text: File.read(text_path(ep))
+ }
+ end
+
+ template = File.read(File.expand_path("lib/site.html.erb", __dir__))
+ html = ERB.new(template).result(binding)
+
+ SITE_DIR.mkpath
+ (SITE_DIR / "index.html").write(html)
+ puts "Generated site/index.html with #{transcripts.length} episodes."
+end
diff --git a/transcribers.rake b/lib/tasks/transcribers.rake
similarity index 100%
rename from transcribers.rake
rename to lib/tasks/transcribers.rake