Browse Source

взаимодействие сайта с FileAudioAPI

dev
poturaevpetr 2 weeks ago
parent
commit
76b5b26c75
  1. 236
      apiApp/routers/audio_files_router.py
  2. 2
      main.py

236
apiApp/routers/audio_files_router.py

@ -0,0 +1,236 @@
"""
API endpoints для обслуживания аудиофайлов
"""
from fastapi import APIRouter, HTTPException, Depends
from fastapi.responses import FileResponse, StreamingResponse
from sqlalchemy.orm import Session
from typing import Optional
import os
import logging
from apiApp.database import get_db
from apiApp.database.Audio import Audio
from apiApp.config import AUDIOFILES_PATH
logger = logging.getLogger(__name__)
audio_files_router = APIRouter()
@audio_files_router.get("/audio/{filename}")
async def get_audio_file(filename: str):
"""
Возвращает аудиофайл для стриминга/воспроизведения
Args:
filename: Имя аудиофайла (например, "in-xxx.wav")
Returns:
StreamingResponse с аудиофайлом
"""
try:
# Проверяем расширение файла
allowed_extensions = ['.wav', '.mp3', '.ogg', '.m4a', '.flac']
if not any(filename.lower().endswith(ext) for ext in allowed_extensions):
raise HTTPException(
status_code=400,
detail=f'Неподдерживаемый формат файла. Разрешены: {", ".join(allowed_extensions)}'
)
# Формируем путь к файлу
file_path = os.path.join(AUDIOFILES_PATH, filename)
# Проверяем существование файла
if not os.path.exists(file_path):
logger.warning(f" Файл не найден: {file_path}")
raise HTTPException(
status_code=404,
detail=f'Файл {filename} не найден'
)
logger.info(f"🎵 Отдача аудио: {filename}")
# Определяем MIME тип
import mimetypes
mime_type, _ = mimetypes.guess_type(file_path)
if mime_type is None:
mime_type = 'audio/wav'
# Возвращаем файл как поток
def iterfile():
with open(file_path, 'rb') as f:
data = f.read(8192)
while data:
yield data
data = f.read(8192)
return StreamingResponse(
iterfile(),
media_type=mime_type,
headers={
'Content-Disposition': f'inline; filename="{filename}"',
'Accept-Ranges': 'bytes'
}
)
except HTTPException:
raise
except Exception as e:
logger.error(f"❌ Ошибка при отдаче аудио: {e}")
raise HTTPException(
status_code=500,
detail=f'Ошибка при отдаче файла: {str(e)}'
)
@audio_files_router.get("/audio/{filename}/info")
async def get_audio_info(filename: str, db: Session = Depends(get_db)):
"""
Возвращает информацию об аудиофайле
Args:
filename: Имя аудиофайла
Returns:
JSON с информацией о файле
"""
try:
# Ищем информацию в БД
audio = db.query(Audio).filter(Audio.filename == filename).first()
if not audio:
raise HTTPException(
status_code=404,
detail=f'Файл {filename} не найден в БД'
)
# Проверяем существование файла
file_path = os.path.join(AUDIOFILES_PATH, filename)
if not os.path.exists(file_path):
raise HTTPException(
status_code=404,
detail=f'Файл {filename} не найден на диске'
)
# Получаем размер файла
file_size = os.path.getsize(file_path)
# Определяем длительность (приблизительно)
# В идеале использовать библиотеку типа mutagen или soundfile
duration = None
try:
import wave
with wave.open(file_path, 'r') as wav_file:
frames = wav_file.getnframes()
rate = wav_file.getframerate()
duration = frames / float(rate) if rate > 0 else 0
except:
pass
return {
"success": True,
"filename": filename,
"file_size_bytes": file_size,
"duration_seconds": duration,
"created_at": audio.index_date.isoformat() if audio.index_date else None,
"audio_id": str(audio.id)
}
except HTTPException:
raise
except Exception as e:
logger.error(f"❌ Ошибка при получении информации: {e}")
raise HTTPException(
status_code=500,
detail=str(e)
)
@audio_files_router.get("/audio/list")
async def list_audio_files(
db: Session = Depends(get_db),
limit: int = 100,
offset: int = 0
):
"""
Возвращает список аудиофайлов
Query Parameters:
limit: Максимальное количество файлов (default: 100)
offset: Смещение для пагинации (default: 0)
Returns:
JSON со списком файлов
"""
try:
# Получаем список файлов из БД
query = db.query(Audio).order_by(Audio.index_date.desc())
total = query.count()
audio_files = query.offset(offset).limit(limit).all()
files_info = []
for audio in audio_files:
file_path = os.path.join(AUDIOFILES_PATH, audio.filename)
exists = os.path.exists(file_path)
files_info.append({
"filename": audio.filename,
"file_size": audio.file_size,
"created_at": audio.index_date.isoformat() if audio.index_date else None,
"exists": exists,
"audio_id": str(audio.id)
})
return {
"success": True,
"total": total,
"count": len(files_info),
"files": files_info
}
except Exception as e:
logger.error(f"❌ Ошибка при получении списка файлов: {e}")
raise HTTPException(
status_code=500,
detail=str(e)
)
@audio_files_router.get("/audio/{filename}/download")
async def download_audio_file(filename: str):
"""
Возвращает аудиофайл для скачивания
Args:
filename: Имя аудиофайла
Returns:
FileResponse для скачивания
"""
try:
# Формируем путь к файлу
file_path = os.path.join(AUDIOFILES_PATH, filename)
# Проверяем существование файла
if not os.path.exists(file_path):
raise HTTPException(
status_code=404,
detail=f'Файл {filename} не найден'
)
logger.info(f"📥 Скачивание аудио: {filename}")
return FileResponse(
path=file_path,
media_type='audio/wav',
filename=filename
)
except HTTPException:
raise
except Exception as e:
logger.error(f"❌ Ошибка при скачивании: {e}")
raise HTTPException(
status_code=500,
detail=str(e)
)

