Загрузка данных


@app.get("/stream/spotify/{spotify_id}")
async def stream_spotify(spotify_id: str):
    """
    Высокоскоростной автономный MP3-стриминг ДЛЯ ВСЕХ ПЕСЕН МИРА через spotDL.
    Принудительно скармливает под капот spotDL рантайм Deno через правильный флаг --yt-dlp-args!
    Отдает чистые байты MP3 в ОЗУ со строгим Content-Length (копия логики SoundCloud).
    """
    try:
        import os
        import io
        import tempfile
        import shutil
        import glob

        # Шаг 1. Автоматически зачищаем мусорный префикс sp:, если он прилетел от мобильного плеера
        if ":" in spotify_id:
            spotify_id = spotify_id.split(":")[-1]

        # Собираем прямую, легальную веб-ссылку на трек Спотифая для скачивания
        spotify_track_url = f"https://open.spotify.com/track/{spotify_id}"
        clean_url = spotify_track_url.replace(" ", "")

        # Шаг 2. Создаем изолированную временную папку на сервере
        with tempfile.TemporaryDirectory() as tmpdir:

            # Настраиваем переменные окружения, чтобы spotDL, yt-dlp и FFmpeg четко видели друг друга
            env = os.environ.copy()
            env["PATH"] = "/usr/local/bin:/usr/bin:/bin:" + env.get("PATH", "")

            # Шаг 3. Запускаем spotDL с жестким указанием аудио-провайдеров и ПРАВИЛЬНЫМ флагом --yt-dlp-args!
            # Это мгновенно расшифрует сигнатуры Ютуба для резерва и намертво уничтожит синтаксический краш!
            process = await asyncio.create_subprocess_exec(
                "spotdl", "download", clean_url,
                "--format", "mp3",                 # Жестко требуем чистейший MP3
                "--output", f"{tmpdir}",           # Качаем прямо в корень временной папки
                "--no-cache",                      # Отключаем мусорный кэш
                "--audio", "soundcloud", "youtube-music", # Сначала SoundCloud, затем Ютуб!
                "--yt-dlp-args", "--js-runtimes deno",    # ИСПРАВЛЕНО НА ОФИЦИАЛЬНЫЙ ФЛАГ ТВОЕЙ СПРАВКИ!
                stdout=asyncio.subprocess.PIPE,
                stderr=asyncio.subprocess.PIPE,
                env=env
            )
            stdout, stderr = await process.communicate()

            # Ищем абсолютно любой файл с расширением .mp3 внутри нашей папки
            mp3_files = glob.glob(os.path.join(tmpdir, "**", "*.mp3"), recursive=True)

            # ЮВЕЛИРНЫЙ ФИКС: берем первый найденный MP3-файл из списка под индексом 0
            if not mp3_files or os.path.getsize(mp3_files[0]) == 0:
                err_msg = stderr.decode('utf-8', errors='ignore').strip()
                out_msg = stdout.decode('utf-8', errors='ignore').strip()
                raise HTTPException(
                    status_code=404, 
                    detail=f"spotDL не смог сгенерировать MP3-файл. Ошибка: {err_msg} | Вывод: {out_msg}"
                )
                
            # Шаг 4. Читаем готовые байты НАЙДЕННОГО MP3-файла напрямую в оперативную память сервера
            target_file = mp3_files[0]
            with open(target_file, "rb") as f:
                mp3_bytes = f.read()


        # Шаг 5. Отдаем монолитный MP3 файл со строгим размером Content-Length (ОДИН В ОДИН КАК У SOUNDCLOUD!)
        from fastapi import Response
        return Response(
            content=mp3_bytes,
            media_type="audio/mpeg",
            headers={
                "Accept-Ranges": "bytes",
                "Content-Length": str(len(mp3_bytes)),  # Считаем точный вес файла до последнего бита!
                "Cache-Control": "public, max-age=252460800",
                "Access-Control-Allow-Origin": "*"
            }
        )

    except HTTPException:
        raise
    except Exception as e:
        import traceback
        raise HTTPException(status_code=500, detail=f"Ошибка spotDL движка: {str(e)} | Log: {traceback.format_exc()}")