mirror of
https://github.com/wahyd4/you-music.git
synced 2026-08-08 20:59:47 +10:00
Fix error
This commit is contained in:
@@ -1,5 +1,5 @@
|
||||
from fastapi import APIRouter, Depends, HTTPException, UploadFile, File, Query
|
||||
from fastapi.responses import FileResponse
|
||||
from fastapi import APIRouter, Depends, HTTPException, UploadFile, File, Query, Request
|
||||
from fastapi.responses import FileResponse, StreamingResponse
|
||||
from sqlalchemy.ext.asyncio import AsyncSession
|
||||
from sqlalchemy import select, or_
|
||||
from typing import List, Optional
|
||||
@@ -7,6 +7,7 @@ import os
|
||||
import shutil
|
||||
from pathlib import Path
|
||||
import re
|
||||
import logging
|
||||
|
||||
from app.db.session import get_db
|
||||
from app.models.models import Music
|
||||
@@ -15,6 +16,7 @@ from app.services.downloader import music_downloader
|
||||
from app.core.config import settings
|
||||
|
||||
router = APIRouter()
|
||||
logger = logging.getLogger(__name__)
|
||||
|
||||
|
||||
def normalize_artist_name(artist: str) -> str:
|
||||
@@ -398,14 +400,16 @@ async def scan_music_directory(db: AsyncSession = Depends(get_db)):
|
||||
@router.get("/file/{music_id}")
|
||||
async def serve_music_file(
|
||||
music_id: int,
|
||||
request: Request,
|
||||
db: AsyncSession = Depends(get_db)
|
||||
):
|
||||
"""Serve music file - handles both regular and local music directory files"""
|
||||
"""Serve music file with Range request support for audio streaming"""
|
||||
# Get music record
|
||||
result = await db.execute(select(Music).where(Music.id == music_id))
|
||||
music = result.scalar_one_or_none()
|
||||
|
||||
if not music:
|
||||
logger.error(f"Music ID {music_id} not found in database")
|
||||
raise HTTPException(status_code=404, detail="Music not found")
|
||||
|
||||
# Determine file path
|
||||
@@ -418,16 +422,79 @@ async def serve_music_file(
|
||||
|
||||
# Check if file exists
|
||||
if not os.path.exists(file_path):
|
||||
raise HTTPException(status_code=404, detail="File not found on disk")
|
||||
logger.error(f"File not found on disk: {file_path} (Music ID: {music_id})")
|
||||
raise HTTPException(status_code=404, detail=f"File not found: {music.file_path}")
|
||||
|
||||
# Return file
|
||||
# Map file extensions to proper MIME types
|
||||
mime_type_map = {
|
||||
'mp3': 'audio/mpeg',
|
||||
'mp4': 'audio/mp4',
|
||||
'm4a': 'audio/mp4',
|
||||
'wav': 'audio/wav',
|
||||
'flac': 'audio/flac',
|
||||
'ogg': 'audio/ogg',
|
||||
'opus': 'audio/opus',
|
||||
'webm': 'audio/webm',
|
||||
'aac': 'audio/aac',
|
||||
}
|
||||
|
||||
# Get MIME type based on file extension
|
||||
file_ext = music.file_format or os.path.splitext(file_path)[1].lstrip('.')
|
||||
media_type = mime_type_map.get(file_ext.lower(), 'audio/mpeg')
|
||||
|
||||
logger.info(f"Serving music file: {file_path} (ID: {music_id}, MIME: {media_type})")
|
||||
|
||||
# Return file with proper headers for audio streaming
|
||||
return FileResponse(
|
||||
path=file_path,
|
||||
media_type=f"audio/{music.file_format or 'mpeg'}",
|
||||
filename=os.path.basename(file_path)
|
||||
media_type=media_type,
|
||||
filename=os.path.basename(file_path),
|
||||
headers={
|
||||
'Accept-Ranges': 'bytes',
|
||||
'Cache-Control': 'public, max-age=3600',
|
||||
}
|
||||
)
|
||||
|
||||
|
||||
@router.get("/file/{music_id}/check")
|
||||
async def check_music_file(
|
||||
music_id: int,
|
||||
db: AsyncSession = Depends(get_db)
|
||||
):
|
||||
"""Check if music file exists and is accessible (diagnostic endpoint)"""
|
||||
# Get music record
|
||||
result = await db.execute(select(Music).where(Music.id == music_id))
|
||||
music = result.scalar_one_or_none()
|
||||
|
||||
if not music:
|
||||
return {
|
||||
"exists": False,
|
||||
"error": "Music record not found in database",
|
||||
"music_id": music_id
|
||||
}
|
||||
|
||||
# Determine file path
|
||||
if music.file_location and os.path.isabs(music.file_location):
|
||||
file_path = music.file_location
|
||||
else:
|
||||
file_path = os.path.join(settings.MUSIC_DIR, music.file_path)
|
||||
|
||||
file_exists = os.path.exists(file_path)
|
||||
|
||||
return {
|
||||
"exists": file_exists,
|
||||
"music_id": music_id,
|
||||
"title": music.title,
|
||||
"file_path": music.file_path,
|
||||
"full_path": file_path,
|
||||
"file_location": music.file_location,
|
||||
"file_format": music.file_format,
|
||||
"music_dir": settings.MUSIC_DIR,
|
||||
"file_size": os.path.getsize(file_path) if file_exists else None,
|
||||
"is_readable": os.access(file_path, os.R_OK) if file_exists else False,
|
||||
}
|
||||
|
||||
|
||||
@router.get("/share/{share_token}", response_model=MusicSchema)
|
||||
async def get_music_by_share_token(share_token: str, db: AsyncSession = Depends(get_db)):
|
||||
"""Get music by share token (public endpoint) - checks expiration"""
|
||||
|
||||
+38
-2
@@ -132,9 +132,45 @@ function App() {
|
||||
// Check if it's a streaming URL
|
||||
const isStreamUrl = currentMusic.file_path.startsWith('/api/stream') || currentMusic.file_path.startsWith('http')
|
||||
// Use dedicated file serving endpoint for all local files
|
||||
audioRef.current.src = isStreamUrl ? currentMusic.file_path : `/api/music/file/${currentMusic.id}`
|
||||
const audioSrc = isStreamUrl ? currentMusic.file_path : `/api/music/file/${currentMusic.id}`
|
||||
|
||||
console.log(`Loading audio: ${currentMusic.title} (ID: ${currentMusic.id})`)
|
||||
console.log(`Audio source: ${audioSrc}`)
|
||||
|
||||
audioRef.current.src = audioSrc
|
||||
|
||||
// Add error handler to help debug loading issues
|
||||
const handleError = (e: Event) => {
|
||||
console.error('Audio loading error:', {
|
||||
musicId: currentMusic.id,
|
||||
title: currentMusic.title,
|
||||
src: audioSrc,
|
||||
error: (e.target as HTMLAudioElement)?.error,
|
||||
networkState: (e.target as HTMLAudioElement)?.networkState,
|
||||
readyState: (e.target as HTMLAudioElement)?.readyState,
|
||||
})
|
||||
|
||||
// Try fallback to direct /music/ path if API endpoint fails
|
||||
if (!isStreamUrl && audioRef.current && !audioRef.current.src.includes('/music/')) {
|
||||
const fallbackSrc = `/music/${currentMusic.file_path}`
|
||||
console.log(`Trying fallback source: ${fallbackSrc}`)
|
||||
audioRef.current.src = fallbackSrc
|
||||
if (isPlaying) {
|
||||
audioRef.current.play().catch(err => console.error('Fallback play error:', err))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
audioRef.current.addEventListener('error', handleError)
|
||||
|
||||
if (isPlaying) {
|
||||
audioRef.current.play()
|
||||
audioRef.current.play().catch(err => {
|
||||
console.error('Play error:', err)
|
||||
})
|
||||
}
|
||||
|
||||
return () => {
|
||||
audioRef.current?.removeEventListener('error', handleError)
|
||||
}
|
||||
}
|
||||
}, [currentMusic])
|
||||
|
||||
Reference in New Issue
Block a user