{"id":54,"date":"2025-04-06T21:05:00","date_gmt":"2025-04-06T18:05:00","guid":{"rendered":"https:\/\/fsaeed.blog\/?p=54"},"modified":"2026-10-31T00:18:52","modified_gmt":"2026-10-30T21:18:52","slug":"free-voice-note-transcription-with-whisper","status":"publish","type":"post","link":"https:\/\/fsaeed.blog\/index.php\/2025\/04\/06\/free-voice-note-transcription-with-whisper\/","title":{"rendered":"Free Voice-Note Transcription on Your Own Machine with Whisper"},"content":{"rendered":"\n<p class=\"wp-block-paragraph\">Hello, tech enthusiasts! \ud83d\udc4b<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">Your colleague sends you a five-minute voice note. You are in a meeting and cannot listen. Later, you need to find what they said about the invoice deadline, and you have to play it all again.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">What if every voice note became text? You could read it in 20 seconds, search it, and copy it into a report.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">Today we will do that with <strong>Whisper<\/strong>, a free speech-to-text model. The best part: it runs on <strong>your own computer<\/strong>. Your audio never leaves your machine. For business calls and private messages, that is a big win.<\/p>\n\n\n\n<h3 class=\"wp-block-heading\">What you need<\/h3>\n\n\n\n<ul class=\"wp-block-list\">\n<li>Python 3.9 or newer (<a href=\"https:\/\/www.python.org\">https:\/\/www.python.org<\/a>)<\/li>\n\n\n<li>ffmpeg, a free tool for audio files (<a href=\"https:\/\/ffmpeg.org\">https:\/\/ffmpeg.org<\/a>)<\/li>\n\n\n<li>An audio file, for example <code>voice_note.ogg<\/code> or <code>meeting.mp3<\/code><\/li>\n\n\n<li>A normal laptop is enough. A graphics card makes it faster, but it is not required.<\/li>\n\n<\/ul>\n\n\n\n<h3 class=\"wp-block-heading\">Step 1: Install ffmpeg<\/h3>\n\n\n\n<p class=\"wp-block-paragraph\"><strong>ffmpeg<\/strong> is like a universal translator for audio and video formats. Install it:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code># Ubuntu \/ Debian\nsudo apt install ffmpeg\n\n# Mac with Homebrew\nbrew install ffmpeg\n\n# Windows with winget\nwinget install ffmpeg<\/code><\/pre>\n\n\n\n<p class=\"wp-block-paragraph\">Check that it works with <code>ffmpeg -version<\/code>.<\/p>\n\n\n\n<h3 class=\"wp-block-heading\">Step 2: Install faster-whisper<\/h3>\n\n\n\n<p class=\"wp-block-paragraph\">There are two popular versions of Whisper for Python. The original is <code>openai-whisper<\/code>. We will use <strong>faster-whisper<\/strong>. It gives the same quality, but it runs faster and uses less memory on a normal computer.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">It is good practice to use a <strong>virtual environment<\/strong>, a private box for this project&#8217;s libraries:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>python -m venv whisper-env\n# Windows: whisper-env\\Scripts\\activate\nsource whisper-env\/bin\/activate\npip install faster-whisper<\/code><\/pre>\n\n\n\n<h3 class=\"wp-block-heading\">Step 3: Transcribe your first file<\/h3>\n\n\n\n<p class=\"wp-block-paragraph\">Create a file named <code>transcribe.py<\/code>:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>from faster_whisper import WhisperModel\n\n# \"small\" is a good balance of speed and accuracy on a laptop\nmodel = WhisperModel(\"small\", device=\"cpu\", compute_type=\"int8\")\n\nsegments, info = model.transcribe(\"voice_note.ogg\")\nprint(f\"Detected language: {info.language}\")\n\nfor segment in segments:\n    print(segment.text.strip())<\/code><\/pre>\n\n\n\n<p class=\"wp-block-paragraph\">Run it:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>python transcribe.py<\/code><\/pre>\n\n\n\n<p class=\"wp-block-paragraph\">The first time, it downloads the model, so you need internet once. After that, everything works offline.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">A <strong>model<\/strong> is the &#8220;brain&#8221; that knows how to turn sound into words. <code>compute_type=\"int8\"<\/code> makes the model lighter so it runs well on a normal processor.<\/p>\n\n\n\n<h3 class=\"wp-block-heading\">Step 4: Choose the right model size<\/h3>\n\n\n\n<p class=\"wp-block-paragraph\">Whisper comes in several sizes. Bigger is more accurate, but slower:<\/p>\n\n\n\n<ul class=\"wp-block-list\">\n<li><code>tiny<\/code> and <code>base<\/code>: very fast, fine for clear English speech.<\/li>\n\n\n<li><code>small<\/code>: a good default for most voice notes.<\/li>\n\n\n<li><code>medium<\/code>: better for noisy audio and for languages like Arabic.<\/li>\n\n\n<li><code>large-v3<\/code>: the most accurate, but slow without a graphics card.<\/li>\n\n<\/ul>\n\n\n\n<p class=\"wp-block-paragraph\">Start with <code>small<\/code>. If the text has too many mistakes, try <code>medium<\/code>.<\/p>\n\n\n\n<h3 class=\"wp-block-heading\">Step 5: Set the language<\/h3>\n\n\n\n<p class=\"wp-block-paragraph\">Whisper guesses the language from the first 30 seconds. Usually it is right. But for short notes or mixed languages, it can guess wrong. You can tell it directly with a language code:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>segments, info = model.transcribe(\"voice_note.ogg\", language=\"ar\")  # Arabic\n# English is \"en\", French is \"fr\", and so on<\/code><\/pre>\n\n\n\n<h3 class=\"wp-block-heading\">Step 6: Save the text to a file<\/h3>\n\n\n\n<p class=\"wp-block-paragraph\">Printing is nice, but a text file is more useful. This version saves each line with its time, so you can jump to the right place in the audio:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>from pathlib import Path\nfrom faster_whisper import WhisperModel\n\nmodel = WhisperModel(\"small\", device=\"cpu\", compute_type=\"int8\")\n\ndef transcribe_to_file(audio_path, language=None):\n    segments, info = model.transcribe(audio_path, language=language)\n    out_path = Path(audio_path).with_suffix(\".txt\")\n    with open(out_path, \"w\", encoding=\"utf-8\") as f:\n        for s in segments:\n            # Time as minutes:seconds, then the text\n            start = f\"{int(s.start \/\/ 60):02d}:{int(s.start % 60):02d}\"\n            f.write(f\"[{start}] {s.text.strip()}\\n\")\n    print(f\"Saved {out_path}\")\n\n# Transcribe every audio file in a \"VoiceNotes\" folder\nfor audio in Path(\"VoiceNotes\").glob(\"*.*\"):\n    if audio.suffix.lower() in {\".ogg\", \".mp3\", \".m4a\", \".wav\", \".opus\"}:\n        transcribe_to_file(str(audio))<\/code><\/pre>\n\n\n\n<p class=\"wp-block-paragraph\">Now <code>VoiceNotes\/voice_note.ogg<\/code> gets a partner file, <code>VoiceNotes\/voice_note.txt<\/code>.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">Prefer the original version? The <code>openai-whisper<\/code> package has a simple command line tool that does the same thing:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>pip install openai-whisper\nwhisper voice_note.ogg --model small --language ar --output_format txt<\/code><\/pre>\n\n\n\n<h3 class=\"wp-block-heading\">Common problems<\/h3>\n\n\n\n<ul class=\"wp-block-list\">\n<li><strong>Very slow<\/strong> \u2192 Use a smaller model, or keep <code>compute_type=\"int8\"<\/code>. Long recordings simply take time on a laptop.<\/li>\n\n\n<li><strong>Text in the wrong language, or translated<\/strong> \u2192 Set <code>language=<\/code> yourself.<\/li>\n\n\n<li><strong>Errors about CUDA or the GPU<\/strong> \u2192 Keep <code>device=\"cpu\"<\/code>. The GPU needs extra NVIDIA libraries.<\/li>\n\n\n<li><strong>&#8220;No such file or directory: ffmpeg&#8221;<\/strong> (openai-whisper) \u2192 ffmpeg is not installed or not on your PATH. Repeat Step 1, then open a new terminal.<\/li>\n\n<\/ul>\n\n\n\n<h3 class=\"wp-block-heading\">Wrap-up<\/h3>\n\n\n\n<p class=\"wp-block-paragraph\">With about 20 lines of Python, you have a private, free transcription tool. No upload, no monthly fee, and no limit on minutes.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">Next idea: combine this with a search script. Transcribe all your voice notes once, then search the text files for a word like &#8220;deadline&#8221; to find the right message in seconds. \ud83c\udf99\ufe0f<\/p>\n","protected":false},"excerpt":{"rendered":"<p>Turn voice notes into text for free on your own computer, without sending your audio to anyone.<\/p>\n","protected":false},"author":1,"featured_media":0,"comment_status":"closed","ping_status":"closed","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[1],"tags":[40,41,12,39,38],"class_list":["post-54","post","type-post","status-publish","format-standard","hentry","category-uncategorized","tag-audio","tag-privacy","tag-python","tag-transcription","tag-whisper"],"_links":{"self":[{"href":"https:\/\/fsaeed.blog\/index.php\/wp-json\/wp\/v2\/posts\/54","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/fsaeed.blog\/index.php\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/fsaeed.blog\/index.php\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/fsaeed.blog\/index.php\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/fsaeed.blog\/index.php\/wp-json\/wp\/v2\/comments?post=54"}],"version-history":[{"count":1,"href":"https:\/\/fsaeed.blog\/index.php\/wp-json\/wp\/v2\/posts\/54\/revisions"}],"predecessor-version":[{"id":79,"href":"https:\/\/fsaeed.blog\/index.php\/wp-json\/wp\/v2\/posts\/54\/revisions\/79"}],"wp:attachment":[{"href":"https:\/\/fsaeed.blog\/index.php\/wp-json\/wp\/v2\/media?parent=54"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/fsaeed.blog\/index.php\/wp-json\/wp\/v2\/categories?post=54"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/fsaeed.blog\/index.php\/wp-json\/wp\/v2\/tags?post=54"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}