Auto-Generate Subtitles (SRT & VTT) from Audio or Video with FunASR

You don't need a cloud service or a paid API to subtitle a video. FunASR turns speech into timestamped SRT or VTT subtitles locally and for free, and can even label speakers. It's especially strong on Chinese and supports five SenseVoiceSmall languages and 31 Fun-ASR-MLT-Nano languages. Every command and snippet below is tested.

Step 1 (video): extract the audio

If your source is a video, pull out 16 kHz mono audio (FunASR's standard input) with ffmpeg:

ffmpeg -i video.mp4 -ar 16000 -ac 1 audio.wav

For audio files (wav/mp3/m4a, ...) skip this step.

Fastest: one command to SRT

pip install -U funasr
funasr audio.wav -f srt -o ./subs

Writes a standard SRT file at ./subs/audio.srt with real, usable timestamps:

1
00:00:00,000 --> 00:00:05,546
欢迎大家来体验达摩院推出的语音识别模型   (the Chinese sample)

Add --spk to split cues by speaker (great for interviews and meetings):

funasr meeting.wav --spk -f srt -o ./subs

Python: emit SRT and VTT together (with speakers)

When you need more control — e.g. a web-friendly VTT as well, or a custom speaker prefix — build subtitles directly from sentence_info in the result:

from funasr import AutoModel
from funasr.utils.postprocess_utils import rich_transcription_postprocess

model = AutoModel(model="iic/SenseVoiceSmall", vad_model="fsmn-vad", spk_model="cam++", device="cuda")
res = model.generate(input="audio.wav")
segments = res[0]["sentence_info"]   # each has start/end (ms), spk, sentence

def ts(ms, sep):                     # ms -> HH:MM:SS,mmm  (SRT uses "," / VTT uses ".")
    h, mm, ss, mmm = ms//3600000, (ms%3600000)//60000, (ms%60000)//1000, ms%1000
    return "%02d:%02d:%02d%s%03d" % (h, mm, ss, sep, mmm)

with open("subs.srt", "w", encoding="utf-8") as f:
    for i, s in enumerate(segments):
        text = rich_transcription_postprocess(s["sentence"])
        f.write("%d\n%s --> %s\nSpeaker %s: %s\n\n" % (i+1, ts(s["start"], ","), ts(s["end"], ","), s["spk"], text))

with open("subs.vtt", "w", encoding="utf-8") as f:
    f.write("WEBVTT\n\n")
    for s in segments:
        text = rich_transcription_postprocess(s["sentence"])
        f.write("%s --> %s\n<v Speaker %s>%s\n\n" % (ts(s["start"], "."), ts(s["end"], "."), s["spk"], text))

Tested output (SRT):

1
00:00:00,610 --> 00:00:05,530
Speaker 0: 欢迎大家来体验达摩院推出的语音识别模型

Always run rich_transcription_postprocess to strip SenseVoice tags like <|zh|>, otherwise they leak into your subtitles.

Last (optional): burn subtitles into the video

ffmpeg -i video.mp4 -vf subtitles=subs.srt output.mp4

Why use FunASR for subtitles

FunASR is Tongyi Lab's open-source, industrial-grade speech recognition toolkit.

Star FunASR on GitHub ★

Related posts