fix(frontend): frontend functional bugs #9
+39
-2
@@ -5,7 +5,12 @@ from fastapi import APIRouter, HTTPException
|
||||
from backend.config import settings
|
||||
from backend.services.file_manager import FileManager
|
||||
from backend.services.task_manager import task_manager
|
||||
from backend.ffmpeg import get_stream_info
|
||||
|
||||
# Import core functions
|
||||
from audio_splitter.ffmpeg import get_stream_info, get_container_format, get_audio_codec
|
||||
from audio_splitter.formats import determine_default_format
|
||||
from audio_splitter.constants import FORMAT_INFO
|
||||
from audio_splitter.defaults import DEFAULT_FORMAT
|
||||
|
||||
router = APIRouter(prefix="/api", tags=["info"])
|
||||
|
||||
@@ -13,7 +18,8 @@ router = APIRouter(prefix="/api", tags=["info"])
|
||||
@router.get("/info/{task_id}")
|
||||
async def get_task_info(task_id: str):
|
||||
"""
|
||||
Return stream information (has_audio, has_video, has_subtitle) for the uploaded file.
|
||||
Return stream information (has_audio, has_video, has_subtitle, audio_codec)
|
||||
for the uploaded file.
|
||||
"""
|
||||
if not task_manager.has_task(task_id):
|
||||
raise HTTPException(status_code=404, detail=f"Task {task_id} not found")
|
||||
@@ -33,3 +39,34 @@ async def get_task_info(task_id: str):
|
||||
}
|
||||
except Exception as e:
|
||||
raise HTTPException(status_code=500, detail=f"Failed to retrieve stream info: {str(e)}")
|
||||
|
||||
|
||||
@router.get("/info/recommended-format/{task_id}")
|
||||
async def get_recommended_format(task_id: str):
|
||||
"""
|
||||
Return the recommended output format (container name) for the uploaded file,
|
||||
based on its container and audio codec.
|
||||
"""
|
||||
if not task_manager.has_task(task_id):
|
||||
raise HTTPException(status_code=404, detail=f"Task {task_id} not found")
|
||||
|
||||
input_path = FileManager.get_input_path(task_id)
|
||||
if not input_path or not input_path.exists():
|
||||
raise HTTPException(status_code=404, detail="Input file not found")
|
||||
|
||||
try:
|
||||
container = get_container_format(str(input_path))
|
||||
codec = get_audio_codec(str(input_path))
|
||||
|
||||
fmt = determine_default_format(container, codec)
|
||||
|
||||
# Fallback if detection fails or format is unsupported
|
||||
if fmt is None:
|
||||
fmt = DEFAULT_FORMAT
|
||||
if fmt not in FORMAT_INFO:
|
||||
fmt = "mp3" # ultimate fallback
|
||||
|
||||
return {"format": fmt}
|
||||
|
||||
except Exception as e:
|
||||
raise HTTPException(status_code=500, detail=f"Failed to determine format: {str(e)}")
|
||||
|
||||
@@ -63,3 +63,8 @@ export const getTaskInfo = async (task_id: string): Promise<{
|
||||
const response = await api.get(`/info/${task_id}`)
|
||||
return response.data
|
||||
}
|
||||
|
||||
export const getRecommendedFormat = async (task_id: string): Promise<{ format: string }> => {
|
||||
const response = await api.get(`/info/recommended-format/${task_id}`)
|
||||
return response.data
|
||||
}
|
||||
|
||||
@@ -3,7 +3,8 @@ import { useDropzone } from 'react-dropzone'
|
||||
import { Box, Typography, Paper, LinearProgress, Alert } from '@mui/material'
|
||||
import { CloudUpload, InsertDriveFile } from '@mui/icons-material'
|
||||
import { useUploadStore } from '../stores/uploadStore'
|
||||
import { uploadFile, getTaskInfo } from '../api/client'
|
||||
import { useOptionsStore } from '../stores/optionsStore' // NEW
|
||||
import { uploadFile, getTaskInfo, getRecommendedFormat } from '../api/client' // NEW
|
||||
import { useTaskStore } from '../stores/taskStore'
|
||||
|
||||
const ALLOWED_EXTENSIONS = ['.mp3', '.flac', '.wav', '.m4a', '.ogg', '.opus', '.aac', '.wma', '.aiff', '.alac', '.ac3']
|
||||
@@ -30,6 +31,7 @@ export const UploadZone: React.FC = () => {
|
||||
} = useUploadStore()
|
||||
|
||||
const { setTaskId: setTaskIdStore } = useTaskStore()
|
||||
const { setOptions } = useOptionsStore() // NEW
|
||||
|
||||
const onDrop = useCallback(
|
||||
async (acceptedFiles: File[]) => {
|
||||
@@ -65,9 +67,18 @@ export const UploadZone: React.FC = () => {
|
||||
setHasAudio(info.has_audio)
|
||||
setHasSubtitle(info.has_subtitle)
|
||||
setAudioCodec(info.audio_codec)
|
||||
|
||||
// Fetch recommended format and update options
|
||||
try {
|
||||
const rec = await getRecommendedFormat(taskId)
|
||||
// Update only the format; keep other options (e.g., transcode_to) as defaults
|
||||
setOptions({ format: rec.format })
|
||||
} catch (err) {
|
||||
console.warn('Failed to fetch recommended format, using default', err)
|
||||
}
|
||||
} catch (err) {
|
||||
console.error('Failed to fetch stream info:', err)
|
||||
// Don't block the upload flow if this fails; we'll just assume no video
|
||||
// Don't block upload flow; user can manually change options
|
||||
}
|
||||
} catch (err: any) {
|
||||
setError(err.response?.data?.detail || err.message || 'Upload failed')
|
||||
@@ -78,7 +89,7 @@ export const UploadZone: React.FC = () => {
|
||||
setFileSize(0)
|
||||
}
|
||||
},
|
||||
[setFile, setFileName, setFileSize, setIsUploading, setUploadProgress, setError, setTaskId, setTaskIdStore]
|
||||
[setFile, setFileName, setFileSize, setIsUploading, setUploadProgress, setError, setTaskId, setTaskIdStore, setHasVideo, setHasAudio, setHasSubtitle, setAudioCodec, setOptions]
|
||||
)
|
||||
|
||||
const { getRootProps, getInputProps, isDragActive } = useDropzone({
|
||||
|
||||
Reference in New Issue
Block a user