Files
ai-podcast/reaper/dialog_regions.lua
T
luke 0b091a1afd Homepage redesign, ep38 publish, Castopod fix, share icons, avatar gender
Website:
- Full homepage redesign: new hero with punchy tagline, social proof strip
  with real caller quotes, featured episode spotlight, clips moved up
- Remove Q&A section, cover art from hero, secondary links
- Fix share icon fill (currentColor), add .sr-only class
- Bump cache versions to v=6

Backend:
- Blacklist Celeste voice
- Fix avatar gender caching with marker files
- Fix _match_voices_to_styles() bypassing BLACKLISTED_VOICES

Publishing:
- Fix Castopod container path (/var/www/castopod/ → /app/)
- Revert CLOUDFLARE_UPLOAD_LIMIT workaround (API fixed)
- Publish episode 38

Reaper:
- Dual silence threshold (2.5s transitions, 6s same-speaker)

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-16 14:31:37 -06:00

116 lines
3.4 KiB
Lua

-- Show Region Marker — background script for REAPER
-- Polls /tmp/reaper_state.txt for state changes and creates colored regions.
-- Backend writes "dialog", "ad", or "ident" to the file.
-- Run via Actions → Run ReaScript before or during recording.
local STATE_FILE = "/tmp/reaper_state.txt"
local COLORS = {
dialog = reaper.ColorToNative(50, 180, 50) + 0x1000000, -- green
ad = reaper.ColorToNative(200, 80, 80) + 0x1000000, -- red
ident = reaper.ColorToNative(80, 120, 200) + 0x1000000, -- blue
}
local LABELS = {
dialog = "DIALOG",
ad = "AD",
ident = "IDENT",
}
local counts = { dialog = 0, ad = 0, ident = 0 }
local current_type = nil -- which region type is currently open
local current_start = 0
local last_pos = 0 -- last known transport position (while running)
local last_state = ""
local transport_active = false
local function log(msg)
reaper.ShowConsoleMsg("[Regions] " .. msg .. "\n")
end
local function is_playing_or_recording()
local state = reaper.GetPlayState()
return state > 0 and state ~= 2
end
local function open_region(rtype)
if current_type then return end
current_type = rtype
current_start = reaper.GetPlayPosition()
log("OPEN " .. rtype .. " at " .. string.format("%.2f", current_start))
end
local function close_region(pos_override)
if not current_type then return end
local pos = pos_override or reaper.GetPlayPosition()
local len = pos - current_start
local rtype = current_type
current_type = nil
log("CLOSE " .. rtype .. " at " .. string.format("%.2f", pos) .. " (len=" .. string.format("%.2f", len) .. ")")
if len > 0.1 then
counts[rtype] = counts[rtype] + 1
local name = LABELS[rtype] .. " " .. counts[rtype]
reaper.AddProjectMarker2(0, true, current_start, pos, name, -1, COLORS[rtype])
log(" -> Created '" .. name .. "'")
else
log(" -> Skipped (too short)")
end
end
local function poll()
if not transport_active then
if is_playing_or_recording() then
transport_active = true
log("Transport started at " .. string.format("%.2f", reaper.GetPlayPosition()))
local f = io.open(STATE_FILE, "r")
if f then
last_state = f:read("*l") or "dialog"
f:close()
else
last_state = "dialog"
end
log("Initial state: '" .. last_state .. "'")
open_region(last_state)
end
reaper.defer(poll)
return
end
-- Track position while transport is running
last_pos = reaper.GetPlayPosition()
-- Detect transport stop (recording ended) — use last known good position
if not is_playing_or_recording() then
log("Transport stopped at last known pos " .. string.format("%.2f", last_pos))
close_region(last_pos)
transport_active = false
reaper.defer(poll)
return
end
local f = io.open(STATE_FILE, "r")
if f then
local state = f:read("*l") or "dialog"
f:close()
if state ~= last_state then
log("State change: '" .. last_state .. "' -> '" .. state .. "'")
close_region()
open_region(state)
last_state = state
end
end
reaper.defer(poll)
end
log("Script loaded — waiting for transport to start...")
reaper.atexit(function()
log("Script stopping (atexit)")
close_region()
local total = counts.dialog + counts.ad + counts.ident
log("Done. " .. total .. " regions (" .. counts.dialog .. " dialog, " .. counts.ad .. " ad, " .. counts.ident .. " ident)")
end)
poll()