<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>DEV Community: Phillip Gray</title>
    <description>The latest articles on DEV Community by Phillip Gray (@thephilgray).</description>
    <link>https://dev.to/thephilgray</link>
    <image>
      <url>https://media2.dev.to/dynamic/image/width=90,height=90,fit=cover,gravity=auto,format=auto/https:%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F58843%2F922d6076-77a5-4097-8ca2-24d4726d91a1.jpeg</url>
      <title>DEV Community: Phillip Gray</title>
      <link>https://dev.to/thephilgray</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/thephilgray"/>
    <language>en</language>
    <item>
      <title>I Used an AI Agent to Make a Product Video. The Cost Was $0, But There's a Catch.</title>
      <dc:creator>Phillip Gray</dc:creator>
      <pubDate>Wed, 01 Jul 2026 05:14:02 +0000</pubDate>
      <link>https://dev.to/thephilgray/i-used-an-ai-agent-to-make-a-product-video-the-cost-was-0-but-theres-a-catch-5761</link>
      <guid>https://dev.to/thephilgray/i-used-an-ai-agent-to-make-a-product-video-the-cost-was-0-but-theres-a-catch-5761</guid>
      <description>&lt;h2&gt;
  
  
  Can an AI Agent Make a Professional Explainer Video for Pocket Change?
&lt;/h2&gt;

&lt;p&gt;The promise of projects like &lt;a href="https://github.com/calesthio/OpenMontage" rel="noopener noreferrer"&gt;OpenMontage&lt;/a&gt;, an open-source agentic video production system, is seductive: describe a video in plain English, and an AI agent handles the rest. Research, scripting, asset generation, editing, rendering—the full stack. To put this to a real-world test, I tasked an agent with producing a 75-second explainer video on a non-trivial topic: local-first software. The goal was a hybrid of animated diagrams, abstract b-roll, and clean text overlays—a classic tech explainer. The question was simple: could the agent deliver a professional product, and what would it &lt;em&gt;really&lt;/em&gt; cost?&lt;/p&gt;

&lt;h2&gt;
  
  
  The Plan: Smooth Sailing and a Reference Point
&lt;/h2&gt;

&lt;p&gt;Getting started with OpenMontage was a breeze. Aside from installing FFmpeg, a well-documented prerequisite, the &lt;code&gt;make setup&lt;/code&gt; command handled all Python and Node dependencies cleanly. The journey began not with a blank prompt, but with a reference video I chose for its polish and recency: Linear's "Introducing Linear Agent." OpenMontage's video analyzer ingested the YouTube URL and returned something far more insightful than a mere transcript. It produced a five-aspect cinematographic breakdown—subject, motion, scene, framing, camera—and even inferred &lt;em&gt;why&lt;/em&gt; the style worked, noting the "high-contrast dark palette... to make plain text look incredibly premium."&lt;/p&gt;

&lt;p&gt;This single prompt took me from a URL to a creative brief with a full estimate of API costs, complete with two distinct concepts grounded in research on the local-first ecosystem. The agent was off to a flying start.&lt;/p&gt;

&lt;h2&gt;
  
  
  The Build: An Agent at the Helm
&lt;/h2&gt;

&lt;p&gt;The agent returned with a &lt;code&gt;STORYBOARD.md&lt;/code&gt;, a detailed 75-second timeline mapping script beats to assets and motion design. It looked solid, so I gave it the green light. A key insight emerged mid-build: OpenMontage isn't an agent itself. As the README states, &lt;strong&gt;"Your AI coding assistant IS the orchestrator."&lt;/strong&gt; The project is a powerful toolkit of pipelines, tools, and skills designed to be wielded by an external agent—in my case, the Antigravity CLI (&lt;code&gt;agy&lt;/code&gt;). This reframed the experiment: I wasn't testing a monolithic product, but how well its tools and instructions could steer my chosen agent.&lt;/p&gt;

&lt;p&gt;The first render attempt was a mixed bag. The agent correctly re-timed the video from 75s to 53s, accounting for the faster-than-estimated narration from the local Piper TTS model. But it also hit a wall. The storyboard had vaguely described a "dedicated subtitle track generated via our transcriber." The result? The entire script was dumped on-screen at once, complete with raw transcriber tokens like &lt;code&gt;[_BEG_]&lt;/code&gt; and awkward word splits (&lt;code&gt;CR DT&lt;/code&gt;). It was a perfect lesson in agentic workflows: the vaguest line in the plan is precisely where it will break.&lt;/p&gt;

&lt;h2&gt;
  
  
  First Look: Art School Project, Not Polished Product
&lt;/h2&gt;

