Improve compatibility and add one-click startup scripts

- Add Windows Portable Package support with auto-detection
- Fix API health check to support multiple response formats
- Fix task ID parsing for ACE-Step API integration
- Change thinking mode default to false for 4GB GPU compatibility
- Add explicit CoT parameter control for LLM features
- Fix audio download path encoding for portable package
- Improve file upload validation with extension fallback
- Add start-all.bat/sh scripts for one-click startup
- Update README with Windows Portable Package instructions
- Add comprehensive troubleshooting section
- Improve cross-platform compatibility
This commit is contained in:
fspecii
2026-02-04 16:59:45 +02:00
parent f9e4601792
commit cde2ff6865
8 changed files with 404 additions and 22 deletions
+3
View File
@@ -90,3 +90,6 @@ comfyui/
# External editors (wavacity is 184MB - clone separately if needed) # External editors (wavacity is 184MB - clone separately if needed)
wavacity-editor/ wavacity-editor/
# Script logs
logs/
+74 -9
View File
@@ -144,16 +144,57 @@
| Requirement | Specification | | Requirement | Specification |
|-------------|---------------| |-------------|---------------|
| **Node.js** | 18 or higher | | **Node.js** | 18 or higher |
| **Python** | 3.10+ (3.11 recommended) | | **Python** | 3.10+ (3.11 recommended) OR Windows Portable Package |
| **NVIDIA GPU** | 8GB+ VRAM (12GB+ recommended) | | **NVIDIA GPU** | 4GB+ VRAM (works without LLM), 12GB+ recommended (with LLM) |
| **CUDA** | 12.8 (for Windows Portable Package) |
| **FFmpeg** | For audio processing | | **FFmpeg** | For audio processing |
| **uv** | Python package manager (recommended) | | **uv** | Python package manager (recommended for standard install) |
--- ---
## ⚡ Quick Start ## ⚡ Quick Start
### Linux / macOS ### 🪟 Windows - One-Click Start (Easiest!)
```batch
cd ace-step-ui
start-all.bat
```
**That's it!** This starts everything: API + Backend + Frontend in one command.
> **Note:** By default, it looks for ACE-Step in `..\ACE-Step-1.5`.
> If yours is elsewhere, set `ACESTEP_PATH` first:
> ```batch
> set ACESTEP_PATH=C:\path\to\ACE-Step-1.5
> start-all.bat
> ```
### 🪟 Windows - Manual Start
```batch
REM 1. Start ACE-Step API
cd C:\ACE-Step-1.5
python_embeded\python acestep\api_server.py
REM 2. Start ACE-Step UI (in another terminal)
cd ace-step-ui
start.bat
```
### Linux / macOS - One-Click Start (Easiest!)
```bash
cd ace-step-ui
./start-all.sh
```
**That's it!** This starts everything: API + Backend + Frontend in one command.
> **Note:** By default, it looks for ACE-Step in `../ACE-Step-1.5`.
> If yours is elsewhere, set `ACESTEP_PATH` first:
> ```bash
> export ACESTEP_PATH=/path/to/ACE-Step-1.5
> ./start-all.sh
> ```
> **To stop:** `./stop-all.sh`
### Linux / macOS - Manual Start
```bash ```bash
# 1. Start ACE-Step API (in ACE-Step-1.5 directory) # 1. Start ACE-Step API (in ACE-Step-1.5 directory)
cd /path/to/ACE-Step-1.5 cd /path/to/ACE-Step-1.5
@@ -164,7 +205,7 @@ cd ace-step-ui
./start.sh ./start.sh
``` ```
### Windows ### Windows (Standard Installation)
```batch ```batch
REM 1. Start ACE-Step API (in ACE-Step-1.5 directory) REM 1. Start ACE-Step API (in ACE-Step-1.5 directory)
cd C:\path\to\ACE-Step-1.5 cd C:\path\to\ACE-Step-1.5
@@ -183,6 +224,22 @@ Open **http://localhost:3000** and start creating!
### 1. Install ACE-Step (The AI Engine) ### 1. Install ACE-Step (The AI Engine)
#### 🪟 Windows Portable Package (Recommended for Windows)
**The easiest way to get started on Windows!** This package includes everything pre-configured:
1. **Download** [ACE-Step-1.5.7z](https://files.acemusic.ai/acemusic/win/ACE-Step-1.5.7z) (~5GB)
2. **Extract** to `C:\ACE-Step-1.5` (or your preferred location)
3. **Done!** The package includes `python_embeded` with all dependencies
**Works with 4GB GPU** - No LLM installation required
**CUDA 12.8** included
**Zero setup hassle**
> **Note:** Thinking Mode (LLM features) is automatically disabled on GPUs with <12GB VRAM. You can still enable it manually if you have 12GB+.
#### Standard Installation (All Platforms)
```bash ```bash
# Clone ACE-Step 1.5 - the open source Suno alternative # Clone ACE-Step 1.5 - the open source Suno alternative
git clone https://github.com/ace-step/ACE-Step-1.5 git clone https://github.com/ace-step/ACE-Step-1.5
@@ -242,13 +299,19 @@ copy server\.env.example server\.env
### Step 1: Start ACE-Step API Server ### Step 1: Start ACE-Step API Server
**🪟 Windows Portable Package:**
```batch
cd C:\ACE-Step-1.5
python_embeded\python acestep\api_server.py
```
**Linux / macOS:** **Linux / macOS:**
```bash ```bash
cd /path/to/ACE-Step-1.5 cd /path/to/ACE-Step-1.5
uv run acestep-api --port 8001 uv run acestep-api --port 8001
``` ```
**Windows:** **Windows (Standard Installation):**
```batch ```batch
cd C:\path\to\ACE-Step-1.5 cd C:\path\to\ACE-Step-1.5
uv run acestep-api --port 8001 uv run acestep-api --port 8001
@@ -334,9 +397,11 @@ Full control over every parameter:
| Issue | Solution | | Issue | Solution |
|-------|----------| |-------|----------|
| **ACE-Step API not reachable** | Ensure `uv run acestep-api --port 8001` is running | | **ACE-Step API not reachable** | Ensure API server is running (see Usage section) |
| **CUDA out of memory** | Close other GPU apps, reduce duration | | **CUDA out of memory** | Close other GPU apps, reduce duration, or disable Thinking Mode |
| **Songs show 0:00 duration** | Install FFmpeg: `sudo apt install ffmpeg` | | **4GB GPU - Out of memory** | Make sure **Thinking Mode is OFF** (it's off by default). LLM features require 12GB+ |
| **AttributeError: 'NoneType'** | Update to latest ACE-Step-1.5 (fix merged in PR #109) |
| **Songs show 0:00 duration** | Install FFmpeg: `sudo apt install ffmpeg` (Linux) or download from [ffmpeg.org](https://ffmpeg.org) (Windows) |
| **LAN access not working** | Check firewall allows ports 3000 and 3001 | | **LAN access not working** | Check firewall allows ports 3000 and 3001 |
--- ---
+1 -1
View File
@@ -102,7 +102,7 @@ export const CreatePanel: React.FC<CreatePanelProps> = ({ onGenerate, isGenerati
const [guidanceScale, setGuidanceScale] = useState(7.0); const [guidanceScale, setGuidanceScale] = useState(7.0);
const [randomSeed, setRandomSeed] = useState(true); const [randomSeed, setRandomSeed] = useState(true);
const [seed, setSeed] = useState(-1); const [seed, setSeed] = useState(-1);
const [thinking, setThinking] = useState(true); const [thinking, setThinking] = useState(false); // Default false for GPU compatibility
const [audioFormat, setAudioFormat] = useState<'mp3' | 'flac'>('mp3'); const [audioFormat, setAudioFormat] = useState<'mp3' | 'flac'>('mp3');
const [inferenceSteps, setInferenceSteps] = useState(8); const [inferenceSteps, setInferenceSteps] = useState(8);
const [inferMethod, setInferMethod] = useState<'ode' | 'sde'>('ode'); const [inferMethod, setInferMethod] = useState<'ode' | 'sde'>('ode');
+10 -2
View File
@@ -26,6 +26,9 @@ const audioUpload = multer({
fileFilter: (_req, file, cb) => { fileFilter: (_req, file, cb) => {
const allowedTypes = [ const allowedTypes = [
'audio/mpeg', 'audio/mpeg',
'audio/mp3', // Alternative MIME type for MP3
'audio/mpeg3',
'audio/x-mpeg-3',
'audio/wav', 'audio/wav',
'audio/x-wav', 'audio/x-wav',
'audio/flac', 'audio/flac',
@@ -35,10 +38,15 @@ const audioUpload = multer({
'audio/ogg', 'audio/ogg',
'audio/webm', 'audio/webm',
]; ];
if (allowedTypes.includes(file.mimetype)) {
// Also check file extension as fallback
const allowedExtensions = ['.mp3', '.wav', '.flac', '.m4a', '.aac', '.ogg', '.webm', '.opus'];
const fileExt = file.originalname.toLowerCase().match(/\.[^.]+$/)?.[0];
if (allowedTypes.includes(file.mimetype) || (fileExt && allowedExtensions.includes(fileExt))) {
cb(null, true); cb(null, true);
} else { } else {
cb(new Error('Invalid file type. Only common audio formats are allowed.')); cb(new Error(`Invalid file type. Only common audio formats are allowed. Received: ${file.mimetype} (${file.originalname})`));
} }
} }
}); });
+14 -4
View File
@@ -92,7 +92,7 @@ async function isApiAvailable(): Promise<boolean> {
if (response.ok) { if (response.ok) {
const data = await response.json(); const data = await response.json();
apiAvailableCache = data.status === 'ok' || data.healthy === true; apiAvailableCache = data.status === 'ok' || data.healthy === true || data.data?.status === 'ok';
console.log(`[ACE-Step] API available at ${ACESTEP_API}: ${apiAvailableCache}`); console.log(`[ACE-Step] API available at ${ACESTEP_API}: ${apiAvailableCache}`);
return apiAvailableCache; return apiAvailableCache;
} }
@@ -133,6 +133,10 @@ async function submitToApi(params: GenerationParams): Promise<{ taskId: string }
vocal_language: params.vocalLanguage || 'en', vocal_language: params.vocalLanguage || 'en',
use_random_seed: params.randomSeed !== false, use_random_seed: params.randomSeed !== false,
shift: params.shift ?? 3.0, shift: params.shift ?? 3.0,
thinking: params.thinking ?? false, // Respect frontend choice, default false for GPU compatibility
use_cot_caption: false, // Explicitly disable CoT features that require LLM
use_cot_language: false, // Explicitly disable CoT features that require LLM
use_cot_metas: false, // Explicitly disable CoT features that require LLM
}; };
if (params.bpm && params.bpm > 0) body.bpm = params.bpm; if (params.bpm && params.bpm > 0) body.bpm = params.bpm;
@@ -148,13 +152,16 @@ async function submitToApi(params: GenerationParams): Promise<{ taskId: string }
if (params.repaintingEnd !== undefined && params.repaintingEnd > 0) body.repainting_end = params.repaintingEnd; if (params.repaintingEnd !== undefined && params.repaintingEnd > 0) body.repainting_end = params.repaintingEnd;
if (params.audioCoverStrength !== undefined && params.audioCoverStrength !== 1.0) body.audio_cover_strength = params.audioCoverStrength; if (params.audioCoverStrength !== undefined && params.audioCoverStrength !== 1.0) body.audio_cover_strength = params.audioCoverStrength;
if (params.instruction) body.instruction = params.instruction; if (params.instruction) body.instruction = params.instruction;
if (params.thinking) body.thinking = true; // LLM and CoT parameters only sent when thinking mode is enabled
if (params.thinking) {
if (params.lmTemperature !== undefined) body.lm_temperature = params.lmTemperature; if (params.lmTemperature !== undefined) body.lm_temperature = params.lmTemperature;
if (params.lmCfgScale !== undefined) body.lm_cfg_scale = params.lmCfgScale; if (params.lmCfgScale !== undefined) body.lm_cfg_scale = params.lmCfgScale;
if (params.lmTopK !== undefined && params.lmTopK > 0) body.lm_top_k = params.lmTopK; if (params.lmTopK !== undefined && params.lmTopK > 0) body.lm_top_k = params.lmTopK;
if (params.lmTopP !== undefined) body.lm_top_p = params.lmTopP; if (params.lmTopP !== undefined) body.lm_top_p = params.lmTopP;
if (params.useCotCaption !== undefined) body.use_cot_caption = params.useCotCaption; if (params.useCotCaption !== undefined) body.use_cot_caption = params.useCotCaption;
if (params.useCotLanguage !== undefined) body.use_cot_language = params.useCotLanguage; if (params.useCotLanguage !== undefined) body.use_cot_language = params.useCotLanguage;
if (params.useCotMetas !== undefined) body.use_cot_metas = params.useCotMetas;
}
if (params.useAdg) body.use_adg = true; if (params.useAdg) body.use_adg = true;
if (params.cfgIntervalStart !== undefined && params.cfgIntervalStart > 0) body.cfg_interval_start = params.cfgIntervalStart; if (params.cfgIntervalStart !== undefined && params.cfgIntervalStart > 0) body.cfg_interval_start = params.cfgIntervalStart;
if (params.cfgIntervalEnd !== undefined && params.cfgIntervalEnd < 1.0) body.cfg_interval_end = params.cfgIntervalEnd; if (params.cfgIntervalEnd !== undefined && params.cfgIntervalEnd < 1.0) body.cfg_interval_end = params.cfgIntervalEnd;
@@ -187,7 +194,7 @@ async function submitToApi(params: GenerationParams): Promise<{ taskId: string }
} }
const result = await response.json(); const result = await response.json();
const taskId = result.data?.job_id || result.job_id; const taskId = result.data?.task_id || result.data?.job_id || result.job_id || result.task_id;
if (!taskId) { if (!taskId) {
throw new Error('No task ID returned from API'); throw new Error('No task ID returned from API');
} }
@@ -260,7 +267,10 @@ async function pollApiResult(taskId: string, maxWaitMs = 600000): Promise<ApiTas
// Download audio from API // Download audio from API
async function downloadAudioFromApi(audioPath: string, destPath: string): Promise<void> { async function downloadAudioFromApi(audioPath: string, destPath: string): Promise<void> {
const url = `${ACESTEP_API}/v1/audio?path=${encodeURIComponent(audioPath)}`; // Check if audioPath is already a relative URL (starts with /v1/audio)
const url = audioPath.startsWith('/v1/audio')
? `${ACESTEP_API}${audioPath}`
: `${ACESTEP_API}/v1/audio?path=${encodeURIComponent(audioPath)}`;
const response = await fetch(url); const response = await fetch(url);
if (!response.ok) { if (!response.ok) {
+112
View File
@@ -0,0 +1,112 @@
@echo off
REM ACE-Step UI Complete Startup Script for Windows
REM Starts ACE-Step API + Backend + Frontend
setlocal
echo ==================================
echo ACE-Step Complete Startup
echo ==================================
echo.
REM Check if node_modules exists
if not exist "node_modules" (
echo Error: UI dependencies not installed!
echo Please run setup.bat first.
pause
exit /b 1
)
if not exist "server\node_modules" (
echo Error: Server dependencies not installed!
echo Please run setup.bat first.
pause
exit /b 1
)
REM Get ACE-Step path from environment or use default
if "%ACESTEP_PATH%"=="" (
set ACESTEP_PATH=..\ACE-Step-1.5
)
REM Check if ACE-Step exists
if not exist "%ACESTEP_PATH%" (
echo.
echo Warning: ACE-Step not found at %ACESTEP_PATH%
echo.
echo Please set ACESTEP_PATH or place ACE-Step-1.5 next to ace-step-ui
echo Example: set ACESTEP_PATH=C:\ACE-Step-1.5
echo.
pause
exit /b 1
)
REM Detect ACE-Step installation type
set API_COMMAND=
if exist "%ACESTEP_PATH%\python_embeded\python.exe" (
echo [+] Detected Windows Portable Package
set API_COMMAND=python_embeded\python acestep\api_server.py
) else (
echo [+] Detected Standard Installation
set API_COMMAND=uv run acestep-api --port 8001
)
REM Get local IP for LAN access
for /f "tokens=2 delims=:" %%a in ('ipconfig ^| findstr /c:"IPv4"') do (
for /f "tokens=1" %%b in ("%%a") do (
set LOCAL_IP=%%b
)
)
echo.
echo ==================================
echo Starting All Services...
echo ==================================
echo.
REM Start ACE-Step API in new window
echo [1/3] Starting ACE-Step API server...
start "ACE-Step API Server" cmd /k "cd /d "%ACESTEP_PATH%" && %API_COMMAND%"
REM Wait for API to start
echo Waiting for API to initialize...
timeout /t 5 /nobreak >nul
REM Start backend in new window
echo [2/3] Starting backend server...
start "ACE-Step UI Backend" cmd /k "cd /d "%~dp0server" && npm run dev"
REM Wait for backend to start
echo Waiting for backend to start...
timeout /t 3 /nobreak >nul
REM Start frontend in new window
echo [3/3] Starting frontend...
start "ACE-Step UI Frontend" cmd /k "cd /d "%~dp0" && npm run dev"
REM Wait a moment
timeout /t 2 /nobreak >nul
echo.
echo ==================================
echo All Services Running!
echo ==================================
echo.
echo ACE-Step API: http://localhost:8001
echo Backend: http://localhost:3001
echo Frontend: http://localhost:3000
echo.
if defined LOCAL_IP (
echo LAN Access: http://%LOCAL_IP%:3000
echo.
)
echo Close the terminal windows to stop all services.
echo.
echo ==================================
echo.
echo Opening browser...
timeout /t 3 /nobreak >nul
start http://localhost:3000
echo.
echo Press any key to close this window (services will keep running)
pause >nul
+151
View File
@@ -0,0 +1,151 @@
#!/bin/bash
# ACE-Step UI Complete Startup Script for Linux/macOS
# Starts ACE-Step API + Backend + Frontend
set -e
echo "=================================="
echo " ACE-Step Complete Startup"
echo "=================================="
echo
# Check if node_modules exists
if [ ! -d "node_modules" ]; then
echo "Error: UI dependencies not installed!"
echo "Please run ./setup.sh first."
exit 1
fi
if [ ! -d "server/node_modules" ]; then
echo "Error: Server dependencies not installed!"
echo "Please run ./setup.sh first."
exit 1
fi
# Get ACE-Step path from environment or use default
ACESTEP_PATH="${ACESTEP_PATH:-../ACE-Step-1.5}"
# Check if ACE-Step exists
if [ ! -d "$ACESTEP_PATH" ]; then
echo
echo "Warning: ACE-Step not found at $ACESTEP_PATH"
echo
echo "Please set ACESTEP_PATH or place ACE-Step-1.5 next to ace-step-ui"
echo "Example: export ACESTEP_PATH=/path/to/ACE-Step-1.5"
echo
exit 1
fi
# Get local IP for LAN access
if command -v ip &> /dev/null; then
LOCAL_IP=$(ip route get 1.1.1.1 2>/dev/null | grep -oP 'src \K\S+' || echo "")
elif command -v ifconfig &> /dev/null; then
LOCAL_IP=$(ifconfig | grep "inet " | grep -v 127.0.0.1 | awk '{print $2}' | head -n1)
fi
echo
echo "=================================="
echo " Starting All Services..."
echo "=================================="
echo
# Create log directory
mkdir -p logs
# Start ACE-Step API in background
echo "[1/3] Starting ACE-Step API server..."
cd "$ACESTEP_PATH"
uv run acestep-api --port 8001 > "../ace-step-ui/logs/api.log" 2>&1 &
API_PID=$!
cd - > /dev/null
# Wait for API to start
echo "Waiting for API to initialize..."
sleep 5
# Check if API started successfully
if ! kill -0 $API_PID 2>/dev/null; then
echo "Error: API failed to start. Check logs/api.log"
exit 1
fi
# Start backend in background
echo "[2/3] Starting backend server..."
cd server
npm run dev > ../logs/backend.log 2>&1 &
BACKEND_PID=$!
cd ..
# Wait for backend to start
echo "Waiting for backend to start..."
sleep 3
# Check if backend started successfully
if ! kill -0 $BACKEND_PID 2>/dev/null; then
echo "Error: Backend failed to start. Check logs/backend.log"
kill $API_PID 2>/dev/null
exit 1
fi
# Start frontend in background
echo "[3/3] Starting frontend..."
npm run dev > logs/frontend.log 2>&1 &
FRONTEND_PID=$!
# Wait a moment
sleep 2
# Check if frontend started successfully
if ! kill -0 $FRONTEND_PID 2>/dev/null; then
echo "Error: Frontend failed to start. Check logs/frontend.log"
kill $API_PID $BACKEND_PID 2>/dev/null
exit 1
fi
echo
echo "=================================="
echo " All Services Running!"
echo "=================================="
echo
echo " ACE-Step API: http://localhost:8001"
echo " Backend: http://localhost:3001"
echo " Frontend: http://localhost:3000"
echo
if [ -n "$LOCAL_IP" ]; then
echo " LAN Access: http://$LOCAL_IP:3000"
echo
fi
echo " Logs: ./logs/"
echo
echo " PIDs:"
echo " API: $API_PID"
echo " Backend: $BACKEND_PID"
echo " Frontend: $FRONTEND_PID"
echo
echo "=================================="
echo
# Save PIDs for stop script
echo "$API_PID" > logs/api.pid
echo "$BACKEND_PID" > logs/backend.pid
echo "$FRONTEND_PID" > logs/frontend.pid
echo "Opening browser..."
sleep 3
# Open browser based on OS
if command -v xdg-open &> /dev/null; then
xdg-open http://localhost:3000 &
elif command -v open &> /dev/null; then
open http://localhost:3000 &
fi
echo
echo "Services are running in background."
echo "To stop all services, run: ./stop-all.sh"
echo "Or press Ctrl+C and they will continue running."
echo
# Wait for user interrupt
trap 'echo; echo "Services still running. Use ./stop-all.sh to stop them."; exit 0' INT
wait
+33
View File
@@ -0,0 +1,33 @@
#!/bin/bash
# ACE-Step UI Stop All Services Script
echo "Stopping all ACE-Step services..."
if [ -f logs/api.pid ]; then
API_PID=$(cat logs/api.pid)
if kill -0 $API_PID 2>/dev/null; then
echo "Stopping API server (PID: $API_PID)..."
kill $API_PID
fi
rm logs/api.pid
fi
if [ -f logs/backend.pid ]; then
BACKEND_PID=$(cat logs/backend.pid)
if kill -0 $BACKEND_PID 2>/dev/null; then
echo "Stopping backend (PID: $BACKEND_PID)..."
kill $BACKEND_PID
fi
rm logs/backend.pid
fi
if [ -f logs/frontend.pid ]; then
FRONTEND_PID=$(cat logs/frontend.pid)
if kill -0 $FRONTEND_PID 2>/dev/null; then
echo "Stopping frontend (PID: $FRONTEND_PID)..."
kill $FRONTEND_PID
fi
rm logs/frontend.pid
fi
echo "All services stopped!"