<?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: Ra Baryon Neutrino</title>
    <description>The latest articles on DEV Community by Ra Baryon Neutrino (@chengsokdara).</description>
    <link>https://dev.to/chengsokdara</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.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F813850%2Fbf8357af-393f-4bcc-bc22-e4d38c3e0220.jpeg</url>
      <title>DEV Community: Ra Baryon Neutrino</title>
      <link>https://dev.to/chengsokdara</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/chengsokdara"/>
    <language>en</language>
    <item>
      <title>Transform Your Speech into Text with the Power of OpenAI and useWhisper</title>
      <dc:creator>Ra Baryon Neutrino</dc:creator>
      <pubDate>Wed, 04 Jun 2025 06:46:10 +0000</pubDate>
      <link>https://dev.to/chengsokdara/transform-your-speech-into-text-with-the-power-of-openai-and-usewhisper-5175</link>
      <guid>https://dev.to/chengsokdara/transform-your-speech-into-text-with-the-power-of-openai-and-usewhisper-5175</guid>
      <description>&lt;blockquote&gt;
&lt;p&gt;This article was generated using ChatGPT from README.md&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h2&gt;
  
  
  Demo
&lt;/h2&gt;

&lt;p&gt;  &lt;iframe src="https://www.youtube.com/embed/__YsEghlLaU"&gt;
  &lt;/iframe&gt;
&lt;/p&gt;

&lt;p&gt;Are you tired of spending hours transcribing speech into text manually? Are you looking for a way to save time and increase accuracy? If so, you'll want to check out useWhisper, a React Hook for OpenAI Whisper API that comes with speech recorder and silence removal built-in.&lt;/p&gt;

&lt;h2&gt;
  
  
  Introduction
&lt;/h2&gt;

&lt;p&gt;Transcribing speech is a common task in many industries, including journalism, entertainment, and customer service. However, the process can be time-consuming and often leads to errors. With useWhisper, you can quickly and accurately transcribe speech into text using the power of OpenAI.&lt;/p&gt;

&lt;h2&gt;
  
  
  Getting Started
&lt;/h2&gt;

&lt;p&gt;Getting started with useWhisper is easy. First, install the package:&lt;/p&gt;

&lt;p&gt;&lt;code&gt;npm i @chengsokdara/use-whisper&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;or&lt;/p&gt;

&lt;p&gt;&lt;code&gt;yarn add @chengsokdara/use-whisper&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;Once you've installed useWhisper, you can start using it in your React app. Import the hook:&lt;/p&gt;

&lt;p&gt;&lt;code&gt;import { useWhisper } from '@chengsokdara/use-whisper'&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;Next, call the hook within your component, passing in your OpenAI API token:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;useWhisper&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;@chengsokdara/use-whisper&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;

&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;App&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nx"&gt;recording&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="nx"&gt;speaking&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="nx"&gt;transcript&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="nx"&gt;transcripting&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="nx"&gt;pauseRecording&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="nx"&gt;startRecording&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="nx"&gt;stopRecording&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;useWhisper&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;
    &lt;span class="na"&gt;apiKey&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;env&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;process&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;OPENAI_API_TOKEN&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="c1"&gt;// YOUR_OPEN_AI_TOKEN&lt;/span&gt;
  &lt;span class="p"&gt;})&lt;/span&gt;

  &lt;span class="k"&gt;return &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;div&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;
      &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;p&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="na"&gt;Recording&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;recording&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="sr"&gt;/p&lt;/span&gt;&lt;span class="err"&gt;&amp;gt;
