DEV Community

seller-mind
seller-mind

Posted on

Why I Moved My Podcast AI Pipeline to the Edge (and Kept the Model Remote)

When I first started taking my podcast seriously, I quickly realized that recording the audio was only half the battle. The real bottleneck was the post-production admin. After finishing a 45-minute episode, I would routinely spend another two hours just writing titles, drafting show notes, and formatting descriptions.

I tried plugging my transcripts into standard centralized AI tools, but the experience was frustrating. The latency was noticeable, the context windows often choked on longer transcripts, and the outputs felt generic. I was spending more time fixing AI-generated fluff than if I had just written it myself.

So I decided to build something.

The Hidden Shift in Content Production

There is a massive shift happening in how we build AI tools for creators, but we often focus too much on the model and ignore the infrastructure. The industry insight here is simple: where you run the orchestration matters just as much as the model you pick.

When you are dealing with large podcast transcripts—often 10,000 to 30,000 words—the naive design is to have one long-lived server that holds the whole job in memory, streams the transcript through a model, and writes the result back. That design has two failure modes that bite podcasters specifically. First, long jobs on a single origin mean a redeploy kills in-flight work. Second, a single region means a creator in Sydney waits on a machine in Virginia.

The cost of ignoring this architectural reality is creator burnout. If the friction of publishing is too high, podcasters stop publishing. The "blank page" syndrome for show notes is a very real hurdle.

Architecting the Edge Pipeline

For PodCrisp, I made the decision to build the entire backend on Cloudflare Workers. That gives me one deployment that runs in every region, no servers to keep alive, and request-scoped execution that never holds state between invocations.

The important clarification, because this is where a lot of "edge AI" writing gets vague: my orchestration runs at the edge, but the model does not. Worker isolates do not have a GPU. So the Worker's job is to receive the request, do the cheap deterministic work (validate the transcript, chunk it, build the prompt, enforce limits), call an inference API, and then post-process the response. The model itself is served from a normal inference endpoint.

That split is actually the useful part. The edge layer is where you want the logic, because it is close to the user and cheap to run at low volume; the model is where you want zero logic, because every provider will eventually change.

Concretely, the summarization call is a plain fetch to a chat-completions style endpoint, with the model name read from config so I can swap providers without a redeploy:

// Cloudflare Worker: summarization step.
// The Worker is the orchestration layer; inference happens at a remote endpoint.
async function generateShowNotes(transcript, env) {
  const baseUrl = env.DEEPSEEK_API_BASE_URL || 'https://api.deepseek.com';
  const model = env.AI_MODEL || 'deepseek-chat';

  const res = await fetch(`${baseUrl}/chat/completions`, {
    method: 'POST',
    headers: {
      'Content-Type': 'application/json',
      Authorization: `Bearer ${env.DEEPSEEK_API_KEY}`,
    },
    body: JSON.stringify({
      model,
      messages: [
        {
          role: 'system',
          content: `Convert podcast transcripts to show notes:
## Episode Summary (2-3 sentences)
## Key Takeaways (5-7 bullet points)
## Resources Mentioned
Never invent guests, links, or numbers that are not in the transcript.`,
        },
        { role: 'user', content: transcript },
      ],
      max_tokens: 1200,
      temperature: 0.3,
    }),
  });

  if (!res.ok) throw new Error(`inference failed: ${res.status}`);
  return (await res.json()).choices[0].message.content;
}
Enter fullscreen mode Exit fullscreen mode

Notice the strict markdown structure requested in the system prompt. By forcing the AI to output specific headers, the resulting show notes are immediately usable. And note the explicit "never invent guests, links, or numbers" line — that single constraint did more for output quality than any temperature tweak.

Transcription is a separate pipeline with its own provider chain, because transcription and summarization have completely different cost and latency profiles. I route through Groq's whisper-large-v3 first, fall back to OpenAI's whisper-1, and keep AssemblyAI as a third option. The Worker picks whichever key is configured, so a single provider outage does not take the whole product down.

The biggest challenge after that was prompt engineering. Models are notoriously eager to please, which often leads to clickbait titles or overly verbose show notes. I had to build strict constraints into the system prompts to force the model to be useful rather than just creative — word counts, banned phrasing, and an explicit instruction to stay inside the transcript.

Practical Results and Trade-offs

Running the orchestration at the edge cut the request overhead noticeably, and more importantly it removed the "one bad deploy kills every in-flight job" class of bug entirely. Creators no longer sit and watch a spinner while a centralized box chews through a 20,000-word transcript.

What surprised me the most was the impact of the SEO keyword suggestions feature. By having the AI analyze the transcript and suggest keywords, and then naturally integrating those into the generated episode descriptions, the episodes started performing much better in podcast directory search results. It turned a tedious SEO task into an automated byproduct of the writing process.

If I were to change one thing, it would be timestamps. Currently they are estimated from content flow and paragraph length, which is an educated guess. I would rather pass real audio timing data into the prompt so the marks land exactly.

Giving Back to the Community

Building this solved my own workflow problems, but I know many other indie podcasters are struggling with the exact same post-production admin. I wrote up the naming side of it separately — the part where the model keeps handing you clickbait — because that was the piece I had to solve by trial and error: how AI podcast naming actually works when you constrain the prompt properly.


Full disclosure: I'm the developer of PodCrisp. I built this because I needed it myself.

Top comments (0)