Qwen3-ASR-0.6B从零开始WebUI源码二次开发添加导出SRT字幕功能1. 项目背景与需求分析Qwen3-ASR-0.6B是一个轻量级高性能语音识别模型参数量6亿基于Qwen3-Omni基座与自研AuT语音编码器。该模型支持52种语言30种主流语言22种中文方言主打多语种、低延迟与高并发吞吐是兼顾精度与效率的边缘/云端部署优选。在实际使用中用户经常需要将语音识别结果导出为SRT字幕格式以便用于视频编辑、会议记录、教育培训等场景。然而原生的WebUI界面并未提供这一功能本文将详细介绍如何通过源码二次开发为Qwen3-ASR-0.6B WebUI添加SRT字幕导出功能。核心需求分析在转录结果页面添加导出SRT按钮将时间戳和文本内容转换为标准SRT格式支持批量导出和多文件处理保持界面简洁易用不影响原有功能2. 环境准备与项目结构2.1 系统要求与依赖确保你的系统已安装以下环境Python 3.8CUDA 11.7如使用GPU加速FFmpeg用于音频处理2.2 项目目录结构了解项目结构是二次开发的基础/root/qwen3-asr-service/ ├── app/ │ ├── main.py # FastAPI主应用 │ └── utils.py # 工具函数 ├── webui/ │ ├── index.html # WebUI页面 │ ├── server.py # 反向代理服务器 │ └── static/ # 静态资源 │ ├── js/ │ │ └── app.js # 前端逻辑 │ └── css/ │ └── style.css # 样式文件 ├── logs/ # 日志目录 └── requirements.txt # 依赖列表3. SRT格式解析与实现原理3.1 SRT字幕格式规范SRT(SubRip Text)是最常用的字幕格式其基本结构如下1 00:00:01,000 -- 00:00:04,000 这是第一句字幕 2 00:00:05,000 -- 00:00:08,000 这是第二句字幕每个字幕块包含序号从1开始的连续数字时间轴开始时间 -- 结束时间格式小时:分钟:秒,毫秒字幕文本一行或多行文字空行每个字幕块之间用空行分隔3.2 时间戳转换算法Qwen3-ASR返回的时间戳通常是秒为单位需要转换为SRT格式的时间码def seconds_to_srt_time(seconds): 将秒数转换为SRT时间格式 hours int(seconds // 3600) minutes int((seconds % 3600) // 60) secs seconds % 60 milliseconds int((secs - int(secs)) * 1000) return f{hours:02d}:{minutes:02d}:{int(secs):02d},{milliseconds:03d}4. 后端API开发4.1 添加SRT导出接口在app/main.py中添加新的API端点from fastapi import Response from fastapi.responses import PlainTextResponse app.post(/api/export_srt) async def export_srt(transcript_data: dict): 将转录结果转换为SRT格式 try: srt_content generate_srt(transcript_data) return PlainTextResponse( contentsrt_content, media_typetext/plain, headers{ Content-Disposition: attachment; filenametranscript.srt } ) except Exception as e: raise HTTPException(status_code500, detailfSRT导出失败: {str(e)}) def generate_srt(transcript_data): 生成SRT格式内容 srt_lines [] segments transcript_data.get(segments, []) for i, segment in enumerate(segments, 1): start_time seconds_to_srt_time(segment[start]) end_time seconds_to_srt_time(segment[end]) text segment[text].strip() srt_lines.append(str(i)) srt_lines.append(f{start_time} -- {end_time}) srt_lines.append(text) srt_lines.append() # 空行分隔 return \n.join(srt_lines)4.2 时间戳转换工具函数在app/utils.py中添加时间转换函数def seconds_to_srt_time(seconds): 将秒数转换为SRT标准时间格式 if seconds is None: return 00:00:00,000 hours int(seconds // 3600) minutes int((seconds % 3600) // 60) secs seconds % 60 milliseconds int((secs - int(secs)) * 1000) return f{hours:02d}:{minutes:02d}:{int(secs):02d},{milliseconds:03d}5. 前端界面改造5.1 修改WebUI界面在webui/static/js/app.js中添加导出功能// 添加导出SRT按钮 function addExportButton(transcriptData) { const resultContainer document.getElementById(result-container); if (!resultContainer) return; // 移除已存在的导出按钮 const existingButton document.getElementById(export-srt-btn); if (existingButton) { existingButton.remove(); } // 创建新的导出按钮 const exportButton document.createElement(button); exportButton.id export-srt-btn; exportButton.className btn btn-export; exportButton.innerHTML i classicon-download/i 导出SRT字幕; exportButton.onclick () exportToSrt(transcriptData); // 将按钮添加到结果容器 const actionBar document.createElement(div); actionBar.className export-action-bar; actionBar.appendChild(exportButton); resultContainer.insertBefore(actionBar, resultContainer.firstChild); } // SRT导出功能 async function exportToSrt(transcriptData) { try { const response await fetch(/api/export_srt, { method: POST, headers: { Content-Type: application/json, }, body: JSON.stringify(transcriptData), }); if (response.ok) { const blob await response.blob(); const url window.URL.createObjectURL(blob); const a document.createElement(a); a.style.display none; a.href url; a.download transcript.srt; document.body.appendChild(a); a.click(); window.URL.revokeObjectURL(url); document.body.removeChild(a); } else { alert(导出失败请重试); } } catch (error) { console.error(导出错误:, error); alert(导出过程中发生错误); } }5.2 添加CSS样式在webui/static/css/style.css中添加按钮样式/* 导出按钮样式 */ .btn-export { background: linear-gradient(135deg, #667eea 0%, #764ba2 100%); color: white; border: none; padding: 12px 24px; border-radius: 8px; cursor: pointer; font-weight: 600; transition: all 0.3s ease; margin: 15px 0; display: inline-flex; align-items: center; gap: 8px; } .btn-export:hover { transform: translateY(-2px); box-shadow: 0 4px 12px rgba(102, 126, 234, 0.3); } .export-action-bar { text-align: center; margin-bottom: 20px; padding: 15px; background: #f8f9fa; border-radius: 8px; border: 1px solid #e9ecef; } /* 图标样式 */ .icon-download { width: 16px; height: 16px; fill: currentColor; }6. 功能集成与测试6.1 修改转录结果显示逻辑在转录完成后的回调函数中集成导出功能// 修改现有的转录结果显示函数 function displayTranscriptionResult(result) { const resultContainer document.getElementById(result-container); resultContainer.innerHTML ; // 显示转录文本 const transcriptText document.createElement(div); transcriptText.className transcript-text; transcriptText.textContent result.text; resultContainer.appendChild(transcriptText); // 添加导出按钮 addExportButton(result); // 显示详细的时间戳信息可选 if (result.segments result.segments.length 0) { const details document.createElement(details); details.innerHTML summary显示时间戳详情/summary div classtimestamp-details ${result.segments.map(seg div classsegment [${formatTime(seg.start)} - ${formatTime(seg.end)}] ${seg.text} /div ).join()} /div ; resultContainer.appendChild(details); } } // 时间格式化辅助函数 function formatTime(seconds) { const mins Math.floor(seconds / 60); const secs Math.floor(seconds % 60); const ms Math.floor((seconds % 1) * 1000); return ${mins.toString().padStart(2, 0)}:${secs.toString().padStart(2, 0)}.${ms.toString().padStart(3, 0)}; }6.2 测试导出功能完成开发后进行全面的功能测试基本功能测试上传音频文件进行转录点击导出SRT按钮检查下载的文件格式是否正确格式验证测试使用视频播放器加载SRT文件验证时间戳同步准确性检查特殊字符处理情况边界情况测试空转录结果的处理长时间音频的导出多语言字符集支持7. 完整代码整合与部署7.1 后端完整代码示例# 在app/main.py中的完整实现 from fastapi import FastAPI, File, UploadFile, HTTPException from fastapi.responses import PlainTextResponse from fastapi.middleware.cors import CORSMiddleware import json app FastAPI(titleQwen3-ASR-0.6B Service) # 添加CORS中间件 app.add_middleware( CORSMiddleware, allow_origins[*], allow_credentialsTrue, allow_methods[*], allow_headers[*], ) app.post(/api/export_srt) async def export_srt(transcript_data: dict): 导出SRT字幕文件 try: srt_content generate_srt(transcript_data) return PlainTextResponse( contentsrt_content, media_typetext/plain, headers{Content-Disposition: attachment; filenametranscript.srt} ) except Exception as e: raise HTTPException(status_code500, detailfSRT导出失败: {str(e)}) def generate_srt(transcript_data): 生成SRT格式内容 if not transcript_data or segments not in transcript_data: return srt_lines [] segments transcript_data[segments] for i, segment in enumerate(segments, 1): start segment.get(start, 0) end segment.get(end, 0) text segment.get(text, ).strip() if not text: # 跳过空文本段 continue start_time seconds_to_srt_time(start) end_time seconds_to_srt_time(end) srt_lines.append(str(i)) srt_lines.append(f{start_time} -- {end_time}) srt_lines.append(text) srt_lines.append() # 空行分隔 return \n.join(srt_lines) def seconds_to_srt_time(seconds): 秒数转SRT时间格式 hours int(seconds // 3600) minutes int((seconds % 3600) // 60) secs seconds % 60 milliseconds int((secs - int(secs)) * 1000) return f{hours:02d}:{minutes:02d}:{int(secs):02d},{milliseconds:03d} # 其他已有API端点保持不变...7.2 部署与重启服务完成代码修改后重启服务使更改生效# 进入项目目录 cd /root/qwen3-asr-service # 重启服务 supervisorctl restart qwen3-asr-service # 查看服务状态 supervisorctl status qwen3-asr-service # 查看日志确认无错误 tail -f /root/qwen3-asr-service/logs/app.log8. 总结通过本文的二次开发教程我们成功为Qwen3-ASR-0.6B WebUI添加了SRT字幕导出功能。这个功能虽然看起来简单但极大提升了语音识别结果的实际应用价值。主要成果实现了标准的SRT字幕导出功能保持了WebUI的简洁性和易用性支持多语言和时间戳精确转换提供了完整的错误处理和用户体验优化实用建议在生产环境中可以考虑添加批量导出功能对于长时间音频建议添加导出进度提示可以进一步支持更多字幕格式如VTT、ASS等考虑添加导出设置选项如字体大小、颜色等元数据这个二次开发示例展示了如何基于现有AI服务进行功能扩展同样的思路可以应用于其他功能的添加和优化。通过简单的代码修改就能让强大的AI能力更好地服务于实际应用场景。获取更多AI镜像想探索更多AI镜像和应用场景访问 CSDN星图镜像广场提供丰富的预置镜像覆盖大模型推理、图像生成、视频生成、模型微调等多个领域支持一键部署。