&lt;p&gt;After stripping the broken caption track, I watched the first complete version. The verdict was immediate: it was cohesive and on-theme, but it looked more like an art school video project than a professional explainer. The problems were substantive:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Missing Information:&lt;/strong&gt; The video mentioned CRDTs—the core technical concept—but never explained or diagrammed them. A crucial GCP billing issue earlier in the process had blocked access to Google's Imagen, and the fallback visuals never filled this explanatory gap.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Sync Issues:&lt;/strong&gt; On-screen text and bullet points were frequently out of sync with the narration, sometimes appearing seconds early or transposed.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Amateur Aesthetics:&lt;/strong&gt; The typography felt like a PowerPoint slide, and the b-roll clips, while individually fine, were repeated randomly.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The agent had nailed the vibe but whiffed on the substance. It had assembled atmosphere where I needed explanation.&lt;/p&gt;

&lt;h2&gt;
  
  
  Iteration and a Quality Plateau
&lt;/h2&gt;

&lt;p&gt;I tasked the agent with a targeted revision: fix the timing and add a diagram explaining CRDTs. It successfully corrected the sync issues and generated a Mermaid flowchart for the diagram. This was a definite improvement, but it also highlighted the agent's limits. The Mermaid diagram, while technically correct, had the aesthetic of a corporate IT presentation—the wrong register entirely for a polished product video. The output had hit a quality plateau. We could iterate on the details, but the fundamental feel remained amateurish. This was the stopping point.&lt;/p&gt;

&lt;h2&gt;
  
  
  Friction, Surprises, and the Real Cost
&lt;/h2&gt;

&lt;p&gt;The process also revealed several fascinating and instructive points of friction. At one point, the agent silently stalled, seemingly stuck in a long thought process. It turned out to be waiting for a hidden permission prompt, a reminder to check an agent's underlying processes. More surprisingly, the agent autonomously patched OpenMontage's source code to fix a bug in how it loaded API keys from the &lt;code&gt;.env&lt;/code&gt; file.&lt;/p&gt;

&lt;p&gt;The most critical lesson, however, was about cost. The final bill for the video was &lt;strong&gt;effectively $0.&lt;/strong&gt; The handful of calls to Google's Imagen API fell within the free tier. But getting there wasn't free. A single &lt;code&gt;GOOGLE_API_KEY&lt;/code&gt; doesn't unlock all of Google's services; the key for Gemini doesn't work for Cloud Text-to-Speech or Imagen out of the box. Unlocking Imagen required enabling billing on my Google Cloud project, which involved a ten-minute detour to set up a new billing account with a &lt;strong&gt;$10 minimum prepay.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;This is the crucial asterisk. The &lt;em&gt;marginal&lt;/em&gt; cost of making the video was pennies, but the &lt;em&gt;floor to enter&lt;/em&gt; was $10 and a bureaucratic setup process. The pocket change promise is real, but the on-ramp isn't free.&lt;/p&gt;

&lt;h2&gt;
  
  
  The Verdict: A Powerful Tool with a Ceiling
&lt;/h2&gt;

&lt;p&gt;So, would I use OpenMontage again? Absolutely. It delivered on its core promise, orchestrating a complex production pipeline from a simple prompt for virtually no cost. The economic advantage over cloud video tools is staggering. Coming from the world of manual video editing, the ability to iterate on a script or timing with a single prompt feels like a superpower.&lt;/p&gt;

&lt;p&gt;But the output has a ceiling. The final product never felt professional. A key workflow gap is the inability to easily review visual assets before they're baked into the final composition. For a truly polished result, I'd need a more hands-on approach, using the agent for heavy lifting but manually guiding the script, visual selection, and final composition.&lt;/p&gt;

&lt;p&gt;OpenMontage proves that agent-driven video production is not only possible but incredibly cost-effective. It can get you 80% of the way there for 1% of the cost. Closing that final 20% gap, however, still requires a human hand at the wheel.&lt;/p&gt;

</description>
      <category>ai</category>
      <category>video</category>
      <category>opensource</category>
      <category>python</category>
    </item>
    <item>
      <title>Building a Local-First Voice Copilot for the Shell with HoldSpeak and Ollama</title>
      <dc:creator>Phillip Gray</dc:creator>
      <pubDate>Sat, 27 Jun 2026 03:04:40 +0000</pubDate>
      <link>https://dev.to/thephilgray/building-a-local-first-voice-copilot-for-the-shell-with-holdspeak-and-ollama-57lm</link>
      <guid>https://dev.to/thephilgray/building-a-local-first-voice-copilot-for-the-shell-with-holdspeak-and-ollama-57lm</guid>
      <description>&lt;h2&gt;
  
  
  The Promise: A Private, Voice-Activated Shell
&lt;/h2&gt;

&lt;p&gt;The dream of a voice-activated command line is compelling: speak a command, see it executed. But for many developers, piping terminal input through a cloud-based API is a non-starter. This is the promise of a project like &lt;code&gt;karolswdev/HoldSpeak&lt;/code&gt;, a cross-platform tool for local voice typing. Could it be the core of a truly local-first, push-to-talk shell assistant? I paired it with Ollama and a local &lt;code&gt;llama3.2&lt;/code&gt; model to find out.&lt;/p&gt;

