Fix NAS playback: Strict HTTP protocol (no HLS), pre-flight checks, and Content-Length
This commit is contained in:
parent
7bc230a8fd
commit
2a0a919294
2 changed files with 40 additions and 22 deletions
|
|
@ -637,6 +637,21 @@ async def stream_audio(id: str):
|
||||||
'extractor_args': {'youtube': {'player_client': ['ios', 'android']}},
|
'extractor_args': {'youtube': {'player_client': ['ios', 'android']}},
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if not stream_url:
|
||||||
|
print(f"DEBUG: Fetching new stream URL for '{id}'")
|
||||||
|
url = f"https://www.youtube.com/watch?v={id}"
|
||||||
|
ydl_opts = {
|
||||||
|
'format': 'bestaudio[ext=m4a][protocol^=http]/bestaudio[protocol^=http]/best[protocol^=http]', # Strictly exclude m3u8/HLS
|
||||||
|
'quiet': True,
|
||||||
|
'noplaylist': True,
|
||||||
|
'nocheckcertificate': True,
|
||||||
|
'geo_bypass': True,
|
||||||
|
'socket_timeout': 30,
|
||||||
|
'retries': 3,
|
||||||
|
'force_ipv4': True,
|
||||||
|
'extractor_args': {'youtube': {'player_client': ['android', 'web', 'ios']}}, # Android often gives good progressive streams
|
||||||
|
}
|
||||||
|
|
||||||
try:
|
try:
|
||||||
with yt_dlp.YoutubeDL(ydl_opts) as ydl:
|
with yt_dlp.YoutubeDL(ydl_opts) as ydl:
|
||||||
info = ydl.extract_info(url, download=False)
|
info = ydl.extract_info(url, download=False)
|
||||||
|
|
@ -649,7 +664,7 @@ async def stream_audio(id: str):
|
||||||
elif ext == 'webm':
|
elif ext == 'webm':
|
||||||
mime_type = "audio/webm"
|
mime_type = "audio/webm"
|
||||||
else:
|
else:
|
||||||
mime_type = "audio/mpeg" # Fallback
|
mime_type = "audio/mpeg"
|
||||||
|
|
||||||
print(f"DEBUG: Got stream URL format: {info.get('format')}, ext: {ext}, mime: {mime_type}")
|
print(f"DEBUG: Got stream URL format: {info.get('format')}, ext: {ext}, mime: {mime_type}")
|
||||||
except Exception as ydl_error:
|
except Exception as ydl_error:
|
||||||
|
|
@ -665,22 +680,35 @@ async def stream_audio(id: str):
|
||||||
|
|
||||||
print(f"Streaming {id} with Content-Type: {mime_type}")
|
print(f"Streaming {id} with Content-Type: {mime_type}")
|
||||||
|
|
||||||
|
# Pre-open the connection to verify it works and get headers
|
||||||
|
try:
|
||||||
|
external_req = requests.get(stream_url, stream=True, timeout=30)
|
||||||
|
external_req.raise_for_status() # Check for 403/404 immediately
|
||||||
|
except requests.exceptions.HTTPError as http_err:
|
||||||
|
print(f"DEBUG: Stream Pre-flight HTTP Error: {http_err}")
|
||||||
|
if http_err.response.status_code == 403:
|
||||||
|
cache.delete(cache_key)
|
||||||
|
raise HTTPException(status_code=500, detail="Upstream stream error")
|
||||||
|
except Exception as e:
|
||||||
|
print(f"DEBUG: Stream Connection Error: {e}")
|
||||||
|
raise HTTPException(status_code=500, detail="Stream connection failed")
|
||||||
|
|
||||||
|
# Forward Content-Length if available for progress bars
|
||||||
|
headers = {}
|
||||||
|
if "Content-Length" in external_req.headers:
|
||||||
|
headers["Content-Length"] = external_req.headers["Content-Length"]
|
||||||
|
|
||||||
def iterfile():
|
def iterfile():
|
||||||
try:
|
try:
|
||||||
with requests.get(stream_url, stream=True, timeout=30) as r:
|
# Use the already open request
|
||||||
r.raise_for_status()
|
for chunk in external_req.iter_content(chunk_size=64*1024):
|
||||||
for chunk in r.iter_content(chunk_size=64*1024):
|
yield chunk
|
||||||
yield chunk
|
external_req.close()
|
||||||
except requests.exceptions.HTTPError as http_err:
|
|
||||||
print(f"DEBUG: Stream HTTP Error: {http_err}")
|
|
||||||
if http_err.response.status_code == 403:
|
|
||||||
cache.delete(cache_key)
|
|
||||||
raise
|
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
print(f"DEBUG: Stream Iterator Error: {e}")
|
print(f"DEBUG: Stream Iterator Error: {e}")
|
||||||
raise
|
pass
|
||||||
|
|
||||||
return StreamingResponse(iterfile(), media_type=mime_type)
|
return StreamingResponse(iterfile(), media_type=mime_type, headers=headers)
|
||||||
|
|
||||||
except HTTPException:
|
except HTTPException:
|
||||||
raise
|
raise
|
||||||
|
|
|
||||||
|
|
@ -9,13 +9,3 @@ services:
|
||||||
|
|
||||||
volumes:
|
volumes:
|
||||||
- ./data:/app/backend/data
|
- ./data:/app/backend/data
|
||||||
|
|
||||||
watchtower:
|
|
||||||
image: containrrr/watchtower
|
|
||||||
container_name: spotify-watchtower
|
|
||||||
restart: always
|
|
||||||
volumes:
|
|
||||||
- /var/run/docker.sock:/var/run/docker.sock
|
|
||||||
command: --interval 3600 --cleanup
|
|
||||||
environment:
|
|
||||||
- WATCHTOWER_INCLUDE_RESTARTING=true
|
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue