Spaces:
Sleeping
Sleeping
Update server.js
Browse files
server.js
CHANGED
|
@@ -29,87 +29,51 @@ const upload = multer({
|
|
| 29 |
limits: { fileSize: 50 * 1024 * 1024 }
|
| 30 |
});
|
| 31 |
|
| 32 |
-
//
|
| 33 |
const EFFECTS = {
|
| 34 |
lofi: {
|
| 35 |
-
name: "LoFi Hip Hop
|
| 36 |
-
|
| 37 |
-
command: `
|
| 38 |
-
-af "asetrate=44100*0.92,atempo=1.087,lowpass=f=4200:p=1,highpass=f=85:p=1,bass=g=6:f=95:w=0.4,treble=g=-4:f=8000:w=0.6,equalizer=f=250:t=h:width=180:g=-2.5,equalizer=f=1000:t=h:width=500:g=1.5,equalizer=f=3500:t=h:width=1500:g=-1.8,equalizer=f=8000:t=h:width=2500:g=-4,acompressor=threshold=-22dB:ratio=3.5:attack=8:release=140:makeup=3,afftdn=nf=-28:tn=1,acrusher=bits=13:mix=0.28:mode=log:aa=0.5,vibrato=f=0.22:d=0.45,aphaser=in_gain=0.55:out_gain=0.85:delay=2.8:decay=0.45:speed=0.48,aecho=0.55:0.68:48:0.28,aecho=0.45:0.58:95:0.18,extrastereo=m=1.5,volume=1.15,alimiter=level_in=1:level_out=0.95:limit=0.98:attack=6:release=50"
|
| 39 |
-
-ar 44100 -b:a 256k
|
| 40 |
-
`
|
| 41 |
},
|
| 42 |
|
| 43 |
slowed_reverb: {
|
| 44 |
-
name: "Slowed + Reverb
|
| 45 |
-
|
| 46 |
-
command: `
|
| 47 |
-
-af "atempo=0.82,asetrate=44100*0.93,lowpass=f=6000:p=1,highpass=f=70:p=1,bass=g=5:f=85:w=0.5,treble=g=-3:f=7000:w=0.7,equalizer=f=150:t=h:width=120:g=4,equalizer=f=3000:t=h:width=2000:g=-2,aecho=0.75:0.82:75:0.38,aecho=0.65:0.75:145:0.28,aecho=0.55:0.68:220:0.18,reverb=roomsize=0.92:damping=0.42:wetlevel=0.48:drylevel=0.52:width=1.0,chorus=0.6:0.85:52:0.38:0.22:2,acompressor=threshold=-18dB:ratio=2.8:attack=12:release=180:makeup=2,extrastereo=m=1.8,volume=1.25,alimiter=level_in=1:level_out=0.95:limit=0.98:attack=8:release=80"
|
| 48 |
-
-ar 44100 -b:a 256k
|
| 49 |
-
`
|
| 50 |
},
|
| 51 |
|
| 52 |
nightcore: {
|
| 53 |
-
name: "Nightcore
|
| 54 |
-
|
| 55 |
-
command: `
|
| 56 |
-
-af "atempo=1.28,asetrate=44100*1.12,highpass=f=120:p=1,treble=g=5:f=6000:w=0.6,equalizer=f=1200:t=h:width=600:g=2.5,equalizer=f=4000:t=h:width=2000:g=3.5,equalizer=f=8000:t=h:width=3000:g=4,bass=g=-2:f=100:w=0.4,aexciter=level_in=1:level_out=1:amount=1.8:drive=4:blend=0.6:freq=7500:ceil=16000,acompressor=threshold=-16dB:ratio=3.2:attack=4:release=35:makeup=3,crystalizer=i=1.5:c=1,extrastereo=m=1.7,volume=1.28,alimiter=level_in=1:level_out=0.96:limit=0.99:attack=4:release=40"
|
| 57 |
-
-ar 44100 -b:a 256k
|
| 58 |
-
`
|
| 59 |
},
|
| 60 |
|
| 61 |
vaporwave: {
|
| 62 |
-
name: "Vaporwave
|
| 63 |
-
|
| 64 |
-
command: `
|
| 65 |
-
-af "asetrate=44100*0.87,atempo=1.15,lowpass=f=5500:p=1,highpass=f=90:p=1,equalizer=f=400:t=h:width=250:g=3.5,equalizer=f=2500:t=h:width=1500:g=-1.5,equalizer=f=6500:t=h:width=2000:g=-3,aphaser=in_gain=0.65:out_gain=0.82:delay=4.5:decay=0.55:speed=0.32,chorus=0.68:0.88:58:0.42:0.28:2,chorus=0.58:0.78:42:0.35:0.22:2,vibrato=f=0.18:d=0.5,reverb=roomsize=0.72:damping=0.38:wetlevel=0.38:drylevel=0.62:width=0.95,aecho=0.5:0.65:85:0.25,acompressor=threshold=-20dB:ratio=3:attack=10:release=100:makeup=2,extrastereo=m=1.6,volume=1.18,alimiter=level_in=1:level_out=0.94:limit=0.97:attack=7:release=60"
|
| 66 |
-
-ar 44100 -b:a 256k
|
| 67 |
-
`
|
| 68 |
},
|
| 69 |
|
| 70 |
"8d_audio": {
|
| 71 |
-
name: "8D Audio
|
| 72 |
-
|
| 73 |
-
command: `
|
| 74 |
-
-af "apulsator=hz=0.085:mode=sine:width=0.92,extrastereo=m=2.8:c=0,aecho=0.72:0.85:65:0.38,aecho=0.62:0.75:125:0.28,haas=level_in=1:level_out=1:side_gain=0.95:middle_source=mid:middle_phase=1,bass=g=3:f=90:w=0.45,reverb=roomsize=0.65:damping=0.5:wetlevel=0.32:drylevel=0.68:width=1.0,acompressor=threshold=-18dB:ratio=2.5:attack=8:release=90:makeup=2,volume=1.12,alimiter=level_in=1:level_out=0.95:limit=0.98:attack=5:release=50"
|
| 75 |
-
-ar 44100 -b:a 256k
|
| 76 |
-
`
|
| 77 |
},
|
| 78 |
|
| 79 |
bass_boosted: {
|
| 80 |
-
name: "Bass Boosted
|
| 81 |
-
|
| 82 |
-
command: `
|
| 83 |
-
-af "bass=g=18:f=95:w=0.35,bass=g=12:f=65:w=0.25,equalizer=f=45:t=h:width=35:g=10,equalizer=f=100:t=h:width=80:g=9,equalizer=f=250:t=h:width=150:g=6,equalizer=f=800:t=h:width=400:g=-2,equalizer=f=4000:t=h:width=2000:g=-4,acompressor=threshold=-24dB:ratio=6:attack=4:release=45:makeup=5,asubboost=dry=0.7:wet=0.3:decay=0.7:feedback=0.6:cutoff=150:slope=1,extrastereo=m=1.4,volume=1.15,alimiter=level_in=1.1:level_out=0.96:limit=0.99:attack=3:release=30:asc=1"
|
| 84 |
-
-ar 44100 -b:a 256k
|
| 85 |
-
`
|
| 86 |
},
|
| 87 |
|
| 88 |
ambient: {
|
| 89 |
-
name: "Ambient Chill
|
| 90 |
-
|
| 91 |
-
command: `
|
| 92 |
-
-af "asetrate=44100*0.96,atempo=1.042,lowpass=f=7000:p=1,highpass=f=60:p=1,equalizer=f=2000:t=h:width=1500:g=-2.5,equalizer=f=6000:t=h:width=3000:g=-4.5,reverb=roomsize=0.95:damping=0.28:wetlevel=0.55:drylevel=0.45:width=1.0,chorus=0.65:0.88:48:0.42:0.25:3,aecho=0.6:0.75:150:0.32,aecho=0.5:0.65:280:0.22,aecho=0.4:0.55:420:0.15,aphaser=in_gain=0.45:out_gain=0.72:delay=3.8:decay=0.48:speed=0.38,acompressor=threshold=-20dB:ratio=2.2:attack=15:release=200:makeup=1.5,extrastereo=m=1.8,volume=1.08,alimiter=level_in=1:level_out=0.93:limit=0.96:attack=10:release=100"
|
| 93 |
-
-ar 44100 -b:a 256k
|
| 94 |
-
`
|
| 95 |
},
|
| 96 |
|
| 97 |
tiktok_lofi: {
|
| 98 |
-
name: "TikTok LoFi
|
| 99 |
-
|
| 100 |
-
command: `
|
| 101 |
-
-af "asetrate=44100*0.90,atempo=1.111,lowpass=f=4500:p=1,highpass=f=80:p=1,bass=g=7:f=90:w=0.45,equalizer=f=200:t=h:width=150:g=-2,equalizer=f=900:t=h:width=450:g=2,equalizer=f=3200:t=h:width=1800:g=-2.5,equalizer=f=7500:t=h:width=2500:g=-5,acompressor=threshold=-20dB:ratio=4:attack=6:release=120:makeup=4,acrusher=bits=12:mix=0.32:mode=log:aa=0.5,vibrato=f=0.25:d=0.5,aphaser=in_gain=0.6:out_gain=0.88:delay=2.5:decay=0.5:speed=0.45,aecho=0.6:0.72:45:0.3,extrastereo=m=1.65,volume=1.22,alimiter=level_in=1:level_out=0.96:limit=0.99:attack=5:release=45"
|
| 102 |
-
-ar 44100 -b:a 256k
|
| 103 |
-
`
|
| 104 |
},
|
| 105 |
|
| 106 |
chill_lofi: {
|
| 107 |
-
name: "Chill LoFi
|
| 108 |
-
|
| 109 |
-
command: `
|
| 110 |
-
-af "asetrate=44100*0.94,atempo=1.064,lowpass=f=4800:p=1,highpass=f=75:p=1,bass=g=5:f=88:w=0.48,treble=g=-3.5:f=7500:w=0.65,equalizer=f=280:t=h:width=200:g=-1.8,equalizer=f=1200:t=h:width=600:g=1.2,equalizer=f=4000:t=h:width=2000:g=-2.2,acompressor=threshold=-21dB:ratio=3:attack=10:release=150:makeup=2.5,acrusher=bits=13:mix=0.25:mode=log:aa=0.5,vibrato=f=0.2:d=0.42,aecho=0.5:0.65:55:0.25,reverb=roomsize=0.55:damping=0.45:wetlevel=0.28:drylevel=0.72:width=0.85,extrastereo=m=1.5,volume=1.12,alimiter=level_in=1:level_out=0.94:limit=0.97:attack=6:release=55"
|
| 111 |
-
-ar 44100 -b:a 256k
|
| 112 |
-
`
|
| 113 |
}
|
| 114 |
};
|
| 115 |
|
|
@@ -117,22 +81,19 @@ const EFFECTS = {
|
|
| 117 |
app.get('/', (req, res) => {
|
| 118 |
res.json({
|
| 119 |
status: 'online',
|
| 120 |
-
message: 'π΅ LoFi Remix API
|
| 121 |
version: '2.0',
|
|
|
|
| 122 |
total_effects: Object.keys(EFFECTS).length,
|
| 123 |
available_effects: Object.keys(EFFECTS).map(key => ({
|
| 124 |
id: key,
|
| 125 |
-
name: EFFECTS[key].name
|
| 126 |
-
description: EFFECTS[key].description
|
| 127 |
})),
|
| 128 |
endpoints: {
|
| 129 |
health: 'GET /',
|
| 130 |
-
process: 'POST /process
|
| 131 |
download: 'GET /download/:filename',
|
| 132 |
effects: 'GET /effects'
|
| 133 |
-
},
|
| 134 |
-
usage: {
|
| 135 |
-
example: 'POST /process with multipart/form-data: audio=<file>&effect=lofi'
|
| 136 |
}
|
| 137 |
});
|
| 138 |
});
|
|
@@ -143,24 +104,21 @@ app.get('/effects', (req, res) => {
|
|
| 143 |
total: Object.keys(EFFECTS).length,
|
| 144 |
effects: Object.keys(EFFECTS).map(key => ({
|
| 145 |
id: key,
|
| 146 |
-
name: EFFECTS[key].name
|
| 147 |
-
description: EFFECTS[key].description
|
| 148 |
}))
|
| 149 |
});
|
| 150 |
});
|
| 151 |
|
| 152 |
-
// π΅ Process Audio
|
| 153 |
app.post('/process', upload.single('audio'), async (req, res) => {
|
| 154 |
try {
|
| 155 |
if (!req.file) {
|
| 156 |
return res.status(400).json({
|
| 157 |
success: false,
|
| 158 |
-
error: 'No audio file uploaded'
|
| 159 |
-
hint: 'Send audio file as multipart/form-data with key "audio"'
|
| 160 |
});
|
| 161 |
}
|
| 162 |
|
| 163 |
-
// Get effect from request (default to lofi)
|
| 164 |
const effectType = req.body.effect || 'lofi';
|
| 165 |
|
| 166 |
if (!EFFECTS[effectType]) {
|
|
@@ -168,8 +126,7 @@ app.post('/process', upload.single('audio'), async (req, res) => {
|
|
| 168 |
return res.status(400).json({
|
| 169 |
success: false,
|
| 170 |
error: `Unknown effect: ${effectType}`,
|
| 171 |
-
available_effects: Object.keys(EFFECTS)
|
| 172 |
-
hint: 'Use one of the available effect IDs'
|
| 173 |
});
|
| 174 |
}
|
| 175 |
|
|
@@ -178,23 +135,22 @@ app.post('/process', upload.single('audio'), async (req, res) => {
|
|
| 178 |
const outputPath = path.join(outputsDir, outputFilename);
|
| 179 |
|
| 180 |
console.log(`π΅ Processing: ${EFFECTS[effectType].name}`);
|
| 181 |
-
console.log(`π Input: ${req.file.originalname}`);
|
| 182 |
|
| 183 |
-
|
| 184 |
-
|
| 185 |
-
|
|
|
|
| 186 |
|
| 187 |
-
console.log(`βοΈ
|
| 188 |
|
| 189 |
-
// Execute FFmpeg
|
| 190 |
const startTime = Date.now();
|
| 191 |
-
await execPromise(ffmpegCommand
|
|
|
|
|
|
|
| 192 |
const processingTime = ((Date.now() - startTime) / 1000).toFixed(2);
|
| 193 |
|
| 194 |
-
// Clean up input file
|
| 195 |
fs.unlinkSync(inputPath);
|
| 196 |
|
| 197 |
-
// Get output file size
|
| 198 |
const stats = fs.statSync(outputPath);
|
| 199 |
const fileSizeKB = (stats.size / 1024).toFixed(2);
|
| 200 |
|
|
@@ -202,38 +158,35 @@ app.post('/process', upload.single('audio'), async (req, res) => {
|
|
| 202 |
|
| 203 |
res.json({
|
| 204 |
success: true,
|
| 205 |
-
message: `
|
|
|
|
|
|
|
| 206 |
effect: {
|
| 207 |
id: effectType,
|
| 208 |
-
name: EFFECTS[effectType].name
|
| 209 |
-
description: EFFECTS[effectType].description
|
| 210 |
},
|
| 211 |
output: {
|
| 212 |
-
|
| 213 |
-
size_kb: fileSizeKB,
|
| 214 |
-
download_url: `/download/${outputFilename}`
|
| 215 |
},
|
| 216 |
processing_time_seconds: processingTime
|
| 217 |
});
|
| 218 |
|
| 219 |
} catch (error) {
|
| 220 |
-
console.error('β
|
| 221 |
|
| 222 |
-
// Clean up on error
|
| 223 |
if (req.file && fs.existsSync(req.file.path)) {
|
| 224 |
fs.unlinkSync(req.file.path);
|
| 225 |
}
|
| 226 |
|
| 227 |
res.status(500).json({
|
| 228 |
success: false,
|
| 229 |
-
error: '
|
| 230 |
-
details: error.message
|
| 231 |
-
hint: 'Check if FFmpeg is installed and the audio file is valid'
|
| 232 |
});
|
| 233 |
}
|
| 234 |
});
|
| 235 |
|
| 236 |
-
// π₯ Download
|
| 237 |
app.get('/download/:filename', (req, res) => {
|
| 238 |
const filename = req.params.filename;
|
| 239 |
const filePath = path.join(outputsDir, filename);
|
|
@@ -241,8 +194,7 @@ app.get('/download/:filename', (req, res) => {
|
|
| 241 |
if (!fs.existsSync(filePath)) {
|
| 242 |
return res.status(404).json({
|
| 243 |
success: false,
|
| 244 |
-
error: 'File not found'
|
| 245 |
-
hint: 'File may have been auto-deleted after 10 seconds'
|
| 246 |
});
|
| 247 |
}
|
| 248 |
|
|
@@ -250,11 +202,10 @@ app.get('/download/:filename', (req, res) => {
|
|
| 250 |
|
| 251 |
res.download(filePath, filename, (err) => {
|
| 252 |
if (!err) {
|
| 253 |
-
// Auto-delete after 10 seconds
|
| 254 |
setTimeout(() => {
|
| 255 |
if (fs.existsSync(filePath)) {
|
| 256 |
fs.unlinkSync(filePath);
|
| 257 |
-
console.log(`ποΈ Cleaned
|
| 258 |
}
|
| 259 |
}, 10000);
|
| 260 |
}
|
|
@@ -263,11 +214,11 @@ app.get('/download/:filename', (req, res) => {
|
|
| 263 |
|
| 264 |
// π Start Server
|
| 265 |
app.listen(PORT, '0.0.0.0', () => {
|
| 266 |
-
console.log('βββββββββββββββββββββββββββββββββββββββ
|
| 267 |
-
console.log('π LoFi Remix API
|
| 268 |
-
console.log('βββββββββββββββββββββββββββββββββββββββ
|
| 269 |
console.log(`π Server: http://0.0.0.0:${PORT}`);
|
| 270 |
-
console.log(`
|
| 271 |
-
console.log(`
|
| 272 |
-
console.log('βββββββββββββββββββββββββββββββββββββββ
|
| 273 |
});
|
|
|
|
| 29 |
limits: { fileSize: 50 * 1024 * 1024 }
|
| 30 |
});
|
| 31 |
|
| 32 |
+
// π OPTIMIZED EFFECTS - Fast Processing
|
| 33 |
const EFFECTS = {
|
| 34 |
lofi: {
|
| 35 |
+
name: "LoFi Hip Hop",
|
| 36 |
+
command: `-filter_complex "[0:a]asetrate=44100*0.92,atempo=1.087,lowpass=f=4200,highpass=f=85,bass=g=6:f=95,treble=g=-4:f=8000,equalizer=f=250:width=180:g=-2.5,equalizer=f=1000:width=500:g=1.5,acompressor=threshold=-22dB:ratio=3.5:attack=8:release=140,vibrato=f=0.22:d=0.45,aecho=0.55:0.68:48:0.28,extrastereo=m=1.5,volume=1.15[out]" -map "[out]" -ar 44100 -b:a 192k`
|
|
|
|
|
|
|
|
|
|
|
|
|
| 37 |
},
|
| 38 |
|
| 39 |
slowed_reverb: {
|
| 40 |
+
name: "Slowed + Reverb",
|
| 41 |
+
command: `-filter_complex "[0:a]atempo=0.82,asetrate=44100*0.93,lowpass=f=6000,highpass=f=70,bass=g=5:f=85,aecho=0.75:0.82:75:0.38,aecho=0.65:0.75:145:0.28,reverb=roomsize=0.92:wetlevel=0.48,chorus=0.6:0.85:52:0.38:0.22:2,acompressor=threshold=-18dB:ratio=2.8:attack=12:release=180,extrastereo=m=1.8,volume=1.25[out]" -map "[out]" -ar 44100 -b:a 192k`
|
|
|
|
|
|
|
|
|
|
|
|
|
| 42 |
},
|
| 43 |
|
| 44 |
nightcore: {
|
| 45 |
+
name: "Nightcore",
|
| 46 |
+
command: `-filter_complex "[0:a]atempo=1.28,asetrate=44100*1.12,highpass=f=120,treble=g=5:f=6000,equalizer=f=4000:width=2000:g=3.5,equalizer=f=8000:width=3000:g=4,acompressor=threshold=-16dB:ratio=3.2:attack=4:release=35,crystalizer=i=1.5,extrastereo=m=1.7,volume=1.28[out]" -map "[out]" -ar 44100 -b:a 192k`
|
|
|
|
|
|
|
|
|
|
|
|
|
| 47 |
},
|
| 48 |
|
| 49 |
vaporwave: {
|
| 50 |
+
name: "Vaporwave",
|
| 51 |
+
command: `-filter_complex "[0:a]asetrate=44100*0.87,atempo=1.15,lowpass=f=5500,highpass=f=90,equalizer=f=400:width=250:g=3.5,equalizer=f=2500:width=1500:g=-1.5,aphaser=in_gain=0.65:out_gain=0.82:delay=4.5:decay=0.55:speed=0.32,chorus=0.68:0.88:58:0.42:0.28:2,vibrato=f=0.18:d=0.5,reverb=roomsize=0.72:wetlevel=0.38,aecho=0.5:0.65:85:0.25,acompressor=threshold=-20dB:ratio=3:attack=10:release=100,extrastereo=m=1.6,volume=1.18[out]" -map "[out]" -ar 44100 -b:a 192k`
|
|
|
|
|
|
|
|
|
|
|
|
|
| 52 |
},
|
| 53 |
|
| 54 |
"8d_audio": {
|
| 55 |
+
name: "8D Audio",
|
| 56 |
+
command: `-filter_complex "[0:a]apulsator=hz=0.085:mode=sine:width=0.92,extrastereo=m=2.8,aecho=0.72:0.85:65:0.38,haas,bass=g=3:f=90,reverb=roomsize=0.65:wetlevel=0.32,acompressor=threshold=-18dB:ratio=2.5:attack=8:release=90,volume=1.12[out]" -map "[out]" -ar 44100 -b:a 192k`
|
|
|
|
|
|
|
|
|
|
|
|
|
| 57 |
},
|
| 58 |
|
| 59 |
bass_boosted: {
|
| 60 |
+
name: "Bass Boosted",
|
| 61 |
+
command: `-filter_complex "[0:a]bass=g=18:f=95,bass=g=12:f=65,equalizer=f=45:width=35:g=10,equalizer=f=100:width=80:g=9,equalizer=f=250:width=150:g=6,acompressor=threshold=-24dB:ratio=6:attack=4:release=45,extrastereo=m=1.4,volume=1.15[out]" -map "[out]" -ar 44100 -b:a 192k`
|
|
|
|
|
|
|
|
|
|
|
|
|
| 62 |
},
|
| 63 |
|
| 64 |
ambient: {
|
| 65 |
+
name: "Ambient Chill",
|
| 66 |
+
command: `-filter_complex "[0:a]asetrate=44100*0.96,atempo=1.042,lowpass=f=7000,highpass=f=60,equalizer=f=2000:width=1500:g=-2.5,reverb=roomsize=0.95:wetlevel=0.55,chorus=0.65:0.88:48:0.42:0.25:3,aecho=0.6:0.75:150:0.32,aphaser=in_gain=0.45:out_gain=0.72:delay=3.8:decay=0.48:speed=0.38,acompressor=threshold=-20dB:ratio=2.2:attack=15:release=200,extrastereo=m=1.8,volume=1.08[out]" -map "[out]" -ar 44100 -b:a 192k`
|
|
|
|
|
|
|
|
|
|
|
|
|
| 67 |
},
|
| 68 |
|
| 69 |
tiktok_lofi: {
|
| 70 |
+
name: "TikTok LoFi",
|
| 71 |
+
command: `-filter_complex "[0:a]asetrate=44100*0.90,atempo=1.111,lowpass=f=4500,highpass=f=80,bass=g=7:f=90,equalizer=f=900:width=450:g=2,equalizer=f=7500:width=2500:g=-5,acompressor=threshold=-20dB:ratio=4:attack=6:release=120,vibrato=f=0.25:d=0.5,aphaser=in_gain=0.6:out_gain=0.88:delay=2.5:decay=0.5:speed=0.45,aecho=0.6:0.72:45:0.3,extrastereo=m=1.65,volume=1.22[out]" -map "[out]" -ar 44100 -b:a 192k`
|
|
|
|
|
|
|
|
|
|
|
|
|
| 72 |
},
|
| 73 |
|
| 74 |
chill_lofi: {
|
| 75 |
+
name: "Chill LoFi",
|
| 76 |
+
command: `-filter_complex "[0:a]asetrate=44100*0.94,atempo=1.064,lowpass=f=4800,highpass=f=75,bass=g=5:f=88,treble=g=-3.5:f=7500,equalizer=f=1200:width=600:g=1.2,acompressor=threshold=-21dB:ratio=3:attack=10:release=150,vibrato=f=0.2:d=0.42,aecho=0.5:0.65:55:0.25,reverb=roomsize=0.55:wetlevel=0.28,extrastereo=m=1.5,volume=1.12[out]" -map "[out]" -ar 44100 -b:a 192k`
|
|
|
|
|
|
|
|
|
|
|
|
|
| 77 |
}
|
| 78 |
};
|
| 79 |
|
|
|
|
| 81 |
app.get('/', (req, res) => {
|
| 82 |
res.json({
|
| 83 |
status: 'online',
|
| 84 |
+
message: 'π΅ LoFi Remix API v2.0 - Optimized',
|
| 85 |
version: '2.0',
|
| 86 |
+
performance: 'Fast processing with filter_complex',
|
| 87 |
total_effects: Object.keys(EFFECTS).length,
|
| 88 |
available_effects: Object.keys(EFFECTS).map(key => ({
|
| 89 |
id: key,
|
| 90 |
+
name: EFFECTS[key].name
|
|
|
|
| 91 |
})),
|
| 92 |
endpoints: {
|
| 93 |
health: 'GET /',
|
| 94 |
+
process: 'POST /process',
|
| 95 |
download: 'GET /download/:filename',
|
| 96 |
effects: 'GET /effects'
|
|
|
|
|
|
|
|
|
|
| 97 |
}
|
| 98 |
});
|
| 99 |
});
|
|
|
|
| 104 |
total: Object.keys(EFFECTS).length,
|
| 105 |
effects: Object.keys(EFFECTS).map(key => ({
|
| 106 |
id: key,
|
| 107 |
+
name: EFFECTS[key].name
|
|
|
|
| 108 |
}))
|
| 109 |
});
|
| 110 |
});
|
| 111 |
|
| 112 |
+
// π΅ Process Audio
|
| 113 |
app.post('/process', upload.single('audio'), async (req, res) => {
|
| 114 |
try {
|
| 115 |
if (!req.file) {
|
| 116 |
return res.status(400).json({
|
| 117 |
success: false,
|
| 118 |
+
error: 'No audio file uploaded'
|
|
|
|
| 119 |
});
|
| 120 |
}
|
| 121 |
|
|
|
|
| 122 |
const effectType = req.body.effect || 'lofi';
|
| 123 |
|
| 124 |
if (!EFFECTS[effectType]) {
|
|
|
|
| 126 |
return res.status(400).json({
|
| 127 |
success: false,
|
| 128 |
error: `Unknown effect: ${effectType}`,
|
| 129 |
+
available_effects: Object.keys(EFFECTS)
|
|
|
|
| 130 |
});
|
| 131 |
}
|
| 132 |
|
|
|
|
| 135 |
const outputPath = path.join(outputsDir, outputFilename);
|
| 136 |
|
| 137 |
console.log(`π΅ Processing: ${EFFECTS[effectType].name}`);
|
|
|
|
| 138 |
|
| 139 |
+
const effectCommand = EFFECTS[effectType].command;
|
| 140 |
+
|
| 141 |
+
// Optimized FFmpeg command with faster settings
|
| 142 |
+
const ffmpegCommand = `ffmpeg -i "${inputPath}" -threads 0 ${effectCommand} -y "${outputPath}"`;
|
| 143 |
|
| 144 |
+
console.log(`βοΈ Starting FFmpeg...`);
|
| 145 |
|
|
|
|
| 146 |
const startTime = Date.now();
|
| 147 |
+
await execPromise(ffmpegCommand, {
|
| 148 |
+
maxBuffer: 50 * 1024 * 1024 // 50MB buffer
|
| 149 |
+
});
|
| 150 |
const processingTime = ((Date.now() - startTime) / 1000).toFixed(2);
|
| 151 |
|
|
|
|
| 152 |
fs.unlinkSync(inputPath);
|
| 153 |
|
|
|
|
| 154 |
const stats = fs.statSync(outputPath);
|
| 155 |
const fileSizeKB = (stats.size / 1024).toFixed(2);
|
| 156 |
|
|
|
|
| 158 |
|
| 159 |
res.json({
|
| 160 |
success: true,
|
| 161 |
+
message: `Processed with ${EFFECTS[effectType].name}`,
|
| 162 |
+
downloadUrl: `/download/${outputFilename}`,
|
| 163 |
+
filename: outputFilename,
|
| 164 |
effect: {
|
| 165 |
id: effectType,
|
| 166 |
+
name: EFFECTS[effectType].name
|
|
|
|
| 167 |
},
|
| 168 |
output: {
|
| 169 |
+
size_kb: fileSizeKB
|
|
|
|
|
|
|
| 170 |
},
|
| 171 |
processing_time_seconds: processingTime
|
| 172 |
});
|
| 173 |
|
| 174 |
} catch (error) {
|
| 175 |
+
console.error('β Error:', error);
|
| 176 |
|
|
|
|
| 177 |
if (req.file && fs.existsSync(req.file.path)) {
|
| 178 |
fs.unlinkSync(req.file.path);
|
| 179 |
}
|
| 180 |
|
| 181 |
res.status(500).json({
|
| 182 |
success: false,
|
| 183 |
+
error: 'Processing failed',
|
| 184 |
+
details: error.message
|
|
|
|
| 185 |
});
|
| 186 |
}
|
| 187 |
});
|
| 188 |
|
| 189 |
+
// π₯ Download
|
| 190 |
app.get('/download/:filename', (req, res) => {
|
| 191 |
const filename = req.params.filename;
|
| 192 |
const filePath = path.join(outputsDir, filename);
|
|
|
|
| 194 |
if (!fs.existsSync(filePath)) {
|
| 195 |
return res.status(404).json({
|
| 196 |
success: false,
|
| 197 |
+
error: 'File not found'
|
|
|
|
| 198 |
});
|
| 199 |
}
|
| 200 |
|
|
|
|
| 202 |
|
| 203 |
res.download(filePath, filename, (err) => {
|
| 204 |
if (!err) {
|
|
|
|
| 205 |
setTimeout(() => {
|
| 206 |
if (fs.existsSync(filePath)) {
|
| 207 |
fs.unlinkSync(filePath);
|
| 208 |
+
console.log(`ποΈ Cleaned: ${filename}`);
|
| 209 |
}
|
| 210 |
}, 10000);
|
| 211 |
}
|
|
|
|
| 214 |
|
| 215 |
// π Start Server
|
| 216 |
app.listen(PORT, '0.0.0.0', () => {
|
| 217 |
+
console.log('βββββββββββββββββββββββββββββββββββββββ');
|
| 218 |
+
console.log('π LoFi Remix API v2.0 - OPTIMIZED');
|
| 219 |
+
console.log('βββββββββββββββββββββββββββββββββββββββ');
|
| 220 |
console.log(`π Server: http://0.0.0.0:${PORT}`);
|
| 221 |
+
console.log(`β‘ Performance: Fast processing enabled`);
|
| 222 |
+
console.log(`π΅ Effects: ${Object.keys(EFFECTS).length}`);
|
| 223 |
+
console.log('βββββββββββββββββββββββββββββββββββββββ');
|
| 224 |
});
|