remove gitkeep from uploads; try to fix issues

This commit is contained in:
ALIHAN DIKEL
2025-03-10 14:22:30 +03:00
parent a4d3ebdff1
commit 80c51b6306
5 changed files with 127 additions and 40 deletions

View File

@@ -6,6 +6,7 @@ h11==0.14.0
httptools==0.6.4
idna==3.10
Jinja2==3.1.6
loguru==0.7.3
MarkupSafe==3.0.2
pillow==11.1.0
pydantic==2.10.6
@@ -22,3 +23,4 @@ uvloop==0.21.0
watchfiles==1.0.4
websockets==15.0.1
wheel==0.45.1
yt-dlp==2025.2.19

View File

@@ -1,5 +1,7 @@
import asyncio
import shutil
import json
from contextlib import asynccontextmanager
from fastapi import FastAPI, UploadFile, File, HTTPException, Request, WebSocket, WebSocketDisconnect
from fastapi.responses import HTMLResponse
@@ -7,9 +9,16 @@ from fastapi.staticfiles import StaticFiles
from fastapi.templating import Jinja2Templates
from config import UPLOAD_DIR, ALLOWED_EXTENSIONS, STATIC_DIR, TEMPLATES_DIR
from worker import audio_processor, FileStatus
app = FastAPI(title="Transcriptor")
@asynccontextmanager
async def lifespan(app: FastAPI):
audio_processor.start() # Startup code
yield
audio_processor.stop() # Shutdown code
app = FastAPI(title="Transcriptor", lifespan=lifespan)
active_connections = []
app.mount("/static", StaticFiles(directory=STATIC_DIR), name="static")

View File

