<?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: XTSoft</title>
    <description>The latest articles on DEV Community by XTSoft (@xtsoft_0c4a5615ffbefe25de).</description>
    <link>https://dev.to/xtsoft_0c4a5615ffbefe25de</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%2F4116605%2F07f46230-c3f6-486a-b546-e57befe4729a.png</url>
      <title>DEV Community: XTSoft</title>
      <link>https://dev.to/xtsoft_0c4a5615ffbefe25de</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/xtsoft_0c4a5615ffbefe25de"/>
    <language>en</language>
    <item>
      <title>I stopped missing half my standups — notes on live bilingual captions without a meeting bot</title>
      <dc:creator>XTSoft</dc:creator>
      <pubDate>Wed, 23 Sep 2026 07:57:23 +0000</pubDate>
      <link>https://dev.to/xtsoft_0c4a5615ffbefe25de/i-stopped-missing-half-my-standups-notes-on-live-bilingual-captions-without-a-meeting-bot-4j8a</link>
      <guid>https://dev.to/xtsoft_0c4a5615ffbefe25de/i-stopped-missing-half-my-standups-notes-on-live-bilingual-captions-without-a-meeting-bot-4j8a</guid>
      <description>&lt;p&gt;I work in a company where the meeting language is not my native one.&lt;/p&gt;

&lt;p&gt;Standups are fine on a good day. Design reviews are worse: three people talking over each other, acronyms I do not know yet, and someone saying “ship it” while I am still parsing the previous sentence. Native meeting captions help sometimes. They also fail in the ways that matter when you are already behind:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;They are often &lt;strong&gt;host-gated&lt;/strong&gt; — if the organizer never turns them on, you get nothing.&lt;/li&gt;
&lt;li&gt;They are usually &lt;strong&gt;one language at a time&lt;/strong&gt; — I want the original and a translation side by side when a term is ambiguous.&lt;/li&gt;
&lt;li&gt;They do not help me &lt;strong&gt;take a note without leaving the conversation&lt;/strong&gt; — by the time I open a doc, the thread has moved on.&lt;/li&gt;
&lt;li&gt;The “AI notetaker” path often means &lt;strong&gt;a bot joins the call&lt;/strong&gt; — extra participant, recording notice, IT policy questions, and a little social tax every time.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;So I stopped optimizing for “better post-call transcript” and started optimizing for &lt;strong&gt;staying present while the call is still happening&lt;/strong&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  The constraint that changed the product shape
&lt;/h2&gt;

&lt;p&gt;Offline meeting tools optimize for a clean recording and a polished summary afterward.&lt;/p&gt;

&lt;p&gt;Live tools optimize for a different set:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Work on &lt;strong&gt;Google Meet, Zoom, and Microsoft Teams&lt;/strong&gt; without waiting for each platform’s feature flag.&lt;/li&gt;
&lt;li&gt;Latency low enough that captions feel attached to the voice — for me, roughly a second is the line between aid and distraction.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Original + translation&lt;/strong&gt; available together when I want learning mode, not only a single target language.&lt;/li&gt;
&lt;li&gt;Notes tied to the &lt;strong&gt;same timeline&lt;/strong&gt; as the captions, so “that sentence about Redis” is clickable later.&lt;/li&gt;
&lt;li&gt;Prefer a &lt;strong&gt;participant-side&lt;/strong&gt; capture over inviting another identity into the room.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;That last one is the fork in the road. Bot-join tools are easy to demo. They are also the reason some teams never install them.&lt;/p&gt;

&lt;h2&gt;
  
  
  Why "no bot" is not just a privacy slogan
&lt;/h2&gt;

&lt;p&gt;When a bot joins, three things happen at once:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Everyone sees an extra participant (or a recording banner).&lt;/li&gt;
&lt;li&gt;Policy and consent become a meeting-level decision, not a personal tool choice.&lt;/li&gt;
&lt;li&gt;You inherit every platform’s bot permissions model.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Participant-side captions flip that: &lt;strong&gt;you&lt;/strong&gt; install something that listens on your machine or in your browser tab. Other people do not get a new invitee. You still need to be honest about what is transcribed for &lt;em&gt;you&lt;/em&gt;, but you avoid the social and IT blast radius of a room-wide bot.&lt;/p&gt;

