获取音频时长
parent
a2a8a48fad
commit
5b1ab08a77
|
|
@ -4,7 +4,8 @@
|
||||||
|
|
||||||
```bash
|
```bash
|
||||||
cd /Users/jiliu/工作/projects/imeeting/backend
|
cd /Users/jiliu/工作/projects/imeeting/backend
|
||||||
pip install mutagen
|
source venv/bin/activate
|
||||||
|
pip install tinytag
|
||||||
```
|
```
|
||||||
|
|
||||||
## 2. 执行数据库迁移
|
## 2. 执行数据库迁移
|
||||||
|
|
@ -28,8 +29,10 @@ mysql -u root -p imeeting < sql/migrations/add_duration_to_audio_files.sql
|
||||||
|
|
||||||
### 3.2 音频处理优化
|
### 3.2 音频处理优化
|
||||||
**音频时长计算:**
|
**音频时长计算:**
|
||||||
- 使用mutagen库自动识别音频格式并提取时长
|
- 使用TinyTag库读取音频文件时长
|
||||||
- 支持mp3, m4a, mp4, wav等常见格式
|
- 纯Python实现,无需外部依赖
|
||||||
|
- 支持mp3, m4a, mp4, wav, ogg, flac等常见格式
|
||||||
|
- 能处理特殊/损坏元数据的文件
|
||||||
- 时长保存到audio_files.duration字段(单位:秒)
|
- 时长保存到audio_files.duration字段(单位:秒)
|
||||||
- 时长读取功能位于`app/utils/audio_parser.py`
|
- 时长读取功能位于`app/utils/audio_parser.py`
|
||||||
|
|
||||||
|
|
@ -47,8 +50,9 @@ mysql -u root -p imeeting < sql/migrations/add_duration_to_audio_files.sql
|
||||||
## 4. 代码变更清单
|
## 4. 代码变更清单
|
||||||
|
|
||||||
### 后端变更:
|
### 后端变更:
|
||||||
- `/backend/app/utils/audio_parser.py` - 新增音频时长解析工具
|
- `/backend/app/utils/audio_parser.py` - 新增音频时长解析工具(使用TinyTag)
|
||||||
- `/backend/app/api/endpoints/meetings.py` - 音频上传时调用audio_parser获取时长,修复Safari播放问题
|
- `/backend/app/api/endpoints/meetings.py` - 完整文件上传时调用audio_parser获取时长,修复Safari播放问题
|
||||||
|
- `/backend/app/api/endpoints/audio.py` - Stream上传完成时调用audio_parser获取时长
|
||||||
- `/backend/app/services/audio_service.py` - 增加duration参数
|
- `/backend/app/services/audio_service.py` - 增加duration参数
|
||||||
- `/backend/app/api/endpoints/auth.py` - 登录时记录日志
|
- `/backend/app/api/endpoints/auth.py` - 登录时记录日志
|
||||||
- `/backend/app/api/endpoints/admin_dashboard.py` - 更新用户统计查询
|
- `/backend/app/api/endpoints/admin_dashboard.py` - 更新用户统计查询
|
||||||
|
|
@ -81,9 +85,10 @@ mysql -u root -p imeeting < sql/migrations/add_duration_to_audio_files.sql
|
||||||
## 6. 注意事项
|
## 6. 注意事项
|
||||||
|
|
||||||
1. **音频时长计算**:
|
1. **音频时长计算**:
|
||||||
- 使用mutagen自动识别格式
|
- 使用TinyTag纯Python库
|
||||||
|
- 无需系统依赖,跨平台兼容
|
||||||
- 计算失败时duration为0,不影响其他功能
|
- 计算失败时duration为0,不影响其他功能
|
||||||
- 支持所有mutagen支持的格式
|
- 支持所有TinyTag支持的格式
|
||||||
|
|
||||||
2. **Safari音频播放兼容性**:
|
2. **Safari音频播放兼容性**:
|
||||||
- 使用直接src属性而非source子元素
|
- 使用直接src属性而非source子元素
|
||||||
|
|
|
||||||
|
|
@ -6,6 +6,7 @@ from app.core.response import create_api_response
|
||||||
from app.services.async_transcription_service import AsyncTranscriptionService
|
from app.services.async_transcription_service import AsyncTranscriptionService
|
||||||
from app.services.async_meeting_service import async_meeting_service
|
from app.services.async_meeting_service import async_meeting_service
|
||||||
from app.services.audio_service import handle_audio_upload
|
from app.services.audio_service import handle_audio_upload
|
||||||
|
from app.utils.audio_parser import get_audio_duration
|
||||||
from pydantic import BaseModel
|
from pydantic import BaseModel
|
||||||
from typing import Optional, List
|
from typing import Optional, List
|
||||||
from datetime import datetime, timedelta
|
from datetime import datetime, timedelta
|
||||||
|
|
@ -460,6 +461,14 @@ async def complete_upload(
|
||||||
file_size = full_path.stat().st_size
|
file_size = full_path.stat().st_size
|
||||||
file_name = full_path.name
|
file_name = full_path.name
|
||||||
|
|
||||||
|
# 6.5 获取音频时长
|
||||||
|
audio_duration = 0
|
||||||
|
try:
|
||||||
|
audio_duration = get_audio_duration(str(full_path))
|
||||||
|
print(f"音频时长: {audio_duration}秒")
|
||||||
|
except Exception as e:
|
||||||
|
print(f"警告: 获取音频时长失败,但不影响后续流程: {e}")
|
||||||
|
|
||||||
# 7. 调用 audio_service 处理文件(数据库更新、启动转录和总结)
|
# 7. 调用 audio_service 处理文件(数据库更新、启动转录和总结)
|
||||||
result = handle_audio_upload(
|
result = handle_audio_upload(
|
||||||
file_path=file_path,
|
file_path=file_path,
|
||||||
|
|
@ -469,7 +478,8 @@ async def complete_upload(
|
||||||
current_user=current_user,
|
current_user=current_user,
|
||||||
auto_summarize=request.auto_summarize,
|
auto_summarize=request.auto_summarize,
|
||||||
background_tasks=background_tasks,
|
background_tasks=background_tasks,
|
||||||
prompt_id=request.prompt_id # 传递提示词模版ID
|
prompt_id=request.prompt_id, # 传递提示词模版ID
|
||||||
|
duration=audio_duration # 传递时长参数
|
||||||
)
|
)
|
||||||
|
|
||||||
# 如果处理失败,返回错误
|
# 如果处理失败,返回错误
|
||||||
|
|
@ -492,7 +502,7 @@ async def complete_upload(
|
||||||
"meeting_id": request.meeting_id,
|
"meeting_id": request.meeting_id,
|
||||||
"file_path": file_path,
|
"file_path": file_path,
|
||||||
"file_size": file_size,
|
"file_size": file_size,
|
||||||
"duration": None, # 可以通过ffprobe获取,但不是必需的
|
"duration": audio_duration,
|
||||||
"task_id": transcription_task_id,
|
"task_id": transcription_task_id,
|
||||||
"task_status": "pending" if transcription_task_id else None,
|
"task_status": "pending" if transcription_task_id else None,
|
||||||
"auto_summarize": request.auto_summarize
|
"auto_summarize": request.auto_summarize
|
||||||
|
|
|
||||||
|
|
@ -4,13 +4,15 @@
|
||||||
用于解析音频文件的元数据信息,如时长、采样率、编码格式等
|
用于解析音频文件的元数据信息,如时长、采样率、编码格式等
|
||||||
"""
|
"""
|
||||||
|
|
||||||
from mutagen import File as MutagenFile
|
from tinytag import TinyTag
|
||||||
|
|
||||||
|
|
||||||
def get_audio_duration(file_path: str) -> int:
|
def get_audio_duration(file_path: str) -> int:
|
||||||
"""
|
"""
|
||||||
获取音频文件时长(秒)
|
获取音频文件时长(秒)
|
||||||
|
|
||||||
|
使用TinyTag读取音频文件时长
|
||||||
|
|
||||||
Args:
|
Args:
|
||||||
file_path: 音频文件的完整路径
|
file_path: 音频文件的完整路径
|
||||||
|
|
||||||
|
|
@ -22,13 +24,15 @@ def get_audio_duration(file_path: str) -> int:
|
||||||
- M4A (.m4a)
|
- M4A (.m4a)
|
||||||
- MP4 (.mp4)
|
- MP4 (.mp4)
|
||||||
- WAV (.wav)
|
- WAV (.wav)
|
||||||
- 以及mutagen支持的其他格式
|
- OGG (.ogg)
|
||||||
|
- FLAC (.flac)
|
||||||
|
- 以及TinyTag支持的其他音频格式
|
||||||
"""
|
"""
|
||||||
try:
|
try:
|
||||||
audio = MutagenFile(file_path)
|
tag = TinyTag.get(file_path)
|
||||||
if audio is not None and hasattr(audio.info, 'length'):
|
if tag.duration and tag.duration > 0:
|
||||||
return int(audio.info.length)
|
return int(tag.duration)
|
||||||
return 0
|
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
print(f"获取音频时长失败 ({file_path}): {e}")
|
print(f"获取音频时长失败 ({file_path}): {e}")
|
||||||
|
|
||||||
return 0
|
return 0
|
||||||
|
|
|
||||||
|
|
@ -22,5 +22,6 @@ psutil
|
||||||
# APK Parsing
|
# APK Parsing
|
||||||
pyaxmlparser
|
pyaxmlparser
|
||||||
|
|
||||||
# Audio Processing
|
# Audio Metadata
|
||||||
mutagen==1.47.0
|
tinytag
|
||||||
|
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue