mirror of
https://github.com/modelscope/FunASR.git
synced 2026-10-12 02:19:18 +00:00
* docs: design product deployment hub * docs(site): plan deployment product hub implementation * feat(site): add deployment evidence registry * feat(site): add deployment recommendation engine * build(site): track reproducible live-site corpus * feat(site): build bilingual deployment product surface * feat(site): add deployment contracts and benchmarks * feat(site): preserve legacy routes and unify navigation * ci(site): validate reproducible product builds * ops(site): add atomic releases and hardened nginx * test(site): add responsive product browser coverage * fix(site): support managed and manual nginx masters * fix(site): make release smoke routes configurable * docs(site): record product hub rollout --------- Co-authored-by: LauraGPT <[email protected]>
144 lines
13 KiB
HTML
144 lines
13 KiB
HTML
<!DOCTYPE html>
|
||
<html lang="en">
|
||
<head>
|
||
<meta charset="utf-8">
|
||
<meta name="viewport" content="width=device-width,initial-scale=1">
|
||
<title>Speech-to-Text with Word/Character-Level Timestamps in Python — Millisecond-Accurate | FunASR Blog</title>
|
||
<meta name="description" content="How to get per-word/character timestamps from speech recognition? FunASR Paraformer emits character-level timestamps natively — every character has [start_ms, end_ms] in a single call. Build word highlighting, click-to-seek, subtitle alignment. With real output and pairing code.">
|
||
<meta name="keywords" content="speech to text with timestamps python, word level timestamps, word timestamps speech recognition, character timestamps, forced alignment, speech recognition timestamps, Paraformer, FunASR, subtitle alignment">
|
||
<link rel="icon" href="/logo.png">
|
||
<meta property="og:title" content="Speech-to-Text with Word/Character-Level Timestamps in Python — Millisecond-Accurate | FunASR Blog">
|
||
<meta property="og:description" content="How to get per-word/character timestamps from speech recognition? FunASR Paraformer emits character-level timestamps natively — every character has [start_ms, end_ms] in a single call. Build word highlighting, click-to-seek, subtitle alignment. With real output and pairing code.">
|
||
<meta property="og:type" content="article">
|
||
<meta property="og:url" content="https://www.funasr.com/en/blog/speech-to-text-timestamps-python.html">
|
||
<meta property="og:image" content="https://www.funasr.com/logo.png">
|
||
<link rel="canonical" href="https://www.funasr.com/en/blog/speech-to-text-timestamps-python.html">
|
||
<link rel="alternate" hreflang="en" href="https://www.funasr.com/en/blog/speech-to-text-timestamps-python.html">
|
||
<link rel="alternate" hreflang="zh" href="https://www.funasr.com/blog/speech-to-text-timestamps-python.html">
|
||
<link rel="alternate" hreflang="x-default" href="https://www.funasr.com/en/blog/speech-to-text-timestamps-python.html">
|
||
<link href="https://fonts.googleapis.com/css2?family=Inter:wght@400;500;600;700;800&display=swap" rel="stylesheet">
|
||
<script type="application/ld+json">
|
||
{"@context":"https://schema.org","@type":"BlogPosting","headline":"Speech-to-Text with Word/Character-Level Timestamps in Python — Millisecond-Accurate | FunASR Blog","description":"How to get per-word/character timestamps from speech recognition? FunASR Paraformer emits character-level timestamps natively — every character has [start_ms, end_ms] in a single call. Build word highlighting, click-to-seek, subtitle alignment. With real output and pairing code.","datePublished":"2026-06-23","dateModified":"2026-06-23","author":{"@type":"Organization","name":"FunASR / Tongyi Lab"},"publisher":{"@type":"Organization","name":"FunASR","logo":{"@type":"ImageObject","url":"https://www.funasr.com/logo.png"}},"mainEntityOfPage":{"@type":"WebPage","@id":"https://www.funasr.com/en/blog/speech-to-text-timestamps-python.html"},"image":"https://www.funasr.com/logo.png"}
|
||
</script>
|
||
<style>:root{--primary:#2563eb;--primary-dark:#1d4ed8;--bg:#fff;--surface:#f8fafc;--border:#e2e8f0;--text:#0f172a;--text-soft:#475569;--text-muted:#94a3b8;--radius:12px}
|
||
*{margin:0;padding:0;box-sizing:border-box}
|
||
body{font-family:'Inter',-apple-system,sans-serif;color:var(--text);line-height:1.7}
|
||
a{color:var(--primary);text-decoration:none}a:hover{text-decoration:underline}
|
||
.container{max-width:800px;margin:0 auto;padding:0 24px}
|
||
.nav{position:fixed;top:0;left:0;right:0;z-index:100;background:rgba(255,255,255,0.9);backdrop-filter:blur(12px);border-bottom:1px solid var(--border);padding:14px 0}
|
||
.nav .container{max-width:1120px;display:flex;align-items:center;gap:24px}
|
||
.nav-logo{font-size:1.2rem;font-weight:800;color:var(--text)}.nav-logo span{color:var(--primary)}
|
||
.nav-links{display:flex;gap:20px;margin-left:auto;flex-wrap:wrap}
|
||
.nav-links a{font-size:0.85rem;font-weight:500;color:var(--text-soft)}
|
||
.nav-btn{padding:7px 16px;background:var(--primary);color:#fff;border-radius:7px;font-size:0.83rem;font-weight:600}
|
||
article{padding:120px 0 80px}
|
||
h1{font-size:2rem;font-weight:800;line-height:1.3;margin-bottom:14px}
|
||
h2{font-size:1.3rem;font-weight:700;margin:36px 0 14px;padding-top:16px;border-top:1px solid var(--border)}
|
||
h3{font-size:1.05rem;font-weight:700;margin:22px 0 10px}
|
||
p{margin-bottom:14px;color:var(--text-soft)}
|
||
ul,ol{margin:0 0 14px 22px;color:var(--text-soft)}li{margin-bottom:6px}
|
||
table{width:100%;border-collapse:collapse;margin:16px 0;font-size:0.86rem}
|
||
th,td{padding:10px 12px;text-align:left;border-bottom:1px solid var(--border)}
|
||
th{font-weight:600;background:var(--surface);font-size:0.78rem;color:var(--text-muted)}
|
||
pre{background:#1e293b;color:#e2e8f0;padding:18px;border-radius:10px;overflow-x:auto;font-size:0.82rem;line-height:1.7;margin:14px 0}
|
||
code{font-family:ui-monospace,Menlo,monospace}
|
||
p code,li code{background:var(--surface);padding:2px 6px;border-radius:5px;font-size:0.85em;color:var(--primary-dark)}
|
||
.post-meta{color:var(--text-muted);font-size:0.85rem;margin-bottom:24px}
|
||
.cta{background:var(--surface);border:1px solid var(--border);border-radius:var(--radius);padding:24px;margin:28px 0;text-align:center}
|
||
.cta a.btn{display:inline-block;padding:10px 24px;background:var(--primary);color:#fff;border-radius:8px;font-weight:600}
|
||
.post-list{list-style:none;margin:0;padding:0}
|
||
.post-list li{margin:0 0 8px}
|
||
.post-card{display:block;border:1px solid var(--border);border-radius:var(--radius);padding:20px 22px;margin-bottom:14px}
|
||
.post-card:hover{border-color:var(--primary);text-decoration:none}
|
||
.post-card h2{border:none;padding:0;margin:0 0 6px;font-size:1.15rem;color:var(--text)}
|
||
.post-card p{margin:0;color:var(--text-soft);font-size:0.9rem}
|
||
.post-card .date{color:var(--text-muted);font-size:0.8rem}
|
||
footer{background:#0f172a;color:#94a3b8;padding:28px 0;text-align:center;font-size:0.8rem}
|
||
footer a{color:#94a3b8}</style>
|
||
</head>
|
||
<body>
|
||
<nav class="nav"><div class="container"><a href="/en/" class="nav-logo">Fun<span>ASR</span></a><div class="nav-links"><a href="/en/#capabilities">Capabilities</a><a href="/en/#usage">How to Use</a><a href="/en/#benchmark">Benchmark</a><a href="/en/#demo">Demo</a><a href="https://modelscope.github.io/FunASR/" target="_blank">Docs</a><a href="/en/quickstart.html">Quickstart</a><a href="/en/models.html">Models</a><a href="/en/ecosystem.html">Ecosystem</a><a href="/en/blog/">Blog</a><a href="/en/vs-whisper.html">vs Whisper</a><a href="/en/donors.html">Donors</a></div><a href="https://www.funasr.com/blog/speech-to-text-timestamps-python.html" style="font-size:0.83rem;font-weight:500;color:var(--text-soft)">中文</a><a href="https://github.com/modelscope/FunASR" target="_blank" class="nav-btn">GitHub ★</a></div></nav>
|
||
<article><div class="container">
|
||
<h1>Speech-to-Text with Word/Character-Level Timestamps in Python — Millisecond-Accurate</h1>
|
||
<p class="post-meta">2026-06-23 · FunASR Team</p>
|
||
|
||
<p>Many use cases need more than "what was said" — they need to know <strong>when each word was spoken</strong>: karaoke-style highlighting, click-a-word-to-seek transcripts, subtitle alignment, video-editing search. Whisper's word timestamps are bolted on (DTW-based, variable accuracy). <strong>FunASR's Paraformer emits character-level timestamps natively</strong>: every character comes with <code>[start_ms, end_ms]</code> in a single call. Here is real measured output.</p>
|
||
|
||
<h2>Transcribe with timestamps (real output)</h2>
|
||
<pre>pip install funasr
|
||
|
||
from funasr import AutoModel
|
||
|
||
model = AutoModel(model="paraformer-zh", vad_model="fsmn-vad", disable_update=True)
|
||
res = model.generate(input="audio.wav")
|
||
|
||
text = res[0]["text"] # 欢 迎 大 家 来 体 验 ...
|
||
timestamp = res[0]["timestamp"] # [[880, 1120], [1120, 1360], ...] per-character start/end ms</pre>
|
||
<p><code>timestamp</code> is a list of <code>[start_ms, end_ms]</code> pairs, one per character in the text.</p>
|
||
|
||
<h2>Pair characters with timestamps (real)</h2>
|
||
<pre>chars = text.split() # Paraformer's Chinese output is space-separated characters
|
||
for ch, (start, end) in zip(chars, timestamp):
|
||
print(f"{ch} {start}-{end}ms")</pre>
|
||
<p>Actual output:</p>
|
||
<table>
|
||
<tr><th>Char</th><th>Span (ms)</th></tr>
|
||
<tr><td>欢</td><td>880 – 1120</td></tr>
|
||
<tr><td>迎</td><td>1120 – 1360</td></tr>
|
||
<tr><td>大</td><td>1380 – 1540</td></tr>
|
||
<tr><td>家</td><td>1540 – 1780</td></tr>
|
||
<tr><td>来</td><td>1780 – 2020</td></tr>
|
||
<tr><td>体</td><td>2020 – 2180</td></tr>
|
||
<tr><td>验</td><td>2180 – 2420</td></tr>
|
||
</table>
|
||
<p>All 19 characters of the sentence get a millisecond-accurate start/end.</p>
|
||
|
||
<h2>What you can build</h2>
|
||
<ul>
|
||
<li><strong>Word highlighting / karaoke</strong>: highlight the character whose span contains the current playback time.</li>
|
||
<li><strong>Click-to-seek transcripts</strong>: clicking a character seeks the audio to its <code>start_ms</code>.</li>
|
||
<li><strong>Precise subtitle alignment</strong>: split and time captions from the timestamps. For full subtitles, see <a href="/en/blog/generate-subtitles-srt-vtt-from-audio-video.html">generating SRT/VTT subtitles</a>.</li>
|
||
<li><strong>Video-edit search</strong>: jump to the exact moment a keyword is spoken.</li>
|
||
</ul>
|
||
|
||
<h2>Why Paraformer for timestamps</h2>
|
||
<table>
|
||
<tr><th></th><th>FunASR Paraformer</th><th>Whisper</th></tr>
|
||
<tr><td>Word/char timestamps</td><td>✅ native, single call</td><td>bolt-on (<code>--word_timestamps</code>, DTW)</td></tr>
|
||
<tr><td>Accuracy</td><td>non-autoregressive + CIF alignment, stable</td><td>implementation-dependent</td></tr>
|
||
<tr><td>Chinese</td><td>character-level, CER 10.18%</td><td>~20%</td></tr>
|
||
<tr><td>License</td><td>open-source, commercial-friendly</td><td>open-source</td></tr>
|
||
</table>
|
||
<p>For higher Chinese accuracy, default to the flagship <a href="/en/blog/which-funasr-model.html">Fun-ASR-Nano</a>; for the full Chinese walkthrough see <a href="/en/blog/chinese-speech-recognition.html">Chinese speech recognition</a>; for long-audio segmentation see <a href="/en/blog/voice-activity-detection-python.html">VAD</a>.</p>
|
||
|
||
<div class="cta"><p><strong>The whole FunASR stack is open-source (MIT)</strong> — character timestamps, ASR, VAD, punctuation, speaker, LLM-ASR (flagship Fun-ASR-Nano), ready to use. If it helps, a GitHub Star supports the project 👇</p><p><a class="btn" href="https://github.com/modelscope/FunASR" target="_blank">⭐ Star FunASR</a></p><p style="margin-top:10px;font-size:0.85rem">Also star:<a href="https://github.com/QwenAudio/SenseVoice" target="_blank">SenseVoice</a> · <a href="https://github.com/QwenAudio/Fun-ASR" target="_blank">Fun-ASR</a> · <a href="https://github.com/modelscope/FunClip" target="_blank">FunClip</a></p></div>
|
||
<!--related-posts-->
|
||
<h2>Related posts</h2>
|
||
<ul class="post-list">
|
||
<li><a href="/en/blog/funasr-vs-whisper-benchmark.html">FunASR vs Whisper Benchmark</a></li>
|
||
<li><a href="/en/blog/sensevoice-deployment-guide.html">SenseVoice Deployment Guide</a></li>
|
||
<li><a href="/en/blog/fun-asr-nano-guide.html">Fun-ASR-Nano Guide</a></li>
|
||
<li><a href="/en/blog/funasr-speaker-diarization.html">Speaker Diarization: Who Spoke When</a></li>
|
||
<li><a href="/en/blog/sensevoice-emotion-language-detection.html">Emotion & Language Detection</a></li>
|
||
<li><a href="/en/blog/funasr-realtime-streaming-asr.html">Real-Time Streaming Speech-to-Text</a></li>
|
||
<li><a href="/en/blog/funasr-transcribe-long-audio.html">Transcribe Long Audio (Hours in One Call)</a></li>
|
||
<li><a href="/en/blog/funasr-cli-transcribe-command-line.html">Transcribe from the Command Line</a></li>
|
||
<li><a href="/en/blog/self-hosted-openai-whisper-api-alternative.html">Self-Hosted OpenAI Whisper API Alternative</a></li>
|
||
<li><a href="/en/blog/generate-subtitles-srt-vtt-from-audio-video.html">Auto-Generate Subtitles (SRT / VTT)</a></li>
|
||
<li><a href="/en/blog/speech-to-text-python-transcribe-audio.html">Speech to Text in Python</a></li>
|
||
<li><a href="/en/blog/funasr-llama-cpp-whisper-cpp-alternative.html">FunASR on llama.cpp (whisper.cpp Alternative)</a></li>
|
||
<li><a href="/en/blog/funasr-vs-faster-whisper-chinese.html">FunASR vs faster-whisper (Chinese/Cantonese)</a></li>
|
||
<li><a href="/en/blog/lightweight-speech-recognition-cpu.html">Lightweight Speech Recognition on CPU</a></li>
|
||
<li><a href="/en/blog/self-hosted-deepgram-assemblyai-alternative.html">Self-Hosted Deepgram/AssemblyAI Alternative</a></li>
|
||
<li><a href="/en/blog/which-funasr-model.html">Which FunASR Model?</a></li>
|
||
<li><a href="/en/blog/cantonese-speech-recognition.html">Cantonese Speech Recognition (SenseVoice)</a></li>
|
||
<li><a href="/en/blog/japanese-speech-recognition.html">Japanese Speech Recognition (SenseVoice)</a></li>
|
||
<li><a href="/en/blog/voice-activity-detection-python.html">Voice Activity Detection in Python</a></li>
|
||
<li><a href="/en/blog/self-hosted-google-aws-azure-speech-to-text.html">Self-Hosted Google/AWS/Azure STT Alternative</a></li>
|
||
<li><a href="/en/blog/chinese-speech-recognition.html">Chinese Speech Recognition in Python</a></li>
|
||
<li><a href="/en/blog/punctuation-restoration-python.html">Punctuation Restoration in Python</a></li>
|
||
</ul>
|
||
</div></article>
|
||
<footer><div class="container">© 2024-2026 Tongyi Lab, Alibaba Group · <a href="https://github.com/modelscope/FunASR/blob/main/LICENSE">MIT License</a></div></footer>
|
||
</body>
|
||
</html> |