&lt;p&gt;That choice has engineering consequences. Browser tab capture covers Meet and web Zoom/Teams well. The Zoom or Teams &lt;strong&gt;desktop client&lt;/strong&gt; does not live in a tab — so a Windows desktop listener became the twin path for “every meeting on this PC,” same account, same minutes pool.&lt;/p&gt;

&lt;h2&gt;
  
  
  Instant vs accurate translation is a real UX split
&lt;/h2&gt;

&lt;p&gt;Early on I treated “translation quality” as one knob.&lt;/p&gt;

&lt;p&gt;In a live meeting it is two jobs:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Instant&lt;/strong&gt;: keep latency ultra-low for back-and-forth. You accept that a half-finished clause might look rough.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Accurate&lt;/strong&gt;: wait for a fuller sentence, spend a bit more model time, get better technical terms and phrasing.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;I switch between them in the same call. Standup banter wants Instant. A design review full of service names wants Accurate. Shipping only one mode means half your meetings feel wrong.&lt;/p&gt;

&lt;h2&gt;
  
  
  Captions that become notes beat a second app
&lt;/h2&gt;

&lt;p&gt;The pause-loop for meetings is not scrubbing a video. It is:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;hear something important → panic  → open Notion → lose the next two sentences → never find the quote later.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Tapping a caption line into a note, with the transcript kept after the call, closed that loop better than “remember to write it down.” Asking the meeting a question afterward (“what did we decide about caching?”) only works if the live capture was good enough to build a timeline on.&lt;/p&gt;

&lt;p&gt;Summaries are useful. They are not a substitute for being able to read the line that was said at 00:17.&lt;/p&gt;

&lt;h2&gt;
  
  
  What I would tell myself before building
&lt;/h2&gt;

&lt;ol&gt;
&lt;li&gt;Solve &lt;strong&gt;missing the live conversation&lt;/strong&gt;, not “AI meeting notes” as a category.&lt;/li&gt;
&lt;li&gt;Treat &lt;strong&gt;bot vs participant-side&lt;/strong&gt; as a product decision, not an implementation detail.&lt;/li&gt;
&lt;li&gt;Ship &lt;strong&gt;bilingual&lt;/strong&gt; as a first-class mode — original-only and translation-only are modes, not the whole product.&lt;/li&gt;
&lt;li&gt;Accept that &lt;strong&gt;browser + desktop&lt;/strong&gt; are two listeners for one account if you care about Zoom/Teams native apps.&lt;/li&gt;
&lt;li&gt;Auto-stop when the room goes quiet. Forgetting a tab open should not silently burn your monthly minutes.&lt;/li&gt;
&lt;/ol&gt;

&lt;h2&gt;
  
  
  The thing I actually use
&lt;/h2&gt;

&lt;p&gt;I packaged this workflow as &lt;a href="https://sonicmeet.app" rel="noopener noreferrer"&gt;SonicMeet&lt;/a&gt; — Chrome/Edge extension, optional Windows desktop app, freemium meeting hours.&lt;/p&gt;

&lt;p&gt;I am not doing a pricing pitch here. The interesting part for me was treating live meeting understanding as a &lt;strong&gt;latency + bilingual layout + no-bot&lt;/strong&gt; problem, not only an ASR accuracy race.&lt;/p&gt;

&lt;h2&gt;
  
  
  Open questions
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;When do you keep Instant mode on by default vs nudge people toward Accurate for technical calls?&lt;/li&gt;
&lt;li&gt;How do you explain desktop audio capture without sounding like spyware?&lt;/li&gt;
&lt;li&gt;For bilingual captions on a laptop: original on top, translation on top, or a user preference you change mid-call?&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;If you have built realtime speech tools for meetings — or you have your own ritual for surviving standups in a second language — I would love to hear what you landed on in the comments.&lt;/p&gt;

&lt;p&gt;Built this because I needed it. Feedback: &lt;a href="mailto:support@sonicmeet.app"&gt;support@sonicmeet.app&lt;/a&gt;&lt;/p&gt;