2
main.py

@ -9,6 +9,7 @@ from apiApp.config import APP_TITLE, APP_VERSION, API_V1_PREFIX, UPLOAD_FOLDER,
from apiApp.database import engine, Base from apiApp.database import engine, Base
from apiApp.routers import audio_router, recognition_router from apiApp.routers import audio_router, recognition_router
from apiApp.routers.ai_conclusion_router import ai_conclusion_router from apiApp.routers.ai_conclusion_router import ai_conclusion_router
from apiApp.routers.audio_files_router import audio_files_router
# Настройка логирования # Настройка логирования
logging.basicConfig(level=logging.INFO) logging.basicConfig(level=logging.INFO)
@ -58,6 +59,7 @@ async def startup_event():
app.include_router(audio_router, prefix=API_V1_PREFIX, tags=["audio"]) app.include_router(audio_router, prefix=API_V1_PREFIX, tags=["audio"])
app.include_router(recognition_router, prefix=API_V1_PREFIX, tags=["recognition"]) app.include_router(recognition_router, prefix=API_V1_PREFIX, tags=["recognition"])
app.include_router(ai_conclusion_router, prefix=API_V1_PREFIX, tags=["ai_conclusion"]) app.include_router(ai_conclusion_router, prefix=API_V1_PREFIX, tags=["ai_conclusion"])
app.include_router(audio_files_router, prefix=API_V1_PREFIX, tags=["audio_files"])
# Статические файлы (для загрузки аудио) # Статические файлы (для загрузки аудио)
app.mount("/uploads", StaticFiles(directory=str(UPLOAD_FOLDER)), name="uploads") app.mount("/uploads", StaticFiles(directory=str(UPLOAD_FOLDER)), name="uploads")

Loading…
Cancel
Save