Add Windows and portable installation support for Python path resolution
- Add resolvePythonPath() function that handles:
- PYTHON_PATH env var override (highest priority)
- Portable installations (python_embeded/python.exe)
- Standard venv with correct paths per OS:
- Windows: .venv/Scripts/python.exe
- Unix: .venv/bin/python
- Remove hardcoded Unix paths from acestep.ts and generate.ts
- Remove hardcoded /home/ambsd default path
Fixes "ENOENT" errors on Windows when spawning Python processes.
This commit is contained in:
@@ -14,6 +14,7 @@ import {
|
|||||||
cleanupJob,
|
cleanupJob,
|
||||||
getJobRawResponse,
|
getJobRawResponse,
|
||||||
downloadAudioToBuffer,
|
downloadAudioToBuffer,
|
||||||
|
resolvePythonPath,
|
||||||
} from '../services/acestep.js';
|
} from '../services/acestep.js';
|
||||||
import { getStorageProvider } from '../services/storage/factory.js';
|
import { getStorageProvider } from '../services/storage/factory.js';
|
||||||
|
|
||||||
@@ -557,12 +558,12 @@ router.post('/format', authMiddleware, async (req: AuthenticatedRequest, res: Re
|
|||||||
|
|
||||||
const { spawn } = await import('child_process');
|
const { spawn } = await import('child_process');
|
||||||
|
|
||||||
const ACESTEP_DIR = process.env.ACESTEP_PATH || '/home/ambsd/Desktop/aceui/ACE-Step-1.5';
|
const ACESTEP_DIR = process.env.ACESTEP_PATH || path.resolve(path.dirname(fileURLToPath(import.meta.url)), '../../../../ACE-Step-1.5');
|
||||||
const __filename = fileURLToPath(import.meta.url);
|
const __filename = fileURLToPath(import.meta.url);
|
||||||
const __dirname = path.dirname(__filename);
|
const __dirname = path.dirname(__filename);
|
||||||
const SCRIPTS_DIR = path.join(__dirname, '../../scripts');
|
const SCRIPTS_DIR = path.join(__dirname, '../../scripts');
|
||||||
const FORMAT_SCRIPT = path.join(SCRIPTS_DIR, 'format_sample.py');
|
const FORMAT_SCRIPT = path.join(SCRIPTS_DIR, 'format_sample.py');
|
||||||
const pythonPath = path.join(ACESTEP_DIR, '.venv', 'bin', 'python');
|
const pythonPath = resolvePythonPath(ACESTEP_DIR);
|
||||||
|
|
||||||
const args = [
|
const args = [
|
||||||
FORMAT_SCRIPT,
|
FORMAT_SCRIPT,
|
||||||
|
|||||||
@@ -1,5 +1,6 @@
|
|||||||
import { writeFile, mkdir, copyFile, rm, stat } from 'fs/promises';
|
import { writeFile, mkdir, copyFile, rm, stat, access } from 'fs/promises';
|
||||||
import { spawn, execSync } from 'child_process';
|
import { spawn, execSync } from 'child_process';
|
||||||
|
import { existsSync } from 'fs';
|
||||||
import path from 'path';
|
import path from 'path';
|
||||||
|
|
||||||
// Get audio duration using ffprobe
|
// Get audio duration using ffprobe
|
||||||
@@ -35,6 +36,29 @@ function resolveAceStepPath(): string {
|
|||||||
return path.resolve(__dirname, '../../../../ACE-Step-1.5');
|
return path.resolve(__dirname, '../../../../ACE-Step-1.5');
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Resolve Python path cross-platform (supports venv and portable installations)
|
||||||
|
export function resolvePythonPath(baseDir: string): string {
|
||||||
|
// Allow explicit override via env var
|
||||||
|
if (process.env.PYTHON_PATH) {
|
||||||
|
return process.env.PYTHON_PATH;
|
||||||
|
}
|
||||||
|
|
||||||
|
const isWindows = process.platform === 'win32';
|
||||||
|
const pythonExe = isWindows ? 'python.exe' : 'python';
|
||||||
|
|
||||||
|
// Check for portable installation first (python_embeded)
|
||||||
|
const portablePath = path.join(baseDir, 'python_embeded', pythonExe);
|
||||||
|
if (existsSync(portablePath)) {
|
||||||
|
return portablePath;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Standard venv path (different structure on Windows vs Unix)
|
||||||
|
if (isWindows) {
|
||||||
|
return path.join(baseDir, '.venv', 'Scripts', pythonExe);
|
||||||
|
}
|
||||||
|
return path.join(baseDir, '.venv', 'bin', 'python');
|
||||||
|
}
|
||||||
|
|
||||||
const ACESTEP_DIR = resolveAceStepPath();
|
const ACESTEP_DIR = resolveAceStepPath();
|
||||||
const SCRIPTS_DIR = path.join(__dirname, '../../scripts');
|
const SCRIPTS_DIR = path.join(__dirname, '../../scripts');
|
||||||
const PYTHON_SCRIPT = path.join(SCRIPTS_DIR, 'simple_generate.py');
|
const PYTHON_SCRIPT = path.join(SCRIPTS_DIR, 'simple_generate.py');
|
||||||
@@ -431,8 +455,7 @@ interface PythonResult {
|
|||||||
|
|
||||||
function runPythonGeneration(scriptArgs: string[]): Promise<PythonResult> {
|
function runPythonGeneration(scriptArgs: string[]): Promise<PythonResult> {
|
||||||
return new Promise((resolve) => {
|
return new Promise((resolve) => {
|
||||||
// Use the ACE-Step venv's Python directly
|
const pythonPath = resolvePythonPath(ACESTEP_DIR);
|
||||||
const pythonPath = path.join(ACESTEP_DIR, '.venv', 'bin', 'python');
|
|
||||||
const args = [PYTHON_SCRIPT, ...scriptArgs];
|
const args = [PYTHON_SCRIPT, ...scriptArgs];
|
||||||
|
|
||||||
const proc = spawn(pythonPath, args, {
|
const proc = spawn(pythonPath, args, {
|
||||||
|
|||||||
Reference in New Issue
Block a user