SenseVoice-small-onnx语音识别教程:结果时间戳对齐与可视化展示
本文介绍了如何在星图GPU平台上自动化部署sensevoice-small-语音识别-onnx模型(带量化后),并利用其进行语音识别与时间戳对齐。该平台简化了部署流程,用户可快速搭建服务,将音频内容(如会议录音)自动转换为带精确时间戳的文本,便于高效生成字幕或进行内容检索与分析。
SenseVoice-small-onnx语音识别教程:结果时间戳对齐与可视化展示
1. 引言
语音识别技术正在快速融入我们的日常工作流。无论是会议纪要、访谈整理,还是视频字幕生成,将音频内容快速、准确地转化为带时间戳的文本,已经成为一项高频需求。
然而,很多朋友在实际使用语音识别服务时,会遇到一个共同的困扰:识别出来的文字虽然准确,但不知道每句话、每个词在音频中的具体位置。这就好比拿到了一份会议记录,却不知道每段发言对应的是哪个时间点,想要回听核对或者制作字幕时,就变得非常麻烦。
今天,我要分享的就是如何利用 SenseVoice-small-onnx 这个轻量高效的语音识别模型,不仅实现多语言转写,还能精确获取每个识别结果的时间戳信息,并通过可视化方式直观展示。无论你是开发者、内容创作者,还是普通用户,都能通过这篇教程,轻松掌握这项实用技能。
2. 环境准备与快速部署
2.1 系统要求与依赖安装
首先,确保你的系统环境满足以下基本要求:
- Python 3.8 或更高版本
- 至少 2GB 可用内存(用于模型加载和推理)
- 基本的命令行操作能力
接下来,我们安装必要的依赖包。打开终端,执行以下命令:
# 安装核心依赖
pip install funasr-onnx gradio fastapi uvicorn soundfile jieba
# 可选:安装可视化相关库
pip install matplotlib pandas
这里简单解释一下每个包的作用:
funasr-onnx:SenseVoice模型的ONNX推理框架gradio:用于快速构建Web界面fastapi和uvicorn:用于创建REST API服务soundfile:音频文件读取库jieba:中文分词工具(用于更精确的时间戳对齐)matplotlib和pandas:数据可视化和处理
2.2 一键启动语音识别服务
SenseVoice-small-onnx已经提供了完整的服务部署脚本。下载项目文件后,只需要一条命令就能启动服务:
# 进入项目目录
cd sensevoice-small-onnx-quant
# 启动服务(默认端口7860)
python3 app.py --host 0.0.0.0 --port 7860
启动成功后,你会在终端看到类似下面的输出:
INFO: Started server process [12345]
INFO: Waiting for application startup.
INFO: Application startup complete.
INFO: Uvicorn running on http://0.0.0.0:7860 (Press CTRL+C to quit)
现在,打开浏览器访问 http://localhost:7860,就能看到语音识别的Web界面了。
3. 基础概念:什么是时间戳对齐?
在深入实践之前,我们先花几分钟理解一下"时间戳对齐"这个概念。这能帮你更好地理解后续的操作和结果。
3.1 时间戳对齐的核心价值
想象一下这样的场景:你有一段30分钟的会议录音,语音识别服务把它转成了文字。如果没有时间戳,你看到的只是一大段文字。但如果有时间戳对齐,你会看到:
[00:01:23 - 00:01:45] 张三:我们本季度的销售额同比增长了15%
[00:01:46 - 00:02:10] 李四:这个增长主要来自华东地区的新客户
时间戳对齐就是给识别出的每个词、每句话打上"时间标签",告诉你它在音频中的开始时间和结束时间。这带来了几个实实在在的好处:
- 精准定位:快速跳转到音频的任意位置
- 字幕生成:自动生成带时间轴的字幕文件
- 内容检索:根据关键词查找对应的音频片段
- 说话人分析:统计每个人的发言时长和时段
3.2 SenseVoice的时间戳输出格式
SenseVoice-small-onnx模型在识别时,除了返回转写文本,还会返回详细的时间戳信息。这些信息通常以两种格式提供:
格式一:词级别时间戳
{
"text": "今天天气真好",
"words": [
{"word": "今天", "start": 0.0, "end": 0.5},
{"word": "天气", "start": 0.5, "end": 1.0},
{"word": "真好", "start": 1.0, "end": 1.5}
]
}
格式二:句子级别时间戳
{
"text": "今天天气真好。我们出去走走吧。",
"sentences": [
{"text": "今天天气真好", "start": 0.0, "end": 1.5},
{"text": "我们出去走走吧", "start": 2.0, "end": 3.5}
]
}
在实际应用中,我们可以根据需求选择不同的粒度。制作字幕通常用句子级别,而语音分析可能更需要词级别信息。
4. 获取带时间戳的识别结果
现在,我们进入实战环节。我将展示三种获取时间戳信息的方法,从简单到复杂,满足不同场景的需求。
4.1 方法一:使用Web界面(最简单)
对于不熟悉编程的朋友,Web界面是最友好的选择。
- 打开浏览器,访问
http://localhost:7860 - 点击"上传音频"按钮,选择你的音频文件
- 在语言选择中,可以选"auto"(自动检测)或指定语言
- 勾选"输出时间戳"选项
- 点击"转写"按钮
等待几秒钟,你会在右侧看到识别结果。如果勾选了时间戳选项,结果会以带时间标记的格式显示:
[00:00:00.000 - 00:00:01.230] 你好,欢迎使用语音识别服务。
[00:00:01.231 - 00:00:03.450] 这是一个多语言识别演示。
小技巧:对于中文音频,建议同时勾选"使用ITN"(逆文本正则化),这样数字、百分比等会被自动转换,比如"百分之二十"会变成"20%"。
4.2 方法二:调用REST API(适合开发者)
如果你需要在其他程序中集成语音识别功能,API调用是最佳选择。
基础调用示例:
curl -X POST "http://localhost:7860/api/transcribe" \
-F "file=@meeting.wav" \
-F "language=zh" \
-F "output_timestamps=true" \
-F "use_itn=true"
Python代码调用示例:
import requests
import json
# API端点
url = "http://localhost:7860/api/transcribe"
# 准备请求数据
files = {'file': open('audio.wav', 'rb')}
data = {
'language': 'auto',
'output_timestamps': 'true',
'timestamp_level': 'word' # 可选:word(词级)或sentence(句级)
}
# 发送请求
response = requests.post(url, files=files, data=data)
result = response.json()
# 解析结果
if result['success']:
text = result['text']
timestamps = result['timestamps'] # 时间戳信息
print(f"识别文本:{text}")
print(f"时间戳:{json.dumps(timestamps, indent=2, ensure_ascii=False)}")
else:
print(f"识别失败:{result['error']}")
API返回的完整数据结构:
{
"success": true,
"text": "完整的识别文本",
"timestamps": [
{
"text": "第一句话",
"start": 0.0,
"end": 1.5,
"words": [
{"word": "第一", "start": 0.0, "end": 0.5},
{"word": "句话", "start": 0.5, "end": 1.5}
]
}
],
"language": "zh",
"duration": 30.5
}
4.3 方法三:直接使用Python SDK(最灵活)
对于需要深度定制或批量处理的场景,直接使用Python SDK提供了最大的灵活性。
from funasr_onnx import SenseVoiceSmall
import json
# 初始化模型(使用缓存路径)
model_path = "/root/ai-models/danieldong/sensevoice-small-onnx-quant"
model = SenseVoiceSmall(model_path, batch_size=1, quantize=True)
# 识别音频并获取时间戳
audio_files = ["speech.wav"]
results = model(audio_files,
language="auto",
use_itn=True,
return_timestamps=True, # 关键参数:返回时间戳
timestamp_level="word") # 词级别时间戳
# 处理结果
for i, result in enumerate(results):
print(f"音频 {i+1} 识别结果:")
print(f"文本:{result['text']}")
# 提取时间戳信息
if 'timestamps' in result:
print("\n时间戳详情:")
for ts in result['timestamps']:
start_time = ts['start']
end_time = ts['end']
word = ts['word']
print(f" [{start_time:.3f}s - {end_time:.3f}s] {word}")
# 也可以获取句子级别的时间戳
sentences = result.get('sentences', [])
if sentences:
print("\n句子级别时间戳:")
for sent in sentences:
print(f" [{sent['start']:.3f}s - {sent['end']:.3f}s] {sent['text']}")
参数说明:
return_timestamps=True:告诉模型返回时间戳信息timestamp_level="word":指定时间戳粒度,可选"word"或"sentence"batch_size=1:批处理大小,对于带时间戳的任务,建议设为1以获得更准确的时间信息
5. 时间戳数据的可视化展示
获取到时间戳数据后,我们可以用各种方式将其可视化,让结果更加直观易懂。
5.1 生成时间轴字幕文件
字幕文件是最实用的输出格式之一,可以直接用于视频编辑或播放器显示。
生成SRT字幕文件:
def generate_srt(timestamps, output_file="output.srt"):
"""生成SRT格式字幕文件"""
with open(output_file, 'w', encoding='utf-8') as f:
for i, sentence in enumerate(timestamps, 1):
# 转换时间格式(秒 -> 时:分:秒,毫秒)
start_time = format_time(sentence['start'])
end_time = format_time(sentence['end'])
# 写入SRT格式
f.write(f"{i}\n")
f.write(f"{start_time} --> {end_time}\n")
f.write(f"{sentence['text']}\n\n")
def format_time(seconds):
"""将秒数转换为SRT时间格式"""
hours = int(seconds // 3600)
minutes = int((seconds % 3600) // 60)
secs = seconds % 60
return f"{hours:02d}:{minutes:02d}:{secs:06.3f}".replace('.', ',')
# 使用示例
sentences = [
{"text": "欢迎来到今天的会议", "start": 0.0, "end": 2.5},
{"text": "我们首先回顾上季度业绩", "start": 2.5, "end": 5.0},
]
generate_srt(sentences, "meeting_subtitles.srt")
生成的SRT文件内容:
1
00:00:00,000 --> 00:00:02,500
欢迎来到今天的会议
2
00:00:02,500 --> 00:00:05,000
我们首先回顾上季度业绩
生成VTT字幕文件(Web字幕格式):
def generate_vtt(timestamps, output_file="output.vtt"):
"""生成WebVTT格式字幕文件"""
with open(output_file, 'w', encoding='utf-8') as f:
f.write("WEBVTT\n\n")
for i, sentence in enumerate(timestamps, 1):
start_time = format_time_vtt(sentence['start'])
end_time = format_time_vtt(sentence['end'])
f.write(f"{start_time} --> {end_time}\n")
f.write(f"{sentence['text']}\n\n")
def format_time_vtt(seconds):
"""将秒数转换为VTT时间格式"""
hours = int(seconds // 3600)
minutes = int((seconds % 3600) // 60)
secs = seconds % 60
return f"{hours:02d}:{minutes:02d}:{secs:06.3f}"
# 使用方式相同
generate_vtt(sentences, "meeting_subtitles.vtt")
5.2 创建交互式时间轴图表
对于数据分析或演示场景,图表能更直观地展示语音内容的时间分布。
import matplotlib.pyplot as plt
import matplotlib.patches as patches
def plot_speech_timeline(timestamps, title="语音时间轴"):
"""绘制语音时间轴图表"""
fig, ax = plt.subplots(figsize=(12, 6))
# 设置颜色映射(不同句子用不同颜色)
colors = plt.cm.Set3(range(len(timestamps)))
# 绘制每个句子的时间块
for i, sentence in enumerate(timestamps):
start = sentence['start']
duration = sentence['end'] - sentence['start']
text = sentence['text'][:20] + "..." if len(sentence['text']) > 20 else sentence['text']
# 创建矩形块
rect = patches.Rectangle(
(start, i*0.8),
duration, 0.6,
linewidth=1,
edgecolor='black',
facecolor=colors[i],
alpha=0.7
)
ax.add_patch(rect)
# 添加文本标签
ax.text(start + duration/2, i*0.8 + 0.3,
text, ha='center', va='center', fontsize=9)
# 设置图表属性
ax.set_xlabel('时间 (秒)', fontsize=12)
ax.set_ylabel('句子序号', fontsize=12)
ax.set_title(title, fontsize=14)
ax.set_xlim(0, max(ts['end'] for ts in timestamps) + 5)
ax.set_ylim(-0.5, len(timestamps)*0.8)
ax.grid(True, alpha=0.3)
plt.tight_layout()
plt.savefig('speech_timeline.png', dpi=150, bbox_inches='tight')
plt.show()
# 使用示例
timestamps = [
{"text": "开场介绍和欢迎词", "start": 0, "end": 45},
{"text": "第一季度业绩汇报", "start": 45, "end": 180},
{"text": "市场趋势分析", "start": 180, "end": 300},
{"text": "问答环节", "start": 300, "end": 420},
]
plot_speech_timeline(timestamps, "会议发言时间分布")
5.3 构建Web可视化界面
结合Gradio,我们可以快速创建一个交互式的可视化工具。
import gradio as gr
import plotly.graph_objects as go
from datetime import datetime
def visualize_timestamps(audio_file, language="auto"):
"""处理音频并生成可视化结果"""
# 调用识别API(这里简化,实际需要调用模型)
# result = model([audio_file], language=language, return_timestamps=True)
# 模拟数据(实际使用时替换为真实识别结果)
result = {
"text": "这是一个测试音频,包含多句话语。时间戳对齐功能非常实用。",
"timestamps": [
{"text": "这是一个测试音频,", "start": 0.0, "end": 2.5},
{"text": "包含多句话语。", "start": 2.5, "end": 4.0},
{"text": "时间戳对齐功能非常实用。", "start": 4.0, "end": 7.0}
]
}
# 创建时间轴图表
fig = go.Figure()
for i, ts in enumerate(result['timestamps']):
fig.add_trace(go.Scatter(
x=[ts['start'], ts['end']],
y=[i, i],
mode='lines+markers',
line=dict(width=10),
marker=dict(size=15),
name=ts['text'][:20] + "...",
hoverinfo='text',
hovertext=f"文本: {ts['text']}<br>时间: {ts['start']:.2f}s - {ts['end']:.2f}s"
))
fig.update_layout(
title="语音识别时间轴",
xaxis_title="时间 (秒)",
yaxis_title="句子序号",
showlegend=True,
height=400
)
# 生成SRT字幕
srt_content = "WEBVTT\n\n"
for i, ts in enumerate(result['timestamps'], 1):
start = format_time_str(ts['start'])
end = format_time_str(ts['end'])
srt_content += f"{start} --> {end}\n{ts['text']}\n\n"
return result['text'], fig, srt_content
def format_time_str(seconds):
"""格式化时间显示"""
return str(datetime.utcfromtimestamp(seconds).strftime('%H:%M:%S.%f'))[:-3]
# 创建Gradio界面
demo = gr.Interface(
fn=visualize_timestamps,
inputs=[
gr.Audio(label="上传音频文件", type="filepath"),
gr.Dropdown(["auto", "zh", "en", "yue", "ja", "ko"],
label="语言选择", value="auto")
],
outputs=[
gr.Textbox(label="识别文本"),
gr.Plot(label="时间轴可视化"),
gr.Textbox(label="字幕文件内容", lines=10)
],
title="语音识别时间戳可视化工具",
description="上传音频文件,获取带时间戳的识别结果和可视化图表"
)
# 启动界面
demo.launch(server_name="0.0.0.0", server_port=7861)
6. 实战案例:会议录音分析与字幕生成
让我们通过一个完整的实战案例,将前面学到的知识串联起来。假设我们有一段30分钟的会议录音,需要完成以下任务:
- 转写会议内容
- 为每个发言添加时间戳
- 生成字幕文件
- 分析发言时间分布
6.1 完整处理流程
import os
from pathlib import Path
import json
from datetime import datetime
class MeetingAnalyzer:
"""会议录音分析器"""
def __init__(self, model_path):
"""初始化分析器"""
from funasr_onnx import SenseVoiceSmall
self.model = SenseVoiceSmall(model_path, batch_size=1, quantize=True)
def process_meeting(self, audio_path, output_dir="output"):
"""处理会议录音"""
# 创建输出目录
os.makedirs(output_dir, exist_ok=True)
# 1. 语音识别(带时间戳)
print("正在识别音频...")
results = self.model([audio_path],
language="auto",
use_itn=True,
return_timestamps=True,
timestamp_level="sentence")
if not results:
print("识别失败")
return
result = results[0]
# 2. 保存原始结果
raw_output = {
"audio_file": audio_path,
"total_duration": result.get('duration', 0),
"language": result.get('language', 'unknown'),
"full_text": result['text'],
"sentences": result.get('sentences', []),
"timestamp": datetime.now().isoformat()
}
raw_file = os.path.join(output_dir, "raw_result.json")
with open(raw_file, 'w', encoding='utf-8') as f:
json.dump(raw_output, f, indent=2, ensure_ascii=False)
print(f"原始结果已保存: {raw_file}")
# 3. 生成字幕文件
srt_file = os.path.join(output_dir, "subtitles.srt")
self.generate_subtitles(raw_output['sentences'], srt_file)
print(f"字幕文件已生成: {srt_file}")
# 4. 生成分析报告
report_file = os.path.join(output_dir, "analysis_report.md")
self.generate_report(raw_output, report_file)
print(f"分析报告已生成: {report_file}")
# 5. 可视化图表
viz_file = os.path.join(output_dir, "timeline.png")
self.visualize_timeline(raw_output['sentences'], viz_file)
print(f"时间轴图表已生成: {viz_file}")
return raw_output
def generate_subtitles(self, sentences, output_file):
"""生成SRT字幕文件"""
with open(output_file, 'w', encoding='utf-8') as f:
for i, sent in enumerate(sentences, 1):
start = self._format_srt_time(sent['start'])
end = self._format_srt_time(sent['end'])
f.write(f"{i}\n{start} --> {end}\n{sent['text']}\n\n")
def _format_srt_time(self, seconds):
"""格式化SRT时间"""
hours = int(seconds // 3600)
minutes = int((seconds % 3600) // 60)
secs = seconds % 60
return f"{hours:02d}:{minutes:02d}:{secs:06.3f}".replace('.', ',')
def generate_report(self, data, output_file):
"""生成分析报告"""
sentences = data['sentences']
total_duration = data['total_duration']
# 计算统计信息
num_sentences = len(sentences)
avg_sentence_duration = sum(s['end'] - s['start'] for s in sentences) / num_sentences
total_speech_duration = sum(s['end'] - s['start'] for s in sentences)
with open(output_file, 'w', encoding='utf-8') as f:
f.write("# 会议录音分析报告\n\n")
f.write(f"**分析时间**: {data['timestamp']}\n")
f.write(f"**音频文件**: {data['audio_file']}\n")
f.write(f"**识别语言**: {data['language']}\n\n")
f.write("## 统计概览\n")
f.write(f"- 音频总时长: {total_duration:.2f} 秒\n")
f.write(f"- 识别句子数: {num_sentences} 句\n")
f.write(f"- 总发言时长: {total_speech_duration:.2f} 秒\n")
f.write(f"- 平均句长: {avg_sentence_duration:.2f} 秒/句\n")
f.write(f"- 语音密度: {(total_speech_duration/total_duration*100):.1f}%\n\n")
f.write("## 详细时间戳\n")
f.write("| 序号 | 开始时间 | 结束时间 | 时长(秒) | 内容摘要 |\n")
f.write("|------|----------|----------|-----------|----------|\n")
for i, sent in enumerate(sentences, 1):
duration = sent['end'] - sent['start']
content_preview = sent['text'][:30] + "..." if len(sent['text']) > 30 else sent['text']
f.write(f"| {i} | {sent['start']:.2f}s | {sent['end']:.2f}s | {duration:.2f} | {content_preview} |\n")
f.write("\n## 完整文本\n")
f.write(data['full_text'])
def visualize_timeline(self, sentences, output_file):
"""生成时间轴可视化图表"""
import matplotlib.pyplot as plt
fig, ax = plt.subplots(figsize=(14, max(6, len(sentences)*0.3)))
# 绘制时间块
for i, sent in enumerate(sentences):
start = sent['start']
duration = sent['end'] - sent['start']
ax.barh(i, duration, left=start, height=0.6,
alpha=0.7, edgecolor='black')
# 添加文本标签(缩短长文本)
text = sent['text']
if len(text) > 40:
text = text[:37] + "..."
ax.text(start + duration/2, i, text,
ha='center', va='center', fontsize=9)
ax.set_xlabel('时间 (秒)', fontsize=12)
ax.set_ylabel('句子序号', fontsize=12)
ax.set_title('会议发言时间分布', fontsize=14, pad=20)
ax.grid(True, alpha=0.3, axis='x')
plt.tight_layout()
plt.savefig(output_file, dpi=150, bbox_inches='tight')
plt.close()
# 使用示例
if __name__ == "__main__":
# 初始化分析器
analyzer = MeetingAnalyzer("/root/ai-models/danieldong/sensevoice-small-onnx-quant")
# 处理会议录音
result = analyzer.process_meeting(
audio_path="meeting_recording.wav",
output_dir="meeting_analysis"
)
print("处理完成!请在 meeting_analysis 目录查看结果文件。")
6.2 输出结果示例
运行上述代码后,你会得到以下文件:
- raw_result.json - 原始识别数据
- subtitles.srt - 可直接使用的字幕文件
- analysis_report.md - 详细的分析报告
- timeline.png - 时间轴可视化图表
分析报告内容示例:
# 会议录音分析报告
**分析时间**: 2024-01-15T14:30:00
**音频文件**: meeting_recording.wav
**识别语言**: zh
## 统计概览
- 音频总时长: 1800.00 秒 (30分钟)
- 识别句子数: 45 句
- 总发言时长: 1420.50 秒
- 平均句长: 31.57 秒/句
- 语音密度: 78.9%
## 详细时间戳
| 序号 | 开始时间 | 结束时间 | 时长(秒) | 内容摘要 |
|------|----------|----------|-----------|----------|
| 1 | 0.00s | 12.50s | 12.50 | 大家好,欢迎参加本次季度... |
| 2 | 15.20s | 42.30s | 27.10 | 首先回顾一下上季度的业绩... |
| ... | ... | ... | ... | ... |
7. 实用技巧与常见问题
7.1 提升时间戳准确性的技巧
时间戳的准确性直接影响使用体验。以下是一些实用技巧:
1. 音频预处理很重要
import librosa
import soundfile as sf
def preprocess_audio(input_path, output_path):
"""音频预处理:标准化音量、降噪、格式转换"""
# 读取音频
y, sr = librosa.load(input_path, sr=16000) # 重采样到16kHz
# 音量标准化
y_normalized = librosa.util.normalize(y)
# 简单的降噪处理(可选)
# y_denoised = librosa.effects.preemphasis(y_normalized)
# 保存为WAV格式(兼容性最好)
sf.write(output_path, y_normalized, sr, subtype='PCM_16')
return output_path
# 使用预处理
clean_audio = preprocess_audio("noisy_recording.mp3", "cleaned_audio.wav")
2. 调整识别参数
# 更精细的时间戳设置
results = model(
audio_files,
language="zh",
return_timestamps=True,
timestamp_level="word", # 词级别更精确
vad=True, # 启用语音活动检测
vad_params={
"threshold": 0.5, # VAD阈值
"min_silence_duration": 0.3, # 最小静音时长
}
)
3. 后处理优化
def refine_timestamps(sentences, min_gap=0.5):
"""优化时间戳:合并过短的间隔"""
if not sentences:
return sentences
refined = [sentences[0]]
for i in range(1, len(sentences)):
prev = refined[-1]
curr = sentences[i]
# 如果间隔太短,合并句子
if curr['start'] - prev['end'] < min_gap:
prev['text'] += " " + curr['text']
prev['end'] = curr['end']
else:
refined.append(curr)
return refined
7.2 常见问题解答
Q: 时间戳不准确怎么办? A: 首先检查音频质量,背景噪音会影响准确性。可以尝试:
- 使用预处理函数清理音频
- 调整VAD参数(语音活动检测)
- 确保音频采样率为16kHz(模型最优采样率)
Q: 长音频处理时间戳偏移? A: 对于超过10分钟的音频,建议分段处理:
def process_long_audio(audio_path, chunk_duration=300):
"""分段处理长音频"""
import librosa
from pydub import AudioSegment
audio = AudioSegment.from_file(audio_path)
chunks = []
# 按固定时长分段
for i in range(0, len(audio), chunk_duration * 1000):
chunk = audio[i:i + chunk_duration * 1000]
chunk_path = f"chunk_{i//1000}.wav"
chunk.export(chunk_path, format="wav")
chunks.append(chunk_path)
# 分别处理每个片段
all_results = []
time_offset = 0
for chunk_file in chunks:
result = model([chunk_file], return_timestamps=True)
# 调整时间戳偏移
for sentence in result[0]['sentences']:
sentence['start'] += time_offset
sentence['end'] += time_offset
all_results.extend(result[0]['sentences'])
time_offset += chunk_duration
return all_results
Q: 如何支持更多音频格式? A: SenseVoice-small-onnx支持多种格式,但建议统一转为WAV处理:
def convert_to_wav(input_file, output_file=None):
"""转换音频格式为WAV"""
from pydub import AudioSegment
if output_file is None:
output_file = input_file.rsplit('.', 1)[0] + '.wav'
audio = AudioSegment.from_file(input_file)
audio.export(output_file, format="wav", parameters=["-ar", "16000"])
return output_file
Q: 时间戳数据如何导出到Excel?
import pandas as pd
def export_to_excel(timestamps, output_file="timestamps.xlsx"):
"""导出时间戳数据到Excel"""
data = []
for i, ts in enumerate(timestamps, 1):
data.append({
'序号': i,
'开始时间(s)': ts['start'],
'结束时间(s)': ts['end'],
'时长(s)': ts['end'] - ts['start'],
'内容': ts['text']
})
df = pd.DataFrame(data)
df.to_excel(output_file, index=False)
print(f"已导出到: {output_file}")
8. 总结
通过这篇教程,我们全面掌握了SenseVoice-small-onnx语音识别模型的时间戳对齐与可视化展示功能。从基础的环境部署,到时间戳数据的获取和处理,再到各种可视化展示方法,我们一步步构建了一个完整的语音识别工作流。
关键收获回顾:
-
时间戳的价值:不仅仅是文字转写,更重要的是知道每个词、每句话在时间轴上的位置,这为后续的字幕生成、内容检索、会议分析等应用奠定了基础。
-
多种获取方式:无论是通过Web界面、REST API还是Python SDK,都能方便地获取带时间戳的识别结果,满足不同用户的需求。
-
丰富的可视化展示:从简单的字幕文件生成,到交互式的时间轴图表,再到完整的Web可视化工具,我们可以根据需求选择最合适的展示方式。
-
实战应用能力:通过会议录音分析的完整案例,我们学会了如何将时间戳功能应用到实际工作中,生成有价值的分析报告和可视化成果。
下一步建议:
如果你已经掌握了基础的时间戳对齐,可以尝试以下进阶方向:
- 结合说话人分离技术,为不同发言人生成独立的时间轴
- 将时间戳数据与视频编辑软件结合,实现自动化字幕添加
- 开发实时语音识别系统,动态展示时间戳信息
- 结合情感分析,在时间轴上标注情感变化趋势
SenseVoice-small-onnx作为一个轻量高效的语音识别解决方案,在保持高精度的同时,提供了丰富的时间戳功能。无论是个人使用还是集成到企业应用中,都能显著提升语音内容处理的效率和质量。
获取更多AI镜像
想探索更多AI镜像和应用场景?访问 CSDN星图镜像广场,提供丰富的预置镜像,覆盖大模型推理、图像生成、视频生成、模型微调等多个领域,支持一键部署。
更多推荐


所有评论(0)