一、项目简介
在短视频、在线教育、播客剪辑、语音质检等场景中,开发者经常需要快速查看音频的基础属性,例如时长、采样率、声道数、音量峰值和波形变化。如果每次都依赖桌面软件,数据难以沉淀,也不方便与业务系统集成。
本文实现一个完整的 Python 音频处理与分析全栈项目:用户可以在浏览器中注册、登录、上传 WAV 音频,后端完成音频解析并保存分析结果,前端展示统计看板、指标列表和简易波形图。项目不仅讲算法指标,也覆盖后端接口、数据库、认证鉴权、Vue 3 前端和部署运行步骤。
二、技术栈
- 后端:FastAPI、SQLAlchemy、Pydantic、Uvicorn
- 数据库:SQLite
- 前端:Vue 3、Vite、Fetch API、CSS 响应式布局
- 认证:PBKDF2-HMAC-SHA256 密码哈希、Bearer Token
- 音频处理:Python 标准库
wave、audioop - 打包交付:README、源码目录、zip 项目包
三、系统架构
系统采用前后端分离架构:
浏览器 Vue 3 页面
│
│ HTTP/JSON + Bearer Token
▼
FastAPI REST API
│
├── 用户注册/登录/退出
├── Token 鉴权依赖
├── 音频上传与 WAV 解析
└── 音频记录查询/删除/汇总
│
▼
SQLite 数据库 + 本地 uploads 文件目录
用户首先注册或登录,前端将后端返回的 token 存入 localStorage。之后上传音频、查询列表、删除记录时,都通过 Authorization: Bearer *** 访问受保护接口。
四、功能模块
-
用户模块
- 注册账号
- 登录获取 Token
- 查询当前用户
- 退出登录并注销 Token
-
音频分析模块
- 上传 WAV 文件
- 解析采样率、声道数、采样宽度、帧数、时长
- 计算 RMS、峰值、过零率
- 生成简化波形点
-
数据管理模块
- 保存音频文件路径和分析结果
- 查询当前用户的音频记录
- 删除记录时同步清理本地文件
- 统计总文件数、总时长和平均 RMS
-
前端交互模块
- 登录/注册切换
- 登录状态保持
- 文件上传
- 指标卡片和波形展示
- 退出登录
五、数据库/数据模型设计
项目使用 SQLite,核心表包括 users、tokens、audio_files。
1. 用户表 users
| 字段 | 类型 | 说明 |
|---|---|---|
| id | Integer | 主键 |
| username | String | 唯一用户名 |
| password_hash | String | 加盐哈希密码 |
| created_at | DateTime | 创建时间 |
2. Token 表 tokens
| 字段 | 类型 | 说明 |
|---|---|---|
| token | String | Bearer Token 主键 |
| user_id | Integer | 所属用户 |
| created_at | DateTime | 创建时间 |
3. 音频表 audio_files
| 字段 | 类型 | 说明 |
|---|---|---|
| id | Integer | 主键 |
| filename | String | 原始文件名 |
| stored_path | String | 服务端保存路径 |
| sample_rate | Integer | 采样率 |
| channels | Integer | 声道数 |
| duration | Float | 时长 |
| rms | Float | 均方根音量 |
| peak | Float | 峰值音量 |
| zero_crossing_rate | Float | 过零率 |
| waveform | Text | JSON 波形点 |
| owner_id | Integer | 所属用户 |
对应 SQLAlchemy 模型节选:
class AudioFile(Base):
__tablename__ = "audio_files"
id = mapped_column(Integer, primary_key=True, index=True)
filename = mapped_column(String(255), nullable=False)
stored_path = mapped_column(String(500), nullable=False)
sample_rate = mapped_column(Integer, default=0)
channels = mapped_column(Integer, default=0)
duration = mapped_column(Float, default=0)
rms = mapped_column(Float, default=0)
peak = mapped_column(Float, default=0)
zero_crossing_rate = mapped_column(Float, default=0)
waveform = mapped_column(Text, default="[]")
owner_id = mapped_column(ForeignKey("users.id"), nullable=False)
六、后端接口设计
| 方法 | 路径 | 功能 | 是否需要登录 |
|---|---|---|---|
| GET | /api/health | 健康检查 | 否 |
| POST | /api/auth/register | 注册并自动登录 | 否 |
| POST | /api/auth/login | 登录 | 否 |
| POST | /api/auth/logout | 退出登录 | 是 |
| GET | /api/me | 当前用户信息 | 是 |
| POST | /api/audios | 上传并分析 WAV | 是 |
| GET | /api/audios | 音频分析列表 | 是 |
| GET | /api/audios/summary | 汇总统计 | 是 |
| DELETE | /api/audios/{audio_id} | 删除音频 | 是 |
鉴权依赖核心代码:
def extract_token(authorization: str | None = Header(default=None)) -> str:
if not authorization or not authorization.lower().startswith("bearer "):
raise HTTPException(status_code=401, detail="缺少登录令牌")
return authorization.split(" ", 1)[1]
def current_user(token: str = Depends(extract_token), db: Session = Depends(get_db)):
user = crud.get_user_by_token(db, token)
if not user:
raise HTTPException(status_code=401, detail="登录已过期,请重新登录")
return user
这样所有音频接口只要声明 user: models.User = Depends(current_user),就自动具备登录保护。
七、前端页面设计
前端使用 Vue 3 单页应用,主要区域包括:
- 顶部 Hero:展示系统名称、技术栈和退出按钮
- 登录/注册卡片:未登录时显示
- 用户信息条:显示当前用户并支持刷新
- 数据看板:展示音频数量、总时长、平均 RMS
- 上传区域:选择 WAV 文件并提交后端
- 音频列表:展示每条记录的指标与波形条
前端 API 封装统一处理 Token:
async function request(path, options = {}) {
const headers = options.headers || {}
const token = getToken()
if (token) headers.Authorization = `Bearer ${token}`
const response = await fetch(`${API_BASE}${path}`, { ...options, headers })
const data = await response.json().catch(() => ({}))
if (!response.ok) throw new Error(data.detail || '请求失败')
return data
}
上传文件时使用 FormData:
uploadAudio: (file) => {
const form = new FormData()
form.append('file', file)
return request('/api/audios', { method: 'POST', body: form })
}
八、核心代码讲解
1. 密码哈希
项目没有明文保存密码,而是使用 PBKDF2 加盐哈希:
def hash_password(password: str, salt: str | None = None) -> str:
salt = salt or secrets.token_hex(16)
digest = hashlib.pbkdf2_hmac("sha256", password.encode(), salt.encode(), 120_000).hex()
return f"pbkdf2_sha256${salt}${digest}"
验证时重新计算摘要,并使用 secrets.compare_digest 防止时序攻击。
2. WAV 音频分析
后端使用 wave.open 获取音频参数,并用 audioop 计算音量指标:
with wave.open(str(path), "rb") as wav:
channels = wav.getnchannels()
sample_width = wav.getsampwidth()
sample_rate = wav.getframerate()
frame_count = wav.getnframes()
frames = wav.readframes(frame_count)
duration = frame_count / sample_rate if sample_rate else 0.0
rms_raw = audioop.rms(frames, sample_width) if frames else 0
peak_raw = audioop.max(frames, sample_width) if frames else 0
RMS 表示音频能量平均水平,峰值表示最大幅度,过零率常用于粗略判断音频频率变化或噪声程度。
3. 波形点生成
为了让前端快速绘制波形,后端不返回所有采样点,而是抽样为最多 120 个点:
step = max(1, sample_count // 120)
for i in range(0, len(mono), sample_width * step):
chunk = mono[i:i + sample_width]
points.append(round(int.from_bytes(chunk, "little", signed=True) / max_amp, 4))
前端根据点的绝对值设置柱状高度,形成轻量波形预览。
4. 音频上传接口
@app.post("/api/audios", response_model=schemas.AudioOut)
async def upload_audio(file: UploadFile = File(...), user: models.User = Depends(current_user), db: Session = Depends(get_db)):
if not file.filename.lower().endswith(".wav"):
raise HTTPException(status_code=400, detail="当前版本仅支持 WAV 文件")
data = await file.read()
audio = crud.save_audio(db, user.id, file.filename, file.content_type or "audio/wav", data)
return crud.to_audio_out(audio)
接口先验证文件后缀和大小,再保存文件、分析数据、写入数据库。
九、部署与运行步骤
项目源码位于 project/ 目录。
1. 启动后端
cd project/backend
python3 -m venv .venv
source .venv/bin/activate
pip install -r requirements.txt
uvicorn app.main:app --reload --host 0.0.0.0 --port 8000
后端默认地址为:http://127.0.0.1:8000。
2. 启动前端
cd project/frontend
npm install
npm run dev
前端默认地址为:http://127.0.0.1:5173。
3. 使用流程
- 打开前端页面。
- 注册一个新账号或使用已有账号登录。
- 上传 PCM WAV 文件。
- 查看音频指标和波形图。
- 根据需要删除历史记录或继续上传更多音频。
十、可扩展方向
- 支持 MP3、FLAC 等格式,可接入 FFmpeg 或 pydub。
- 增加频谱图、梅尔频谱、MFCC 特征提取。
- 接入语音识别模型,实现转写和关键词检索。
- 增加团队空间,让多个用户协作管理音频资产。
- 支持对象存储,将上传文件保存到 MinIO、S3 等服务。
十一、项目总结
本文完成了一个真正可运行的 Python 音频处理与分析全栈项目。后端使用 FastAPI 提供 REST API,SQLite 保存用户与分析记录,认证模块实现密码哈希和 Token 鉴权;前端使用 Vue 3 + Vite 构建交互页面,完成注册、登录、上传、统计和波形展示。这个项目既适合作为音频处理入门案例,也可以继续扩展为语音质检、音频素材管理或智能语音分析平台。

7090

被折叠的 条评论
为什么被折叠?



