
Whisper Transcription
- 700 installs
- 145 repo stars
- Updated April 2, 2026
- guia-matthieu/clawfu-skills
whisper-transcription is a Claude Code skill that runs local OpenAI Whisper transcription via a Python CLI for developers who need TXT, SRT, VTT, or JSON transcripts from audio and video without cloud upload APIs.
About
whisper-transcription is an automation skill from guia-matthieu/clawfu-skills with 501 installs that wraps OpenAI Whisper in a bundled Python CLI (scripts/main.py). Developers install openai-whisper, torch, ffmpeg-python, and click, then run single-file or batch jobs with model sizes from tiny through large and export TXT, SRT, VTT, or JSON. The skill guides model selection tradeoffs and supports timestamp extraction plus translation workflows when ffmpeg is present. Reach for whisper-transcription when coding agents must convert user interviews, standups, podcasts, or screen recordings into searchable text inside Cursor or Claude Code without sending media to third-party APIs.
- Local-first Whisper transcription using OpenAI-compatible models
- Supports multiple Whisper model variants for speed vs accuracy tradeoffs
- Direct integration with Claude, Cursor and other agent coding tools
- Outputs clean markdown transcripts with timestamps
- 501 developers have installed this skill from the Clawfu collection
Whisper Transcription by the numbers
- 700 all-time installs (skills.sh)
- Ranked #1,428 of 16,546 AI & Agent Building skills by installs in the Skillselion catalog
- Data as of Aug 3, 2026 (Skillselion catalog sync)
npx skills add https://github.com/guia-matthieu/clawfu-skills --skill whisper-transcriptionAdd your badge
Show developers this skill is listed on Skillselion. Paste this into your README.
| Installs | 700 |
|---|---|
| repo stars | ★ 145 |
| Last updated | April 2, 2026 |
| Repository | guia-matthieu/clawfu-skills ↗ |
How do you transcribe local audio with Whisper in agents?
Convert audio recordings, user interviews, or meeting notes into accurate text inside their AI coding workflow.
Who is it for?
Developers who batch-transcribe local recordings inside AI coding agents and want offline Whisper output in multiple subtitle formats.
Skip if: Developers who only need hosted speech-to-text APIs without installing ffmpeg, PyTorch, or a local Whisper runtime.
When should I use this skill?
A developer asks to transcribe audio, video, podcasts, or meeting recordings to text, SRT, or VTT inside an agent session.
What you get
Plain-text, SRT, VTT, or JSON transcript files with optional timestamps from local audio or video inputs.
- transcript.txt
- subtitles.srt
- captions.vtt
By the numbers
- 501 installs on skills.sh
- Supports 4 output formats: TXT, SRT, VTT, JSON
- Whisper model guide covers tiny through large tiers
Files
Whisper Transcription
Transcribe any audio or video to text using OpenAI's Whisper model - the same technology powering ChatGPT voice features.
When to Use This Skill
- Podcast repurposing - Convert episodes to blog posts, show notes, social snippets
- Video subtitles - Generate SRT/VTT files for YouTube, social media
- Interview extraction - Pull quotes and insights from recorded calls
- Content audit - Make audio/video libraries searchable
- Translation - Transcribe and translate foreign language content
What Claude Does vs What You Decide
| Claude Does | You Decide |
|---|---|
| Structures production workflow | Final creative direction |
| Suggests technical approaches | Equipment and tool choices |
| Creates templates and checklists | Quality standards |
| Identifies best practices | Brand/voice decisions |
| Generates script outlines | Final script approval |
Dependencies
pip install openai-whisper torch ffmpeg-python click
# Also requires ffmpeg installed on system
# macOS: brew install ffmpeg
# Ubuntu: sudo apt install ffmpegCommands
Transcribe Single File
python scripts/main.py transcribe audio.mp3 --model medium --output transcript.txt
python scripts/main.py transcribe video.mp4 --format srt --output subtitles.srtBatch Transcription
python scripts/main.py batch ./recordings/ --format txt --output ./transcripts/Transcribe + Translate
python scripts/main.py translate foreign-audio.mp3 --to enExtract Timestamps
python scripts/main.py timestamps podcast.mp3 --format jsonExamples
Example 1: Podcast to Blog Post
# Transcribe 1-hour podcast
python scripts/main.py transcribe episode-42.mp3 --model medium
# Output: episode-42.txt (full transcript with timestamps)
# Processing time: ~5 min for 1 hour audio on M1 MacExample 2: YouTube Subtitles
# Generate SRT for video upload
python scripts/main.py transcribe marketing-video.mp4 --format srt
# Output: marketing-video.srt
# Upload directly to YouTube/VimeoExample 3: Batch Process Interview Library
# Transcribe all recordings in folder
python scripts/main.py batch ./customer-interviews/ --model small --format txt
# Output: ./customer-interviews/*.txt (one per audio file)Model Selection Guide
| Model | Speed | Accuracy | VRAM | Best For |
|---|---|---|---|---|
tiny | Fastest | ~70% | 1GB | Quick drafts, short clips |
base | Fast | ~80% | 1GB | Social media clips |
small | Medium | ~85% | 2GB | Podcasts, interviews |
medium | Slow | ~90% | 5GB | Professional transcripts |
large | Slowest | ~95% | 10GB | Critical accuracy needs |
Recommendation: Start with small for most marketing content. Use medium for client deliverables.
Output Formats
| Format | Extension | Use Case |
|---|---|---|
txt | .txt | Blog posts, analysis |
srt | .srt | Video subtitles (YouTube) |
vtt | .vtt | Web video subtitles |
json | .json | Programmatic access |
tsv | .tsv | Spreadsheet analysis |
Performance Tips
1. GPU acceleration - 10x faster with CUDA GPU 2. Audio extraction - Script auto-extracts audio from video 3. Chunking - Long files auto-split for memory efficiency 4. Language detection - Automatic, or specify with --language
Skill Boundaries
What This Skill Does Well
- Structuring audio production workflows
- Providing technical guidance
- Creating quality checklists
- Suggesting creative approaches
What This Skill Cannot Do
- Replace audio engineering expertise
- Make subjective creative decisions
- Access or edit audio files directly
- Guarantee commercial success
Related Skills
- video-processing - Extract audio from video
- youtube-downloader - Download videos to transcribe
- content-repurposer - Transform transcripts to content
- podcast-production - Create podcasts
Skill Metadata
- Mode: cyborg
category: automation
subcategory: audio-processing
dependencies: [openai-whisper, torch, ffmpeg-python]
difficulty: beginner
time_saved: 10+ hours/week#!/usr/bin/env python3
"""
Whisper Transcription - Audio/Video to Text using OpenAI Whisper.
Usage:
python main.py transcribe audio.mp3 --model medium
python main.py batch ./recordings/ --format srt
python main.py translate foreign.mp3 --to en
"""
import click
from pathlib import Path
from typing import Optional
import json
def check_whisper():
"""Check if whisper is installed."""
try:
import whisper # noqa: F401
return True
except ImportError:
return False
def get_model(model_name: str):
"""Load whisper model."""
import whisper
click.echo(f" Loading model '{model_name}'...")
return whisper.load_model(model_name)
def format_timestamp(seconds: float) -> str:
"""Convert seconds to SRT timestamp format."""
hours = int(seconds // 3600)
minutes = int((seconds % 3600) // 60)
secs = int(seconds % 60)
millis = int((seconds % 1) * 1000)
return f"{hours:02d}:{minutes:02d}:{secs:02d},{millis:03d}"
def format_vtt_timestamp(seconds: float) -> str:
"""Convert seconds to VTT timestamp format."""
hours = int(seconds // 3600)
minutes = int((seconds % 3600) // 60)
secs = int(seconds % 60)
millis = int((seconds % 1) * 1000)
return f"{hours:02d}:{minutes:02d}:{secs:02d}.{millis:03d}"
def write_srt(segments: list, output_path: Path):
"""Write segments to SRT format."""
with open(output_path, 'w', encoding='utf-8') as f:
for i, seg in enumerate(segments, 1):
start = format_timestamp(seg['start'])
end = format_timestamp(seg['end'])
text = seg['text'].strip()
f.write(f"{i}\n{start} --> {end}\n{text}\n\n")
def write_vtt(segments: list, output_path: Path):
"""Write segments to VTT format."""
with open(output_path, 'w', encoding='utf-8') as f:
f.write("WEBVTT\n\n")
for i, seg in enumerate(segments, 1):
start = format_vtt_timestamp(seg['start'])
end = format_vtt_timestamp(seg['end'])
text = seg['text'].strip()
f.write(f"{i}\n{start} --> {end}\n{text}\n\n")
def write_txt(result: dict, output_path: Path, include_timestamps: bool = False):
"""Write transcription to text file."""
with open(output_path, 'w', encoding='utf-8') as f:
if include_timestamps:
for seg in result['segments']:
start = format_timestamp(seg['start']).split(',')[0]
f.write(f"[{start}] {seg['text'].strip()}\n")
else:
f.write(result['text'])
@click.group()
def cli():
"""Whisper Transcription - Audio/Video to Text."""
if not check_whisper():
click.echo("Error: openai-whisper not installed")
click.echo("Run: pip install openai-whisper torch")
raise SystemExit(1)
@cli.command()
@click.argument('file', type=click.Path(exists=True))
@click.option('--model', '-m', default='small',
type=click.Choice(['tiny', 'base', 'small', 'medium', 'large']),
help='Whisper model size')
@click.option('--format', '-f', 'output_format', default='txt',
type=click.Choice(['txt', 'srt', 'vtt', 'json', 'tsv']),
help='Output format')
@click.option('--output', '-o', type=click.Path(), help='Output file path')
@click.option('--language', '-l', help='Source language (auto-detected if not specified)')
@click.option('--timestamps', is_flag=True, help='Include timestamps in txt output')
def transcribe(file: str, model: str, output_format: str, output: Optional[str],
language: Optional[str], timestamps: bool):
"""Transcribe audio or video file to text."""
input_path = Path(file)
click.echo("\n Whisper Transcription")
click.echo(" " + "=" * 40)
click.echo(f" Input: {input_path.name}")
click.echo(f" Model: {model}")
click.echo(f" Format: {output_format}")
# Load model
whisper_model = get_model(model)
# Transcribe
click.echo(" Transcribing...")
options = {}
if language:
options['language'] = language
result = whisper_model.transcribe(str(input_path), **options)
# Determine output path
if output:
output_path = Path(output)
else:
output_path = input_path.with_suffix(f'.{output_format}')
# Write output
click.echo(f" Writing: {output_path.name}")
if output_format == 'txt':
write_txt(result, output_path, timestamps)
elif output_format == 'srt':
write_srt(result['segments'], output_path)
elif output_format == 'vtt':
write_vtt(result['segments'], output_path)
elif output_format == 'json':
with open(output_path, 'w', encoding='utf-8') as f:
json.dump(result, f, indent=2, ensure_ascii=False)
elif output_format == 'tsv':
with open(output_path, 'w', encoding='utf-8') as f:
f.write("start\tend\ttext\n")
for seg in result['segments']:
f.write(f"{seg['start']:.2f}\t{seg['end']:.2f}\t{seg['text'].strip()}\n")
click.echo("\n " + "-" * 40)
click.echo(f" [Done] Transcribed {input_path.name}")
click.echo(f" Output: {output_path}")
click.echo(f" Language detected: {result.get('language', 'unknown')}")
# Show preview
preview = result['text'][:200].strip()
click.echo(f"\n Preview:\n {preview}...")
@cli.command()
@click.argument('folder', type=click.Path(exists=True))
@click.option('--model', '-m', default='small',
type=click.Choice(['tiny', 'base', 'small', 'medium', 'large']))
@click.option('--format', '-f', 'output_format', default='txt',
type=click.Choice(['txt', 'srt', 'vtt', 'json']))
@click.option('--output', '-o', type=click.Path(), help='Output directory')
def batch(folder: str, model: str, output_format: str, output: Optional[str]):
"""Batch transcribe all audio/video files in folder."""
input_dir = Path(folder)
output_dir = Path(output) if output else input_dir
output_dir.mkdir(parents=True, exist_ok=True)
# Find audio/video files
extensions = {'.mp3', '.wav', '.m4a', '.mp4', '.mkv', '.webm', '.ogg', '.flac'}
files = [f for f in input_dir.iterdir() if f.suffix.lower() in extensions]
if not files:
click.echo(f"No audio/video files found in {folder}")
return
click.echo("\n Batch Transcription")
click.echo(" " + "=" * 40)
click.echo(f" Found {len(files)} files")
click.echo(f" Model: {model}")
whisper_model = get_model(model)
for i, file_path in enumerate(files, 1):
click.echo(f"\n [{i}/{len(files)}] {file_path.name}")
result = whisper_model.transcribe(str(file_path))
output_path = output_dir / file_path.with_suffix(f'.{output_format}').name
if output_format == 'txt':
write_txt(result, output_path)
elif output_format == 'srt':
write_srt(result['segments'], output_path)
elif output_format == 'vtt':
write_vtt(result['segments'], output_path)
elif output_format == 'json':
with open(output_path, 'w', encoding='utf-8') as f:
json.dump(result, f, indent=2, ensure_ascii=False)
click.echo(f" -> {output_path.name}")
click.echo(f"\n [Done] Transcribed {len(files)} files")
@cli.command()
@click.argument('file', type=click.Path(exists=True))
@click.option('--to', '-t', 'target_lang', default='en', help='Target language')
@click.option('--model', '-m', default='small',
type=click.Choice(['tiny', 'base', 'small', 'medium', 'large']))
@click.option('--output', '-o', type=click.Path(), help='Output file path')
def translate(file: str, target_lang: str, model: str, output: Optional[str]):
"""Transcribe and translate audio to target language."""
input_path = Path(file)
click.echo(f"\n Translate to {target_lang}")
click.echo(" " + "=" * 40)
whisper_model = get_model(model)
click.echo(" Transcribing and translating...")
result = whisper_model.transcribe(str(input_path), task='translate')
output_path = Path(output) if output else input_path.with_suffix(f'.{target_lang}.txt')
with open(output_path, 'w', encoding='utf-8') as f:
f.write(result['text'])
click.echo(f"\n [Done] Translated to {target_lang}")
click.echo(f" Output: {output_path}")
@cli.command()
@click.argument('file', type=click.Path(exists=True))
@click.option('--model', '-m', default='small',
type=click.Choice(['tiny', 'base', 'small', 'medium', 'large']))
@click.option('--format', '-f', 'output_format', default='json',
type=click.Choice(['json', 'txt']))
def timestamps(file: str, model: str, output_format: str):
"""Extract timestamps with text segments."""
input_path = Path(file)
click.echo("\n Extract Timestamps")
click.echo(" " + "=" * 40)
whisper_model = get_model(model)
result = whisper_model.transcribe(str(input_path))
segments = []
for seg in result['segments']:
segments.append({
'start': seg['start'],
'end': seg['end'],
'start_formatted': format_timestamp(seg['start']).split(',')[0],
'end_formatted': format_timestamp(seg['end']).split(',')[0],
'text': seg['text'].strip()
})
output_path = input_path.with_suffix('.timestamps.' + output_format)
if output_format == 'json':
with open(output_path, 'w', encoding='utf-8') as f:
json.dump(segments, f, indent=2, ensure_ascii=False)
else:
with open(output_path, 'w', encoding='utf-8') as f:
for seg in segments:
f.write(f"[{seg['start_formatted']} - {seg['end_formatted']}]\n")
f.write(f"{seg['text']}\n\n")
click.echo(f"\n [Done] Extracted {len(segments)} segments")
click.echo(f" Output: {output_path}")
if __name__ == "__main__":
cli()
openai-whisper>=20231117
torch>=2.0.0
ffmpeg-python>=0.2.0
click>=8.0.0
Related skills
How it compares
Pick whisper-transcription when local offline Whisper with SRT/VTT export matters more than a hosted speech API with zero Python setup.
FAQ
What output formats does whisper-transcription support?
whisper-transcription exports transcripts as TXT, SRT, VTT, or JSON via scripts/main.py flags such as --format srt and --output. Developers pick a Whisper model from tiny through large depending on speed versus accuracy needs.
What do you need installed to run whisper-transcription?
whisper-transcription requires ffmpeg on the system plus Python packages openai-whisper, torch, ffmpeg-python, and click from requirements.txt. Without ffmpeg the CLI cannot decode most audio and video inputs.
Can whisper-transcription process multiple files at once?
whisper-transcription documents batch transcription flows in SKILL.md so agents can loop local media through scripts/main.py instead of one-off single-file commands, keeping subtitle format consistent across a folder.