</description>
      <category>javascript</category>
      <category>webdev</category>
      <category>productivity</category>
    </item>
    <item>
      <title>I stopped reading subtitles and started listening — notes on real-time AI dubbing in a browser tab</title>
      <dc:creator>XTSoft</dc:creator>
      <pubDate>Sat, 12 Sep 2026 11:59:44 +0000</pubDate>
      <link>https://dev.to/xtsoft_0c4a5615ffbefe25de/i-stopped-reading-subtitles-and-started-listening-notes-on-real-time-ai-dubbing-in-a-browser-tab-3a47</link>
      <guid>https://dev.to/xtsoft_0c4a5615ffbefe25de/i-stopped-reading-subtitles-and-started-listening-notes-on-real-time-ai-dubbing-in-a-browser-tab-3a47</guid>
      <description>&lt;p&gt;For a long time I treated foreign-language video like a reading assignment.&lt;/p&gt;

&lt;p&gt;Open the tab. Turn on captions if they exist. Pause when the line is too fast. Scrub back. Open a dictionary. Miss the next joke anyway.&lt;/p&gt;

&lt;p&gt;That works for a recorded lecture you control. It falls apart for a livestream, a Coursera week you are already behind on, or a meeting where people keep talking while you are still parsing the last sentence.&lt;/p&gt;

&lt;p&gt;Subtitles help you &lt;em&gt;decode&lt;/em&gt;. They do not always help you &lt;em&gt;stay present&lt;/em&gt;. At some point I wanted the opposite posture: keep my eyes on the video, and let my ears take the translation.&lt;/p&gt;

&lt;p&gt;So I started building toward &lt;strong&gt;real-time AI dubbing&lt;/strong&gt; on whatever audio is already playing in the browser — not “upload a file and wait for an MP4.”&lt;/p&gt;

&lt;h2&gt;
  
  
  The job is not “translation quality” in the abstract
&lt;/h2&gt;

&lt;p&gt;Offline tools optimize for a clean transcript and a polished voiceover. Live tools optimize for a different constraint set:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;Stay on the same tab&lt;/strong&gt; — no export, no special player
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Latency low enough to feel watchable&lt;/strong&gt; — for me, roughly half a second is the line between tool and distraction
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Original + translation available together&lt;/strong&gt; when I want them (learning mode)
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;A spoken translation&lt;/strong&gt; when I am tired of reading
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Fail gracefully&lt;/strong&gt; when the network blips — reconnect without throwing away the session mental model
&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;If you only chase BLEU scores, you can still ship something people rage-quit in minute three of a Twitch stream.&lt;/p&gt;

&lt;h2&gt;
  
  
  Tab audio is a blunt but useful boundary
&lt;/h2&gt;

&lt;p&gt;Site-by-site integrations never end. YouTube today, Coursera tomorrow, some random course player next week.&lt;/p&gt;

&lt;p&gt;For v1, “if the tab is playing sound” is a blunt MVP line that actually ships. Capture the tab’s audio, chunk it sensibly (silence is not worth uploading), show captions, and — when dubbing is on — play a translated voice while optionally ducking the original.&lt;/p&gt;

&lt;p&gt;That last part matters more than I expected. A dubbed voice at 100% with the original also at 100% is mush. Ducking the source while the AI voice speaks is a small control with a large “this feels intentional” effect.&lt;/p&gt;

&lt;h2&gt;
  
  
  Dual subtitles changed how I learn; dubbing changed how I watch
&lt;/h2&gt;

&lt;p&gt;Bilingual captions (source + target) cut how often I alt-tab to a dictionary. I still use them when I want accuracy or vocab.&lt;/p&gt;

&lt;p&gt;Dubbing is for a different night: long stream, tired eyes, I mostly want to &lt;em&gt;hear&lt;/em&gt; the meaning and glance at the picture. Same pipeline, different output surface.&lt;/p&gt;

&lt;p&gt;I also learned that “subtitle style” is not cosmetic. A cinema burn-in and a side panel transcript are different reading postures. One keeps you in the video; the other is closer to notes.&lt;/p&gt;

&lt;h2&gt;
  
  
  What I would tell myself before building
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;1. Solve the pause loop, not “AI dubbing” as a vibe.&lt;/strong&gt;&lt;br&gt;&lt;br&gt;
The job-to-be-done was staying present on live or long-form speech.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;2. Universal tab audio beats perfect site hacks for v1.&lt;/strong&gt;&lt;br&gt;&lt;br&gt;
Special-case forever and you never ship Twitch.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;3. Voice choice and mix are product, not polish.&lt;/strong&gt;&lt;br&gt;&lt;br&gt;
People abandon tools that sound wrong even when the text is fine.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;4. Desktop is a different problem.&lt;/strong&gt;&lt;br&gt;&lt;br&gt;
Browser tab capture covers most courses and streams. Downloaded files, desktop Zoom, and “everything on the PC” need a different listener. I ended up with a Windows 11 app for that case — same account, same hours — because the extension alone cannot hear what never enters a tab.&lt;/p&gt;

&lt;h2&gt;
  
  
  The thing I actually use
&lt;/h2&gt;

&lt;p&gt;I packaged this workflow as &lt;strong&gt;DubTab&lt;/strong&gt; — Chrome/Edge extension, optional Windows app, freemium minutes.&lt;/p&gt;

&lt;p&gt;Site: &lt;a href="https://dubtab.com" rel="noopener noreferrer"&gt;dubtab.com&lt;/a&gt;&lt;br&gt;&lt;br&gt;
Chrome Web Store: &lt;a href="https://chromewebstore.google.com/detail/real-time-video-translato/eckchpcahbgbkngandbmcdpdokeoojbf" rel="noopener noreferrer"&gt;DubTab&lt;/a&gt;&lt;br&gt;&lt;br&gt;
Short demo: &lt;a href="https://www.youtube.com/watch?v=pmL_XEo68jg" rel="noopener noreferrer"&gt;YouTube&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;I am not doing a pricing pitch here. The interesting part for me was treating live dubbing as a latency + mix + session problem, not only an ASR problem.&lt;/p&gt;

&lt;h2&gt;
  
  
  Open questions
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;Where do you split live captions vs archival transcripts in product &lt;em&gt;and&lt;/em&gt; storage?
&lt;/li&gt;
&lt;li&gt;How do you explain tab-audio permissions without sounding like malware?
&lt;/li&gt;
&lt;li&gt;For learners: default to bilingual captions, dubbing, or both — what feels least noisy on a 13" laptop?&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;If you have built realtime speech tools — or you have your own pause-rewind ritual for foreign streams — I would love to hear what you landed on in the comments.&lt;/p&gt;




&lt;p&gt;&lt;em&gt;Built this because I needed it. Feedback: &lt;a href="mailto:support@dubtab.com"&gt;support@dubtab.com&lt;/a&gt;&lt;/em&gt;&lt;/p&gt;

</description>
      <category>javascript</category>
      <category>productivity</category>
      <category>webdev</category>
      <category>chrome</category>
    </item>
    <item>
      <title>I kept pausing Japanese streams — so I built tab-audio captions on Cloudflare Workers</title>
      <dc:creator>XTSoft</dc:creator>
      <pubDate>Wed, 09 Sep 2026 01:49:53 +0000</pubDate>
      <link>https://dev.to/xtsoft_0c4a5615ffbefe25de/i-kept-pausing-japanese-streams-so-i-built-tab-audio-captions-on-cloudflare-workers-2cdb</link>
      <guid>https://dev.to/xtsoft_0c4a5615ffbefe25de/i-kept-pausing-japanese-streams-so-i-built-tab-audio-captions-on-cloudflare-workers-2cdb</guid>
      <description>&lt;p&gt;I'm a Chinese speaker living in the US. Weekdays are mostly English: standup on Zoom, design docs, Slack threads that somehow always explode at 5pm. Nights and weekends are Japanese — VTuber streams, cooking livestreams, the occasional anime episode I refuse to watch with English-only subs.&lt;/p&gt;

&lt;p&gt;For months my "language practice" looked like this:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Twitch / YouTube open in Chrome
&lt;/li&gt;
&lt;li&gt;Host says something fast
&lt;/li&gt;
&lt;li&gt;I miss it
&lt;/li&gt;
&lt;li&gt;Pause
&lt;/li&gt;
&lt;li&gt;Scrub back 8–12 seconds
&lt;/li&gt;
&lt;li&gt;Still not sure → open a dictionary tab
&lt;/li&gt;
&lt;li&gt;Stream moves on without me
&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;That loop is survivable for a recorded course. It is miserable for a live stream where chat is already three jokes ahead.&lt;/p&gt;

&lt;p&gt;I didn't want another upload-a-video translator. I wanted: stay on the same tab, see the original line + a Chinese (or English) translation almost immediately, keep watching.&lt;/p&gt;

&lt;p&gt;So I built a Chrome/Edge extension that captions &lt;strong&gt;whatever audio is playing in the tab&lt;/strong&gt;, and put the realtime path on &lt;strong&gt;Cloudflare Workers + Durable Objects&lt;/strong&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  The product constraint (before the stack)
&lt;/h2&gt;