&lt;p&gt;The goal was simple: hold a key, speak a command like "list files by size," release the key, and have the correct shell command appear, gated by a final confirmation prompt. This project turned out to be a tale of two stacks: one for voice that was surprisingly clean, and one for language that revealed the sharp edges of the local-first promise.&lt;/p&gt;

&lt;h3&gt;
  
  
  Building the Demo
&lt;/h3&gt;

&lt;p&gt;To test this idea, I built a small Python script to tie these components together. You can find the complete code for this experiment, including the prompt engineering, in my demo project on GitHub: &lt;a href="https://github.com/thephilgray/holdspeak-cli" rel="noopener noreferrer"&gt;voice-activated-shell-demo&lt;/a&gt;.&lt;/p&gt;

&lt;h4&gt;
  
  
  Setup Instructions
&lt;/h4&gt;

&lt;p&gt;Recreating this local-first voice assistant involves a few distinct steps:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Install HoldSpeak from Source&lt;/strong&gt;: Since we need to use it as a library, clone the repository and install it in editable mode.&lt;br&gt;
&lt;/p&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;git clone https://github.com/karolswdev/HoldSpeak.git
&lt;span class="nb"&gt;cd &lt;/span&gt;HoldSpeak
pip3 &lt;span class="nb"&gt;install&lt;/span&gt; &lt;span class="nt"&gt;-e&lt;/span&gt; &lt;span class="nb"&gt;.&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Install and Run Ollama&lt;/strong&gt;: Use Homebrew (on macOS) to install the Ollama CLI, then start the server.&lt;br&gt;
&lt;/p&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;brew &lt;span class="nb"&gt;install &lt;/span&gt;ollama
ollama serve
&lt;/code&gt;&lt;/pre&gt;

&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Pull a Local LLM&lt;/strong&gt;: In a separate terminal, pull a small, capable model. I used &lt;code&gt;llama3.2&lt;/code&gt;.&lt;br&gt;
&lt;/p&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;ollama pull llama3.2
&lt;/code&gt;&lt;/pre&gt;

&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Grant Permissions (macOS)&lt;/strong&gt;: To allow the hotkey listener to work, your terminal application (e.g., iTerm, Terminal.app) must be given Accessibility permissions in &lt;code&gt;System Settings &amp;gt; Privacy &amp;amp; Security &amp;gt; Accessibility&lt;/code&gt;.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Run the Demo Script&lt;/strong&gt;: With the setup complete, you can run the final Python script that integrates all these components.&lt;/p&gt;&lt;/li&gt;
&lt;/ol&gt;

&lt;h2&gt;
  
  
  Finding the Seams in HoldSpeak
&lt;/h2&gt;

&lt;p&gt;HoldSpeak presents itself as an application, but my goal was to use it as a library. The first step, installation, was a simple &lt;code&gt;pip3 install -e .&lt;/code&gt;. The second step was hitting a wall: &lt;code&gt;import holdspeak&lt;/code&gt; exports no documented, usable API. The path forward was to grep the source code.&lt;/p&gt;

&lt;p&gt;This source-diving quickly revealed the clean seams I needed:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;&lt;code&gt;AudioRecorder&lt;/code&gt; (&lt;code&gt;holdspeak/audio.py&lt;/code&gt;): A simple class to capture audio from the default microphone.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;code&gt;Transcriber&lt;/code&gt; (&lt;code&gt;holdspeak/transcribe.py&lt;/code&gt;): A wrapper that intelligently selects a local backend (in my case, MLX Whisper on macOS) to convert audio into text.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The core components were there, but finding them was the tax. For a project with extensive product documentation, it provided no documented API.&lt;/p&gt;

&lt;h2&gt;
  
  
  Assembling the Local Stack
&lt;/h2&gt;

&lt;p&gt;With the voice components identified, I set up the other half of the local stack: the Large Language Model. Standing up a local LLM with Ollama is one of the easiest parts of the modern AI landscape: &lt;code&gt;brew install ollama&lt;/code&gt;, &lt;code&gt;ollama serve&lt;/code&gt;, and &lt;code&gt;ollama pull llama3.2&lt;/code&gt;. No accounts, no API keys.&lt;/p&gt;

&lt;p&gt;The friction appeared immediately, not in setup, but in correctness. A smoke test asking for "list files sorted by size" returned &lt;code&gt;ls -lh | sort -k1&lt;/code&gt;, a plausible but incorrect command that sorts by file permissions, not size. The correct command is &lt;code&gt;ls -lhS&lt;/code&gt;. This early result established the central tension of the project: the local LLM was easy to install but unreliable out of the box.&lt;/p&gt;

&lt;p&gt;In contrast, wiring up HoldSpeak's &lt;code&gt;AudioRecorder&lt;/code&gt; and &lt;code&gt;Transcriber&lt;/code&gt; was almost anticlimactic. Twelve lines of Python were all it took to capture and transcribe audio. When I spoke "list files by size," Whisper returned the exact text, &lt;code&gt;'List files by size'&lt;/code&gt;, flawlessly. The local stack had two very different halves: speech-to-text was crisp and effortless; text-to-command was already the weak link.&lt;/p&gt;

&lt;h2&gt;
  
  
  Adding Push-to-Talk and a Safety Gate
&lt;/h2&gt;

&lt;p&gt;More source-diving uncovered a third seam: &lt;code&gt;HotkeyListener&lt;/code&gt; (&lt;code&gt;holdspeak/hotkey.py&lt;/code&gt;). This class provided a clean callback API for push-to-talk functionality, defaulting to the Right Option key. Integrating it was trivial, but it surfaced an undocumented OS-level hurdle: on macOS, my terminal (iTerm) needed Accessibility permissions. The listener failed silently until I granted the permission and completely restarted the application.&lt;/p&gt;

&lt;p&gt;With the hotkey, recorder, transcriber, and Ollama all wired together, the final piece was a confirmation loop. Before executing any command with &lt;code&gt;subprocess&lt;/code&gt;, a simple &lt;code&gt;input("run? [y/N]")&lt;/code&gt; provided a critical safety gate.&lt;/p&gt;

&lt;p&gt;The very first real run proved why it was so necessary. I held Right Option and said, "show me the 5 largest files." The LLM returned &lt;code&gt;ls -lhS | tail -n 5&lt;/code&gt;. It looked correct, so I hit &lt;code&gt;y&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;It was wrong. &lt;code&gt;ls -lhS&lt;/code&gt; sorts files from largest to smallest. &lt;code&gt;tail -n 5&lt;/code&gt; therefore returns the 5 &lt;em&gt;smallest&lt;/em&gt; files from that list. The confirmation prompt protected me from malicious commands, but not from plausible but subtly incorrect ones. I had approved my own bug.&lt;/p&gt;

&lt;h2&gt;
  
  
  Evaluation: A Great Voice Library, A Fragile Copilot
&lt;/h2&gt;

&lt;p&gt;Should you build a voice CLI copilot on HoldSpeak today? Yes for the voice layer, but with major caveats about relying on a small, local LLM for autonomy.&lt;/p&gt;

&lt;h3&gt;
  
  
  HoldSpeak as a Library
&lt;/h3&gt;

&lt;p&gt;I would use HoldSpeak again. Once you find the entry points—&lt;code&gt;AudioRecorder&lt;/code&gt;, &lt;code&gt;Transcriber&lt;/code&gt;, and &lt;code&gt;HotkeyListener&lt;/code&gt;—they are well-shaped components that compose into a working push-to-talk loop in under 100 lines. The local Whisper transcription was fast, accurate, and required zero configuration to use the MLX backend on Apple Silicon. The single biggest improvement HoldSpeak could make is documenting this programmatic path. A short "using HoldSpeak as a library" guide would have erased most of this project's friction.&lt;/p&gt;

&lt;h3&gt;
  
  
  The Local-First Tradeoff
&lt;/h3&gt;

&lt;p&gt;This demo perfectly illustrates the tradeoff of a fully local AI stack. The "no cloud" setup is fast, cheap, and private. But that convenience comes at the cost of correctness. The &lt;code&gt;llama3.2&lt;/code&gt; model produced plausible-but-wrong commands repeatedly, and while prompt engineering can fix specific failure cases you identify in advance, it's a process of patching over specific failures rather than building generalized reliability.&lt;/p&gt;

&lt;p&gt;The confirm-before-execute gate is mandatory. It makes the tool &lt;em&gt;safe&lt;/em&gt;, but it does not make it &lt;em&gt;correct&lt;/em&gt;. It protects you from commands you recognize as wrong, but does nothing for the ones that look right, which is where small models often fail. A voice interface, by its nature, encourages speed over the careful inspection of an LLM's work.&lt;/p&gt;

&lt;p&gt;HoldSpeak is a recommendable, high-quality voice library waiting to be discovered. The local-first shell copilot I built on top of it, however, remains a great demo but not yet a shippable tool. To make it real, you'd need a larger, more capable model (defeating some of the purpose of a small local setup) or a UI that explains &lt;em&gt;why&lt;/em&gt; a command was chosen, giving the user a better chance to catch the subtle bugs a confirmation prompt can't.&lt;/p&gt;

</description>
      <category>python</category>
      <category>cli</category>
      <category>voice</category>
      <category>ollama</category>
    </item>
  </channel>
</rss>
