|
|
|
@ -162,6 +162,11 @@ def process_audio_file(audio_id: str, db: Session): |
|
|
|
file_size = os.path.getsize(file_path) |
|
|
|
file_size = os.path.getsize(file_path) |
|
|
|
logger.info(f"📁 Файл найден: {file_path} (размер: {file_size} bytes)") |
|
|
|
logger.info(f"📁 Файл найден: {file_path} (размер: {file_size} bytes)") |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
# Проверяем размер файла - минимум 1000 bytes (1KB) для аудио |
|
|
|
|
|
|
|
if file_size < 1000: |
|
|
|
|
|
|
|
logger.warning(f"⚠️ Файл слишком маленький для аудио ({file_size} bytes), пропускаем: {audio.filename}") |
|
|
|
|
|
|
|
return |
|
|
|
|
|
|
|
|
|
|
|
# Формируем запрос в GigaAM API |
|
|
|
# Формируем запрос в GigaAM API |
|
|
|
# Пробуем асинхронный endpoint, если не работает - fallback на обычный |
|
|
|
# Пробуем асинхронный endpoint, если не работает - fallback на обычный |
|
|
|
from apiApp.config import GIGAAM_API_URL |
|
|
|
from apiApp.config import GIGAAM_API_URL |
|
|
|
@ -267,6 +272,12 @@ async def process_all_pending_audio( |
|
|
|
logger.warning(f"⚠️ Файл не найден на диске: {audio.filename}") |
|
|
|
logger.warning(f"⚠️ Файл не найден на диске: {audio.filename}") |
|
|
|
continue |
|
|
|
continue |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
# Проверяем размер файла |
|
|
|
|
|
|
|
file_size = os.path.getsize(file_path) |
|
|
|
|
|
|
|
if file_size < 1000: |
|
|
|
|
|
|
|
logger.warning(f"⚠️ Файл слишком маленький ({file_size} bytes), пропускаем: {audio.filename}") |
|
|
|
|
|
|
|
continue |
|
|
|
|
|
|
|
|
|
|
|
# Добавляем в фон (асинхронно) |
|
|
|
# Добавляем в фон (асинхронно) |
|
|
|
# В FastAPI используем BackgroundTasks |
|
|
|
# В FastAPI используем BackgroundTasks |
|
|
|
# Но нужно создавать новую сессию для каждого таска |
|
|
|
# Но нужно создавать новую сессию для каждого таска |
|
|
|
@ -374,10 +385,20 @@ async def get_audio_stats(db: Session = Depends(get_db)): |
|
|
|
all_audio = db.query(Audio).all() |
|
|
|
all_audio = db.query(Audio).all() |
|
|
|
existing_count = 0 |
|
|
|
existing_count = 0 |
|
|
|
missing_files = [] |
|
|
|
missing_files = [] |
|
|
|
|
|
|
|
small_files = [] # Файлы меньше 1KB |
|
|
|
|
|
|
|
|
|
|
|
for audio in all_audio: |
|
|
|
for audio in all_audio: |
|
|
|
file_path = os.path.join(AUDIOFILES_PATH, audio.filename) |
|
|
|
file_path = os.path.join(AUDIOFILES_PATH, audio.filename) |
|
|
|
if os.path.exists(file_path): |
|
|
|
if os.path.exists(file_path): |
|
|
|
existing_count += 1 |
|
|
|
existing_count += 1 |
|
|
|
|
|
|
|
file_size = os.path.getsize(file_path) |
|
|
|
|
|
|
|
if file_size < 1000: |
|
|
|
|
|
|
|
small_files.append({ |
|
|
|
|
|
|
|
"audio_id": str(audio.id), |
|
|
|
|
|
|
|
"filename": audio.filename, |
|
|
|
|
|
|
|
"file_size": file_size, |
|
|
|
|
|
|
|
"index_date": audio.index_date.isoformat() if audio.index_date else None |
|
|
|
|
|
|
|
}) |
|
|
|
else: |
|
|
|
else: |
|
|
|
missing_files.append({ |
|
|
|
missing_files.append({ |
|
|
|
"audio_id": str(audio.id), |
|
|
|
"audio_id": str(audio.id), |
|
|
|
@ -390,14 +411,19 @@ async def get_audio_stats(db: Session = Depends(get_db)): |
|
|
|
"with_conclusion": with_conclusion, |
|
|
|
"with_conclusion": with_conclusion, |
|
|
|
"without_conclusion": without_conclusion, |
|
|
|
"without_conclusion": without_conclusion, |
|
|
|
"existing_on_disk": existing_count, |
|
|
|
"existing_on_disk": existing_count, |
|
|
|
"missing_on_disk": total_audio - existing_count |
|
|
|
"missing_on_disk": total_audio - existing_count, |
|
|
|
|
|
|
|
"small_files_count": len(small_files) |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
# Добавляем список отсутствующих файлов (первые 50) |
|
|
|
# Добавляем списки проблемных файлов (первые 50 каждого типа) |
|
|
|
if missing_files: |
|
|
|
if missing_files: |
|
|
|
stats["missing_files_sample"] = missing_files[:50] |
|
|
|
stats["missing_files_sample"] = missing_files[:50] |
|
|
|
logger.warning(f"⚠️ Найдено {len(missing_files)} отсутствующих файлов") |
|
|
|
logger.warning(f"⚠️ Найдено {len(missing_files)} отсутствующих файлов") |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
if small_files: |
|
|
|
|
|
|
|
stats["small_files_sample"] = small_files[:50] |
|
|
|
|
|
|
|
logger.warning(f"⚠️ Найдено {len(small_files)} файлов меньше 1KB") |
|
|
|
|
|
|
|
|
|
|
|
return stats |
|
|
|
return stats |
|
|
|
|
|
|
|
|
|
|
|
except Exception as e: |
|
|
|
except Exception as e: |
|
|
|
@ -408,3 +434,71 @@ async def get_audio_stats(db: Session = Depends(get_db)): |
|
|
|
) |
|
|
|
) |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
@audio_management_router.delete("/audio/cleanup") |
|
|
|
|
|
|
|
async def cleanup_invalid_audio_files( |
|
|
|
|
|
|
|
delete_missing: bool = False, |
|
|
|
|
|
|
|
delete_small: bool = True, |
|
|
|
|
|
|
|
min_size_bytes: int = 1000, |
|
|
|
|
|
|
|
db: Session = Depends(get_db) |
|
|
|
|
|
|
|
): |
|
|
|
|
|
|
|
""" |
|
|
|
|
|
|
|
Удаляет записи Audio для проблемных файлов |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
Query Parameters: |
|
|
|
|
|
|
|
delete_missing: Удалять записи с отсутствующими файлами (default: False) |
|
|
|
|
|
|
|
delete_small: Удалять записи с маленькими файлами (default: True) |
|
|
|
|
|
|
|
min_size_bytes: Минимальный размер файла в bytes (default: 1000) |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
Returns: |
|
|
|
|
|
|
|
Статистику удаления |
|
|
|
|
|
|
|
""" |
|
|
|
|
|
|
|
try: |
|
|
|
|
|
|
|
all_audio = db.session.query(Audio).all() |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
deleted_missing = 0 |
|
|
|
|
|
|
|
deleted_small = 0 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
for audio in all_audio: |
|
|
|
|
|
|
|
file_path = os.path.join(AUDIOFILES_PATH, audio.filename) |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
# Проверяем отсутствие файла |
|
|
|
|
|
|
|
if delete_missing and not os.path.exists(file_path): |
|
|
|
|
|
|
|
logger.info(f"🗑️ Удаление записи с отсутствующим файлом: {audio.filename}") |
|
|
|
|
|
|
|
db.session.delete(audio) |
|
|
|
|
|
|
|
deleted_missing += 1 |
|
|
|
|
|
|
|
continue |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
# Проверяем размер файла |
|
|
|
|
|
|
|
if delete_small and os.path.exists(file_path): |
|
|
|
|
|
|
|
file_size = os.path.getsize(file_path) |
|
|
|
|
|
|
|
if file_size < min_size_bytes: |
|
|
|
|
|
|
|
logger.info(f"🗑️ Удаление записи с маленьким файлом ({file_size} bytes): {audio.filename}") |
|
|
|
|
|
|
|
# Удаляем и файл тоже |
|
|
|
|
|
|
|
try: |
|
|
|
|
|
|
|
os.remove(file_path) |
|
|
|
|
|
|
|
logger.info(f" Файл удалён: {file_path}") |
|
|
|
|
|
|
|
except Exception as e: |
|
|
|
|
|
|
|
logger.warning(f" Не удалось удалить файл: {e}") |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
db.session.delete(audio) |
|
|
|
|
|
|
|
deleted_small += 1 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
db.session.commit() |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
return { |
|
|
|
|
|
|
|
"success": True, |
|
|
|
|
|
|
|
"deleted_missing": deleted_missing, |
|
|
|
|
|
|
|
"deleted_small": deleted_small, |
|
|
|
|
|
|
|
"total_deleted": deleted_missing + deleted_small, |
|
|
|
|
|
|
|
"message": f"Удалено {deleted_missing + deleted_small} записей" |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
except Exception as e: |
|
|
|
|
|
|
|
db.session.rollback() |
|
|
|
|
|
|
|
logger.error(f"❌ Ошибка при очистке: {e}") |
|
|
|
|
|
|
|
raise HTTPException( |
|
|
|
|
|
|
|
status_code=500, |
|
|
|
|
|
|
|
detail=str(e) |
|
|
|
|
|
|
|
) |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|