imetting_backend/app/services/audio_service.py

173 lines
6.5 KiB
Python
Raw Permalink Blame History

This file contains ambiguous Unicode characters!

This file contains ambiguous Unicode characters that may be confused with others in your current locale. If your use case is intentional and legitimate, you can safely ignore this warning. Use the Escape button to highlight these characters.

"""
音频处理服务
处理已保存的完整音频文件:数据库更新、转录、自动总结
"""
from fastapi import BackgroundTasks
from app.core.database import get_db_connection
from app.core.response import create_api_response
from app.core.config import BASE_DIR
from app.services.async_transcription_service import AsyncTranscriptionService
from app.services.async_meeting_service import async_meeting_service
from pathlib import Path
import os
transcription_service = AsyncTranscriptionService()
def handle_audio_upload(
file_path: str,
file_name: str,
file_size: int,
meeting_id: int,
current_user: dict,
auto_summarize: bool = True,
background_tasks: BackgroundTasks = None,
prompt_id: int = None
) -> dict:
"""
处理已保存的完整音频文件
职责:
1. 权限检查
2. 检查已有文件和转录记录
3. 更新数据库audio_files 表)
4. 启动转录任务
5. 可选启动自动总结监控
Args:
file_path: 已保存的文件路径(相对于 BASE_DIR 的路径,如 /uploads/audio/123/xxx.webm
file_name: 原始文件名
file_size: 文件大小(字节)
meeting_id: 会议ID
current_user: 当前用户信息
auto_summarize: 是否自动生成总结默认True
background_tasks: FastAPI 后台任务对象
prompt_id: 提示词模版ID可选如果不指定则使用默认模版
Returns:
dict: {
"success": bool, # 是否成功
"response": dict, # 如果需要返回,这里是响应数据
"file_info": dict, # 文件信息 (成功时)
"transcription_task_id": str, # 转录任务ID (成功时)
"replaced_existing": bool, # 是否替换了现有文件 (成功时)
"has_transcription": bool # 原来是否有转录记录 (成功时)
}
"""
print(f"[Audio Service] handle_audio_upload called - Meeting ID: {meeting_id}, Auto-summarize: {auto_summarize}, Received prompt_id: {prompt_id}, Type: {type(prompt_id)}")
# 1. 权限和已有文件检查
try:
with get_db_connection() as connection:
cursor = connection.cursor(dictionary=True)
# 检查会议是否存在及权限
cursor.execute("SELECT user_id FROM meetings WHERE meeting_id = %s", (meeting_id,))
meeting = cursor.fetchone()
if not meeting:
return {
"success": False,
"response": create_api_response(code="404", message="会议不存在")
}
if meeting['user_id'] != current_user['user_id']:
return {
"success": False,
"response": create_api_response(code="403", message="无权限操作此会议")
}
# 检查已有音频文件
cursor.execute(
"SELECT file_name, file_path, upload_time FROM audio_files WHERE meeting_id = %s",
(meeting_id,)
)
existing_info = cursor.fetchone()
# 检查是否有转录记录
has_transcription = False
if existing_info:
cursor.execute(
"SELECT COUNT(*) as segment_count FROM transcript_segments WHERE meeting_id = %s",
(meeting_id,)
)
has_transcription = cursor.fetchone()['segment_count'] > 0
cursor.close()
except Exception as e:
return {
"success": False,
"response": create_api_response(code="500", message=f"检查已有文件失败: {str(e)}")
}
# 2. 删除旧的音频文件(如果存在)
replaced_existing = existing_info is not None
if replaced_existing and existing_info['file_path']:
old_file_path = BASE_DIR / existing_info['file_path'].lstrip('/')
if old_file_path.exists():
try:
os.remove(old_file_path)
print(f"Deleted old audio file: {old_file_path}")
except Exception as e:
print(f"Warning: Failed to delete old file {old_file_path}: {e}")
transcription_task_id = None
try:
# 3. 更新数据库记录
with get_db_connection() as connection:
cursor = connection.cursor(dictionary=True)
if replaced_existing:
cursor.execute(
'UPDATE audio_files SET file_name = %s, file_path = %s, file_size = %s, upload_time = NOW(), task_id = NULL WHERE meeting_id = %s',
(file_name, file_path, file_size, meeting_id)
)
else:
cursor.execute(
'INSERT INTO audio_files (meeting_id, file_name, file_path, file_size, upload_time) VALUES (%s, %s, %s, %s, NOW())',
(meeting_id, file_name, file_path, file_size)
)
connection.commit()
cursor.close()
# 4. 启动转录任务
try:
transcription_task_id = transcription_service.start_transcription(meeting_id, file_path)
print(f"Transcription task {transcription_task_id} started for meeting {meeting_id}")
# 5. 如果启用自动总结且提供了 background_tasks添加监控任务
if auto_summarize and transcription_task_id and background_tasks:
background_tasks.add_task(
async_meeting_service.monitor_and_auto_summarize,
meeting_id,
transcription_task_id,
prompt_id # 传递 prompt_id 给自动总结监控任务
)
print(f"[audio_service] Auto-summarize enabled, monitor task added for meeting {meeting_id}, prompt_id: {prompt_id}")
except Exception as e:
print(f"Failed to start transcription: {e}")
raise
except Exception as e:
# 出错时的处理(文件已保存,不删除)
return {
"success": False,
"response": create_api_response(code="500", message=f"处理失败: {str(e)}")
}
# 6. 返回成功结果
return {
"success": True,
"file_info": {
"file_name": file_name,
"file_path": file_path,
"file_size": file_size
},
"transcription_task_id": transcription_task_id,
"replaced_existing": replaced_existing,
"has_transcription": has_transcription
}