&lt;p&gt;Hard requirements from day one:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Works on &lt;strong&gt;any tab with audio&lt;/strong&gt; — YouTube, Twitch, Netflix-in-browser, Zoom/Meet in the browser, random course sites
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;No file upload&lt;/strong&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Bilingual&lt;/strong&gt; overlay (source + target)
&lt;/li&gt;
&lt;li&gt;Latency low enough that a live stream still feels watchable (~0.5s ballpark for me)
&lt;/li&gt;
&lt;li&gt;Prefer keeping &lt;strong&gt;raw audio in the tab&lt;/strong&gt;; only ship text / small chunks for processing
&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;That ruled out "export MP4 → wait → download SRT." The extension had to own capture; the edge had to own the session.&lt;/p&gt;

&lt;h2&gt;
  
  
  How the pieces fit (CF-shaped)
&lt;/h2&gt;

&lt;p&gt;High level, nothing fancy:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Extension (Chrome MV3)&lt;/strong&gt;&lt;br&gt;&lt;br&gt;
Uses &lt;code&gt;tabCapture&lt;/code&gt; / offscreen document patterns to grab the tab's audio stream, run VAD-ish chunking so I'm not uploading silence, and render a floating bilingual overlay. Settings and history live locally first.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Worker (stateless edge)&lt;/strong&gt;&lt;br&gt;&lt;br&gt;
Auth, plan checks, routing. A request comes in: "here's a short audio/text segment for session &lt;code&gt;X&lt;/code&gt;." The Worker doesn't hold long-lived state — it just verifies the user and hands the work to the right place.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Durable Object (one per caption session)&lt;/strong&gt;&lt;br&gt;&lt;br&gt;
This is the part that made the architecture click for me.&lt;/p&gt;

&lt;p&gt;Each Start click maps to a Durable Object keyed by session id. That object:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Owns the &lt;strong&gt;WebSocket&lt;/strong&gt; to the extension (hibernation-friendly)
&lt;/li&gt;
&lt;li&gt;Queues / serializes ASR + translation steps so chunks don't arrive out of order on screen
&lt;/li&gt;
&lt;li&gt;Tracks &lt;strong&gt;minute usage&lt;/strong&gt; for the free tier without racing a shared Redis
&lt;/li&gt;
&lt;li&gt;Keeps a short rolling buffer of recent caption lines (enough to recover a reconnect without rebuilding history from scratch)
&lt;/li&gt;
&lt;li&gt;Tears down cleanly when the user hits Stop or the tab dies
&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;I tried the "just shove everything through a single Worker + external WebSocket server" version first. It worked until two tabs and a flaky Wi‑Fi night. Per-session Durable Objects made the failure domain obvious: one stuck session doesn't take down everyone else's captions.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Why Cloudflare specifically&lt;/strong&gt;&lt;br&gt;&lt;br&gt;
I didn't want to babysit a caption server in us-west-2 while I'm watching a stream at 1am PT. Workers put the handshake close to me; Durable Objects give me single-threaded session semantics without standing up Redis + a sticky-session LB for a side project that started as "please stop pausing."&lt;/p&gt;

&lt;p&gt;ASR / translation providers sit behind the Worker as normal HTTPS calls. The interesting bit for me wasn't swapping models — it was keeping the &lt;strong&gt;session glue&lt;/strong&gt; boring and correct at the edge.&lt;/p&gt;

&lt;h2&gt;
  
  
  What "good enough" latency felt like
&lt;/h2&gt;

&lt;p&gt;I didn't optimize for leaderboard numbers. I optimized for: can I leave this on for a 90-minute cooking stream without rage-pausing?&lt;/p&gt;

&lt;p&gt;For me, captions landing around &lt;strong&gt;half a second&lt;/strong&gt; after speech is the line between "tool" and "distraction." Faster is nicer; much slower and my thumb goes back to the spacebar.&lt;/p&gt;

&lt;p&gt;So the goal stayed: &lt;em&gt;watchable live captions&lt;/em&gt;, not &lt;em&gt;court-ready transcripts&lt;/em&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  A normal evening with it
&lt;/h2&gt;

&lt;p&gt;Typical flow now:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Install the extension
&lt;/li&gt;
&lt;li&gt;Open the Japanese stream (or the English Zoom tab for work)
&lt;/li&gt;
&lt;li&gt;Pick target language — Chinese when I'm tired, English when I'm taking notes
&lt;/li&gt;
&lt;li&gt;Hit Start
&lt;/li&gt;
&lt;li&gt;Read along: original on top, translation under it
&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Meetings: browser Meet/Zoom tab → Start → stop pretending I caught every acronym.&lt;br&gt;&lt;br&gt;
Language nights: dual subtitles on, dictionary tab closed unless I really want a deep dive later.&lt;/p&gt;

&lt;p&gt;I still export / copy history when I need searchable notes after a lecture. Live comprehension and archival transcripts turned out to be different jobs — which is why the Durable Object keeps only a short buffer, not a forever archive in SQLite by default.&lt;/p&gt;

&lt;h2&gt;
  
  
  Privacy, said plainly
&lt;/h2&gt;

&lt;p&gt;"Listens to tab audio" sounds creepy if you care about privacy (I do — this runs on my work laptop too).&lt;/p&gt;

&lt;p&gt;Design intent:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Capture stays in the &lt;strong&gt;extension / tab&lt;/strong&gt; path
&lt;/li&gt;
&lt;li&gt;The session DO sees &lt;strong&gt;segments for that session&lt;/strong&gt;, not a permanent dump of every stream I've ever watched
&lt;/li&gt;
&lt;li&gt;UI makes it obvious when captioning is running
&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Not a formal security audit. Just: I wouldn't ship something I refuse to enable myself.&lt;/p&gt;

&lt;h2&gt;
  
  
  The thing I actually shipped
&lt;/h2&gt;

&lt;p&gt;All of that is packaged as &lt;strong&gt;SonicCaption&lt;/strong&gt; — Chrome/Edge extension, freemium minutes, bilingual overlay.&lt;/p&gt;

&lt;p&gt;Site: &lt;a href="https://soniccaption.com" rel="noopener noreferrer"&gt;soniccaption.com&lt;/a&gt;&lt;br&gt;&lt;br&gt;
Short demo: &lt;a href="https://www.youtube.com/watch?v=uYHMBQvShtI" rel="noopener noreferrer"&gt;YouTube&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;I'm not doing a pricing pitch here. The interesting part was the constraint set and putting session state in Durable Objects instead of "yet another Node process."&lt;/p&gt;

&lt;h2&gt;
  
  
  What I'd tell myself six months ago
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;1. Fix the pause loop, not "AI translation" as a vibe.&lt;/strong&gt;&lt;br&gt;&lt;br&gt;
The job was staying present on a live Japanese stream while my brain is half in English from work Slack.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;2. One Durable Object per session beats a clever global queue.&lt;/strong&gt;&lt;br&gt;&lt;br&gt;
Ordering, reconnects, and usage counters got simpler when the unit of isolation matched the unit of user intent (Start → Stop).&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;3. Universal tab audio beats site-specific hacks for v1.&lt;/strong&gt;&lt;br&gt;&lt;br&gt;
Special-casing YouTube forever is how you never ship Twitch.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;4. Dual subtitles change behavior.&lt;/strong&gt;&lt;br&gt;&lt;br&gt;
Source + target together cut how often I alt-tabbed to a dictionary mid-stream.&lt;/p&gt;

&lt;h2&gt;
  
  
  Open questions
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;Where do you split live captions vs archival transcripts in product &lt;em&gt;and&lt;/em&gt; in storage?
&lt;/li&gt;
&lt;li&gt;How do you explain &lt;code&gt;tabCapture&lt;/code&gt; permissions without sounding like malware?
&lt;/li&gt;
&lt;li&gt;For bilingual UI on a 13" laptop: stacked lines, side-by-side, or toggle — what feels least noisy?&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;If you've built realtime stuff on Workers / Durable Objects (or fought the same pause-rewind ritual on JP streams), I'd love to hear what you landed on in the comments.&lt;/p&gt;




&lt;p&gt;&lt;em&gt;Built this because I needed it. Feedback: &lt;a href="mailto:support@soniccaption.com"&gt;support@soniccaption.com&lt;/a&gt;&lt;/em&gt;&lt;/p&gt;

</description>
      <category>javascript</category>
      <category>webdev</category>
      <category>chrome</category>
      <category>cloudflare</category>
    </item>
  </channel>
</rss>