&lt;/span&gt;      &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;p&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="na"&gt;Speaking&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;speaking&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="sr"&gt;/p&lt;/span&gt;&lt;span class="err"&gt;&amp;gt;
&lt;/span&gt;      &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;p&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="na"&gt;Transcripting&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;transcripting&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="sr"&gt;/p&lt;/span&gt;&lt;span class="err"&gt;&amp;gt;
&lt;/span&gt;      &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;p&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="nx"&gt;Transcribed&lt;/span&gt; &lt;span class="na"&gt;Text&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;transcript&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;text&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="sr"&gt;/p&lt;/span&gt;&lt;span class="err"&gt;&amp;gt;
&lt;/span&gt;      &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;button&lt;/span&gt; &lt;span class="nx"&gt;onClick&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;{()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nf"&gt;startRecording&lt;/span&gt;&lt;span class="p"&gt;()}&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="nx"&gt;Start&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="sr"&gt;/button&lt;/span&gt;&lt;span class="err"&gt;&amp;gt;
&lt;/span&gt;      &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;button&lt;/span&gt; &lt;span class="nx"&gt;onClick&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;{()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nf"&gt;pauseRecording&lt;/span&gt;&lt;span class="p"&gt;()}&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="nx"&gt;Pause&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="sr"&gt;/button&lt;/span&gt;&lt;span class="err"&gt;&amp;gt;
&lt;/span&gt;      &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;button&lt;/span&gt; &lt;span class="nx"&gt;onClick&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;{()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nf"&gt;stopRecording&lt;/span&gt;&lt;span class="p"&gt;()}&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="nx"&gt;Stop&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="sr"&gt;/button&lt;/span&gt;&lt;span class="err"&gt;&amp;gt;
&lt;/span&gt;    &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="sr"&gt;/div&lt;/span&gt;&lt;span class="err"&gt;&amp;gt;
&lt;/span&gt;  &lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;You're now ready to start using useWhisper to transcribe speech!&lt;/p&gt;
&lt;h2&gt;
  
  
  Configuration Options
&lt;/h2&gt;

&lt;p&gt;One of the benefits of useWhisper is its flexibility. It provides several configuration options that you can use to customize your speech recognition experience.&lt;br&gt;
The available options are:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;apiKey: Your OpenAI API key (required).&lt;/li&gt;
&lt;li&gt;autoStart: Automatically start speech recording on component mount.&lt;/li&gt;
&lt;li&gt;customServer: Supply your own whisper REST API endpoint&lt;/li&gt;
&lt;li&gt;nonStop: If true, recording will auto-stop after stopTimeout. However, if the user keeps speaking, the recorder will keep recording.&lt;/li&gt;
&lt;li&gt;removeSilence: Remove silence before sending the file to OpenAI API.&lt;/li&gt;
&lt;li&gt;stopTimeout: If nonStop is true, this becomes required. This controls when the recorder auto-stops.&lt;/li&gt;
&lt;/ul&gt;
&lt;h2&gt;
  
  
  Methods and States
&lt;/h2&gt;

&lt;p&gt;In addition to the configuration options, useWhisper also provides several methods that you can use to control speech recording:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;recording: Speech recording state.&lt;/li&gt;
&lt;li&gt;speaking: Detect when the user is speaking.&lt;/li&gt;
&lt;li&gt;transcript: Object returned after Whisper transcription is complete.&lt;/li&gt;
&lt;li&gt;transcripting : Remove silence from speech and send request to OpenAI Whisper API&lt;/li&gt;
&lt;li&gt;pauseRecording: Pause speech recording.&lt;/li&gt;
&lt;li&gt;startRecording: Start speech recording.&lt;/li&gt;
&lt;li&gt;stopRecording: Stop speech recording.&lt;/li&gt;
&lt;/ul&gt;
&lt;h2&gt;
  
  
  Transcript Object
&lt;/h2&gt;

&lt;p&gt;The transcript object returned from the hook contains the following:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;blob: Recorded speech in JavaScript Blob.&lt;/li&gt;
&lt;li&gt;text: Transcribed text returned from Whisper API.&lt;/li&gt;
&lt;/ul&gt;
&lt;h2&gt;
  
  
  Source Code
&lt;/h2&gt;


&lt;div class="ltag-github-readme-tag"&gt;
  &lt;div class="readme-overview"&gt;
    &lt;h2&gt;
      &lt;img src="https://assets.dev.to/assets/github-logo-5a155e1f9a670af7944dd5e12375bc76ed542ea80224905ecaf878b9157cdefc.svg" alt="GitHub logo"&gt;
      &lt;a href="https://github.com/chengsokdara" rel="noopener noreferrer"&gt;
        chengsokdara
      &lt;/a&gt; / &lt;a href="https://github.com/chengsokdara/use-whisper" rel="noopener noreferrer"&gt;
        use-whisper
      &lt;/a&gt;
    &lt;/h2&gt;
    &lt;h3&gt;
      React hook for OpenAI Whisper with speech recorder, real-time transcription, and silence removal built-in
    &lt;/h3&gt;
  &lt;/div&gt;
  &lt;div class="ltag-github-body"&gt;
    
&lt;div id="readme" class="md"&gt;
&lt;div class="markdown-heading"&gt;
&lt;h1 class="heading-element"&gt;useWhisper&lt;/h1&gt;
&lt;/div&gt;

&lt;p&gt;React Hook for OpenAI Whisper API with speech recorder, real-time transcription and silence removal built-in&lt;/p&gt;




&lt;ul&gt;
&lt;li&gt;
&lt;div class="markdown-heading"&gt;
&lt;h3 class="heading-element"&gt;Demo&lt;/h3&gt;
&lt;/div&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;div class="markdown-heading"&gt;
&lt;h6 class="heading-element"&gt;Real-Time transcription demo&lt;/h6&gt;
&lt;/div&gt;
&lt;/li&gt;
&lt;/ul&gt;


  
    
    

    &lt;span class="m-1"&gt;use-whisper-real-time-transcription.mp4&lt;/span&gt;
    
  

  

  





&lt;ul&gt;
&lt;li&gt;
&lt;div class="markdown-heading"&gt;
&lt;h3 class="heading-element"&gt;Announcement&lt;/h3&gt;

&lt;/div&gt;
&lt;p&gt;useWhisper for React Native is being developed.&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Repository: &lt;a href="https://github.com/chengsokdara/use-whisper-native" rel="noopener noreferrer"&gt;https://github.com/chengsokdara/use-whisper-native&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Progress: &lt;a class="issue-link js-issue-link" href="https://github.com/chengsokdara/use-whisper-native/issues/1" rel="noopener noreferrer"&gt;chengsokdara/use-whisper-native#1&lt;/a&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;div class="markdown-heading"&gt;
&lt;h3 class="heading-element"&gt;Install&lt;/h3&gt;

&lt;/div&gt;
&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="snippet-clipboard-content notranslate position-relative overflow-auto"&gt;&lt;pre class="notranslate"&gt;&lt;code&gt;npm i @chengsokdara/use-whisper
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;div class="snippet-clipboard-content notranslate position-relative overflow-auto"&gt;&lt;pre class="notranslate"&gt;&lt;code&gt;yarn add @chengsokdara/use-whisper
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;div class="markdown-heading"&gt;
&lt;h3 class="heading-element"&gt;Usage&lt;/h3&gt;

&lt;/div&gt;


&lt;/li&gt;

&lt;/ul&gt;

&lt;div class="highlight highlight-source-js notranslate position-relative overflow-auto js-code-highlight"&gt;
&lt;pre&gt;&lt;span class="pl-k"&gt;import&lt;/span&gt; &lt;span class="pl-kos"&gt;{&lt;/span&gt; &lt;span class="pl-s1"&gt;useWhisper&lt;/span&gt; &lt;span class="pl-kos"&gt;}&lt;/span&gt; &lt;span class="pl-k"&gt;from&lt;/span&gt; &lt;span class="pl-s"&gt;'&lt;a class="mentioned-user" href="https://dev.to/chengsokdara"&gt;@chengsokdara&lt;/a&gt;/use-whisper'&lt;/span&gt;
&lt;span class="pl-k"&gt;const&lt;/span&gt; &lt;span class="pl-v"&gt;App&lt;/span&gt; &lt;span class="pl-c1"&gt;=&lt;/span&gt; &lt;span class="pl-kos"&gt;(&lt;/span&gt;&lt;span class="pl-kos"&gt;)&lt;/span&gt; &lt;span class="pl-c1"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="pl-kos"&gt;{&lt;/span&gt;
  &lt;span class="pl-k"&gt;const&lt;/span&gt; &lt;span class="pl-kos"&gt;{&lt;/span&gt;
    recording&lt;span class="pl-kos"&gt;,&lt;/span&gt;
    speaking&lt;span class="pl-kos"&gt;,&lt;/span&gt;
    transcribing&lt;span class="pl-kos"&gt;,&lt;/span&gt;
    transcript&lt;span class="pl-kos"&gt;,&lt;/span&gt;
    pauseRecording&lt;span class="pl-kos"&gt;,&lt;/span&gt;
    startRecording&lt;span class="pl-kos"&gt;,&lt;/span&gt;
    stopRecording&lt;span class="pl-kos"&gt;,&lt;/span&gt;
  &lt;span class="pl-kos"&gt;}&lt;/span&gt; &lt;span class="pl-c1"&gt;=&lt;/span&gt; &lt;span class="pl-en"&gt;useWhisper&lt;/span&gt;&lt;span class="pl-kos"&gt;(&lt;/span&gt;&lt;span class="pl-kos"&gt;{&lt;/span&gt;
    &lt;span class="pl-c1"&gt;apiKey&lt;/span&gt;: &lt;span class="pl-s1"&gt;process&lt;/span&gt;&lt;span class="pl-kos"&gt;.&lt;/span&gt;&lt;span class="pl-c1"&gt;env&lt;/span&gt;&lt;span class="pl-kos"&gt;.&lt;/span&gt;&lt;span class="pl-c1"&gt;OPENAI_API_TOKEN&lt;/span&gt;&lt;span class="pl-kos"&gt;,&lt;/span&gt; &lt;span class="pl-c"&gt;// YOUR_OPEN_AI_TOKEN&lt;/span&gt;
  &lt;span class="pl-kos"&gt;}&lt;/span&gt;&lt;span class="pl-kos"&gt;)&lt;/span&gt;

  &lt;span class="pl-k"&gt;return&lt;/span&gt; &lt;span class="pl-kos"&gt;(&lt;/span&gt;
    &lt;span class="pl-c1"&gt;&amp;lt;&lt;/span&gt;&lt;span class="pl-s1"&gt;div&lt;/span&gt;&lt;span class="pl-c1"&gt;&amp;gt;&lt;/span&gt;
      &lt;span class="pl-c1"&gt;&amp;lt;&lt;/span&gt;&lt;span class="pl-s1"&gt;p&lt;/span&gt;&lt;span class="pl-c1"&gt;&amp;gt;&lt;/span&gt;Recording: &lt;span class="pl-kos"&gt;{&lt;/span&gt;&lt;span class="pl-s1"&gt;recording&lt;/span&gt;&lt;span class="pl-kos"&gt;}&lt;/span&gt;&lt;span class="pl-kos"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="pl-s1"&gt;p&lt;/span&gt;&lt;span class="pl-c1"&gt;&amp;gt;&lt;/span&gt;
      &lt;span class="pl-c1"&gt;&amp;lt;&lt;/span&gt;&lt;span class="pl-s1"&gt;p&lt;/span&gt;&lt;span class="pl-c1"&gt;&amp;gt;&lt;/span&gt;Speaking: &lt;span class="pl-kos"&gt;{&lt;/span&gt;&lt;span class="pl-s1"&gt;speaking&lt;/span&gt;&lt;span class="pl-kos"&gt;}&lt;/span&gt;&lt;span class="pl-kos"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="pl-s1"&gt;p&lt;/span&gt;&lt;span class="pl-c1"&gt;&amp;gt;&lt;/span&gt;
      &lt;span class="pl-c1"&gt;&amp;lt;&lt;/span&gt;&lt;span class="pl-s1"&gt;p&lt;/span&gt;&lt;span class="pl-c1"&gt;&amp;gt;&lt;/span&gt;Transcribing: &lt;span class="pl-kos"&gt;{&lt;/span&gt;&lt;span class="pl-s1"&gt;transcribing&lt;/span&gt;&lt;span class="pl-kos"&gt;}&lt;/span&gt;&lt;span class="pl-kos"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="pl-s1"&gt;p&lt;/span&gt;&lt;span class="pl-c1"&gt;&amp;gt;&lt;/span&gt;
      &lt;span class="pl-c1"&gt;&amp;lt;&lt;/span&gt;&lt;span class="pl-s1"&gt;p&lt;/span&gt;&lt;span class="pl-c1"&gt;&amp;gt;&lt;/span&gt;Transcribed Text: &lt;span class="pl-kos"&gt;{&lt;/span&gt;&lt;span class="pl-s1"&gt;transcript&lt;/span&gt;&lt;span class="pl-kos"&gt;.&lt;/span&gt;&lt;span class="pl-c1"&gt;text&lt;/span&gt;&lt;span class="pl-kos"&gt;}&lt;/span&gt;&lt;span class="pl-kos"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="pl-s1"&gt;p&lt;/span&gt;&lt;span class="pl-c1"&gt;&amp;gt;&lt;/span&gt;
      &lt;span class="pl-c1"&gt;&amp;lt;&lt;/span&gt;&lt;span class="pl-s1"&gt;button&lt;/span&gt; &lt;span class="pl-c1"&gt;onClick&lt;/span&gt;&lt;span class="pl-c1"&gt;=&lt;/span&gt;&lt;span class="pl-kos"&gt;{&lt;/span&gt;&lt;span class="pl-kos"&gt;(&lt;/span&gt;&lt;span class="pl-kos"&gt;)&lt;/span&gt; &lt;span class="pl-c1"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="pl-en"&gt;startRecording&lt;/span&gt;&lt;span class="pl-kos"&gt;(&lt;/span&gt;&lt;span class="pl-kos"&gt;)&lt;/span&gt;&lt;span class="pl-kos"&gt;}&lt;/span&gt;&lt;span class="pl-c1"&gt;&amp;gt;&lt;/span&gt;Start&lt;span class="pl-kos"&gt;&amp;lt;/&lt;/span&gt;&lt;/pre&gt;…
&lt;/div&gt;
&lt;/div&gt;
  &lt;/div&gt;
  &lt;div class="gh-btn-container"&gt;&lt;a class="gh-btn" href="https://github.com/chengsokdara/use-whisper" rel="noopener noreferrer"&gt;View on GitHub&lt;/a&gt;&lt;/div&gt;
&lt;/div&gt;



&lt;h2&gt;
  
  
  Contact me
&lt;/h2&gt;

&lt;p&gt;for web or mobile app development using React or React Native&lt;br&gt;
&lt;a href="mailto:chengsokdara@gmail.com"&gt;chengsokdara@gmail.com&lt;/a&gt;&lt;br&gt;
&lt;a href="https://chengsokdara.github.io" rel="noopener noreferrer"&gt;https://chengsokdara.github.io&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Conclusion
&lt;/h2&gt;

&lt;p&gt;useWhisper is a game-changer for anyone who needs to transcribe speech into text quickly and accurately. With its built-in speech recorder and silence removal, you can save time and reduce cost. Whether you're a journalist, customer service representative, or anyone who needs to transcribe speech, useWhisper is the tool for you. Try it out today!&lt;/p&gt;

</description>
      <category>react</category>
      <category>whisper</category>
      <category>openai</category>
      <category>nextjs</category>
    </item>
    <item>
      <title>AI-Powered Hiring: From Inbox Chaos to Structured Data with Postmark &amp; LLM</title>
      <dc:creator>Ra Baryon Neutrino</dc:creator>
      <pubDate>Sun, 01 Jun 2025 18:12:07 +0000</pubDate>
      <link>https://dev.to/chengsokdara/ai-powered-hiring-from-inbox-chaos-to-structured-data-with-postmark-llm-59kf</link>
      <guid>https://dev.to/chengsokdara/ai-powered-hiring-from-inbox-chaos-to-structured-data-with-postmark-llm-59kf</guid>
      <description>&lt;p&gt;This is a submission for the &lt;a href="https://dev.to/challenges/postmark"&gt;Postmark Challenge: Inbox Innovators&lt;/a&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  Postmark x Dev.to Challenge by Cheng Sokdara
&lt;/h2&gt;

&lt;h2&gt;
  
  
  What I Built
&lt;/h2&gt;

&lt;p&gt;I built a web application that automates the initial stages of the hiring process by leveraging Next.js and Postmark's inbound email parsing feature. The application receives job application emails, uses an LLM (OpenAI GPT) to intelligently extract relevant information from the email body and any attached resumes (PDF or DOCX), and then stores this structured data in Firebase Firestore. This data, including candidate details, job application specifics, and the original parsed email, is then accessible via a dashboard for easy viewing and management.&lt;/p&gt;

&lt;h2&gt;
  
  
  Demo
&lt;/h2&gt;

&lt;p&gt;You can try out the live demo here:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://postmark-devto-chengsokdara.vercel.app" rel="noopener noreferrer"&gt;https://postmark-devto-chengsokdara.vercel.app&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Faxwbaf7dzzkg087f0m1h.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Faxwbaf7dzzkg087f0m1h.png" alt="Dashboard with webhook URL" width="800" height="362"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fjtaurlz2vqbtwfxwwttz.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fjtaurlz2vqbtwfxwwttz.png" alt="Job application table page" width="800" height="362"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fxhnmsqqvn79x3xglgei0.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fxhnmsqqvn79x3xglgei0.png" alt="Job application details page" width="800" height="362"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Ft2iz8b399wd34vmfpbti.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Ft2iz8b399wd34vmfpbti.png" alt="Dashboard on mobile" width="362" height="781"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fofkni6atd513mesjefd9.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fofkni6atd513mesjefd9.png" alt="Parsed email table page on mobile" width="364" height="787"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Testing Instructions:&lt;/strong&gt;&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt; Navigate to the demo application and log in using a Google account.&lt;/li&gt;
&lt;li&gt; Once on the dashboard, you'll need to provide a username and a disposable OpenAI API key. This key is used securely on the server-side to process the parsed emails with the LLM.&lt;/li&gt;
&lt;li&gt; After submitting the form, a unique webhook URL will be generated for you.&lt;/li&gt;
&lt;li&gt; Copy this webhook URL.&lt;/li&gt;
&lt;li&gt; Go to your Postmark account, navigate to your inbound email settings, and paste this webhook URL. Save the changes.&lt;/li&gt;
&lt;li&gt; Now, using any email client, compose a job application email (you can attach a resume in PDF or DOCX format) and send it to your Postmark inbound email address.&lt;/li&gt;
&lt;li&gt; Wait a few seconds for the processing to complete.&lt;/li&gt;
&lt;li&gt; Refresh the dashboard in the web app or navigate to the "Applications," "Candidates," or "Emails" pages to see the parsed data.&lt;/li&gt;
&lt;/ol&gt;

&lt;h2&gt;
  
  
  Code Repository
&lt;/h2&gt;

&lt;p&gt;The complete source code is available on GitHub:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://github.com/chengsokdara/postmark-devto-chengsokdara" rel="noopener noreferrer"&gt;https://github.com/chengsokdara/postmark-devto-chengsokdara&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  How I Built It
&lt;/h2&gt;

&lt;p&gt;I developed this project from scratch with the help of ChatGPT and Grok. This involved writing original utility functions and a few custom UI components.&lt;/p&gt;

&lt;p&gt;The core process flow is as follows:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt; Postmark receives an inbound job application email and parses it, providing a JSON representation.&lt;/li&gt;
&lt;li&gt; My application ingests this JSON. If a resume (PDF or DOCX) is attached, it's parsed using &lt;code&gt;pdf2json&lt;/code&gt; for PDFs or &lt;code&gt;mammoth&lt;/code&gt; for DOCX files.&lt;/li&gt;
&lt;li&gt; The combined data (parsed email content and parsed resume text) is then sent to the OpenAI GPT LLM.&lt;/li&gt;
&lt;li&gt; The LLM processes this information, extracting key details and structuring them.&lt;/li&gt;
&lt;li&gt; This structured data, which includes candidate information, job application details, and the original parsed email, is then saved to Firebase Firestore.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;My experience with Postmark's inbound parsing was straightforward; the JSON output was easy to work with and integrate into the application flow.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Tech Stack:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Framework:&lt;/strong&gt; Next.js (App Router) with TypeScript&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Styling:&lt;/strong&gt; Tailwind CSS &amp;amp; Daisy UI&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Database:&lt;/strong&gt; Firebase Firestore&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Authentication:&lt;/strong&gt; Firebase Auth&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;State Management (Global Toast):&lt;/strong&gt; Zustand&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;File Parsing:&lt;/strong&gt; &lt;code&gt;pdf2json&lt;/code&gt; (for PDFs), &lt;code&gt;mammoth&lt;/code&gt; (for DOCX)&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Validation:&lt;/strong&gt; Zod&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;LLM:&lt;/strong&gt; OpenAI GPT-3.5 (or your preferred model)&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Icons:&lt;/strong&gt; Heroicons&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Email Parsing Service:&lt;/strong&gt; Postmark&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Team Submissions
&lt;/h2&gt;

&lt;p&gt;&lt;a href="https://dev.to/chengsokdara"&gt;@chengsokdara&lt;/a&gt;&lt;/p&gt;




&lt;p&gt;Contact me for web or mobile app development using React or React Native&lt;br&gt;
&lt;a href="https://chengsokdara.github.io" rel="noopener noreferrer"&gt;https://chengsokdara.github.io&lt;/a&gt;&lt;/p&gt;

</description>
      <category>devchallenge</category>
      <category>postmarkchallenge</category>
      <category>webdev</category>
      <category>api</category>
    </item>
  </channel>
</rss>