@@ -82,15 +82,6 @@
color: #777;
font-size: 0.9em;
}
#refreshButton {
background-color: #5bc0de;
margin-left: 10px;
padding: 5px 10px;
font-size: 0.9em;
}
#refreshButton:hover {
background-color: #46b8da;
}
.connection-status {
font-size: 0.8em;
font-weight: normal;
@@ -115,7 +106,7 @@
<body>
<h1>Audio File Upload</h1>
<p>Upload your MP3 or WAV audio files</p>
<div class="upload-form">
<form id="uploadForm">
<div class="form-group">
@@ -125,12 +116,12 @@
<button type="submit">Upload</button>
</form>
</div>
<div id="result" style="display: none;"></div>
<!-- File List Dashboard -->
<div class="file-dashboard">
<h2>Uploaded Files <span id="connectionStatus" class="connection-status">Connecting...</span></h2>
<h2>Uploaded Files <span id="connectionStatus" class="connection-status connecting">Connecting...</span></h2>
<div id="fileList" class="file-list">
<p>Loading files...</p>
</div>
@@ -140,43 +131,43 @@
// File upload handling
document.getElementById('uploadForm').addEventListener('submit', async (e) => {
e.preventDefault();
const fileInput = document.getElementById('audioFile');
const file = fileInput.files[0];
if (!file) {
showResult('Please select a file.', false);
return;
}
// Check file extension
const fileName = file.name;
const fileExt = fileName.split('.').pop().toLowerCase();
if (!['mp3', 'wav'].includes(fileExt)) {
showResult('Only MP3 and WAV files are allowed.', false);
return;
}
// Create form data
const formData = new FormData();
formData.append('file', file);
try {
const response = await fetch('/upload', {
method: 'POST',
body: formData
});
const result = await response.json();
if (response.ok) {
if (result.status === "duplicate") {
showResult(`File "${result.filename}" already exists in uploads directory!`, false);
} else {
showResult(`File "${result.filename}" uploaded successfully!`, true);
fileInput.value = ''; // Clear the input
// No need to manually refresh - WebSocket will handle it
}
} else {
@@ -186,35 +177,35 @@
showResult(`Upload failed: ${error.message}`, false);
}
});
function showResult(message, isSuccess) {
const resultDiv = document.getElementById('result');
resultDiv.textContent = message;
resultDiv.className = isSuccess ? 'success' : 'error';
resultDiv.style.display = 'block';
// Hide the message after 5 seconds
setTimeout(() => {
resultDiv.style.display = 'none';
}, 5000);
}
// File list handling
let socket = null;
function connectWebSocket() {
// Close any existing connection
if (socket) {
socket.close();
}
// Create WebSocket connection
const protocol = window.location.protocol === 'https:' ? 'wss:' : 'ws:';
const wsUrl = `${protocol}//${window.location.host}/ws`;
socket = new WebSocket(wsUrl);
const statusEl = document.getElementById('connectionStatus');
// Connection opened
socket.addEventListener('open', (event) => {
statusEl.textContent = 'Connected';
@@ -222,7 +213,7 @@
// Request initial file list
socket.send('getFiles');
});
// Listen for messages
socket.addEventListener('message', (event) => {
try {
@@ -232,7 +223,7 @@
console.error('Error parsing WebSocket message:', error);
}
});
// Connection closed
socket.addEventListener('close', (event) => {
statusEl.textContent = 'Disconnected - Reconnecting...';
@@ -240,7 +231,7 @@
// Try to reconnect after a delay
setTimeout(connectWebSocket, 3000);
});
// Connection error
socket.addEventListener('error', (event) => {
console.error('WebSocket error:', event);
@@ -248,15 +239,15 @@
statusEl.className = 'connection-status disconnected';
});
}
function updateFileList(files) {
const fileListElement = document.getElementById('fileList');
if (!files || files.length === 0) {
fileListElement.innerHTML = '<p>No files uploaded yet.</p>';
return;
}
let html = '';
files.forEach(file => {
// Format the file size
@@ -266,20 +257,20 @@
const fileSizeMB = (fileSizeKB / 1024).toFixed(1);
fileSizeStr = fileSizeMB + ' MB';
}
// Format the date
const date = new Date(file.created * 1000);
const dateStr = date.toLocaleString();
html += `<div class="file-item">
<div class="file-name">${file.name}</div>
<div class="file-meta">Size: ${fileSizeStr} | Uploaded: ${dateStr}</div>
</div>`;
});
fileListElement.innerHTML = html;
}
// Initialize WebSocket connection when page loads
document.addEventListener('DOMContentLoaded', connectWebSocket);
</script>

View File

85
src/worker.py Normal file
View File

@@ -0,0 +1,85 @@
# src/worker.py
import asyncio
import time
from pathlib import Path
from typing import Dict, List, Set, Optional
from enum import Enum
from loguru import logger
from config import UPLOAD_DIR
class FileStatus(Enum):
PENDING = "pending"
PROCESSING = "processing"
COMPLETED = "completed"
FAILED = "failed"
class AudioProcessor:
def __init__(self):
self.file_status: Dict[str, FileStatus] = {}
self.is_running = False
self._task: Optional[asyncio.Task] = None
def start(self):
"""Start the background worker"""
if not self._task or self._task.done():
self.is_running = True
self._task = asyncio.create_task(self._monitor_files())
def stop(self):
"""Stop the background worker"""
self.is_running = False
if self._task and not self._task.done():
self._task.cancel()
async def _monitor_files(self):
"""Monitor the uploads folder for new files"""
while self.is_running:
# Check for new files
for file_path in UPLOAD_DIR.iterdir():
if file_path.is_file() and file_path.suffix.lower() in ['.mp3', '.wav']:
filename = file_path.name
if filename not in self.file_status:
# New file found, mark as pending
self.file_status[filename] = FileStatus.PENDING
# Sleep before next check
await asyncio.sleep(2)
async def process_file(self, filename: str) -> bool:
"""Process a specific audio file"""
file_path = UPLOAD_DIR / filename
# Check if file exists and is valid
if not file_path.exists():
return False
# Update status
self.file_status[filename] = FileStatus.PROCESSING
try:
# TODO: Implement actual processing logic here
await asyncio.sleep(3) # For now, just simulate processing with a delay
# Mark as completed
self.file_status[filename] = FileStatus.COMPLETED
return True
except Exception as e:
self.file_status[filename] = FileStatus.FAILED
logger.error(f"Error processing {filename}: {e}")
return False
def get_status(self, filename: str) -> FileStatus:
"""Get the status of a file"""
return self.file_status.get(filename, FileStatus.PENDING)
def get_all_statuses(self) -> Dict[str, str]:
"""Get status of all files"""
return {name: status.value for name, status in self.file_status.items()}
# Create a global instance of the processor
audio_processor = AudioProcessor()