Files
openDIAW.be/ai-bridge.js
T
kxkm acffe78750 feat: 3615 Jai pete fork — patched API URLs, bypassed features, local mode
All api.opendaw.studio → /api/opendaw (local proxy)
Feature checks bypassed (crossOriginIsolated via Express headers)
DemoProjects, PublishMusic, UserCounter, ErrorsPage all local
2026-03-21 14:40:54 +01:00

74 lines
4.6 KiB
JavaScript

const http = require("http");
const { execFileSync } = require("child_process");
const fs = require("fs");
const PORT = 8301;
const TTS_URL = "http://127.0.0.1:9100";
const OLLAMA_URL = "http://127.0.0.1:11434";
function readBody(req) {
return new Promise(r => { const c = []; req.on("data", d => c.push(d)); req.on("end", () => r(Buffer.concat(c).toString())); });
}
const server = http.createServer(async (req, res) => {
res.setHeader("Access-Control-Allow-Origin", "*");
res.setHeader("Access-Control-Allow-Methods", "GET,POST,OPTIONS");
res.setHeader("Access-Control-Allow-Headers", "Content-Type");
if (req.method === "OPTIONS") { res.writeHead(200); res.end(); return; }
const url = new URL(req.url, `http://localhost:${PORT}`);
if (url.pathname === "/health") {
res.writeHead(200, {"Content-Type":"application/json"});
res.end(JSON.stringify({ok:true,service:"ai-bridge",backends:["tts","musicgen","noise","ollama"]}));
return;
}
if (url.pathname === "/generate/music" && req.method === "POST") {
const {prompt="ambient",duration=30,style="experimental"} = JSON.parse(await readBody(req));
try {
const r = await fetch(`${TTS_URL}/compose`,{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify({prompt:`${prompt}, ${style}`,duration}),signal:AbortSignal.timeout(300000)});
if (!r.ok) throw new Error(`TTS ${r.status}`);
const buf = Buffer.from(await r.arrayBuffer());
res.writeHead(200,{"Content-Type":"audio/wav","Content-Length":buf.length}); res.end(buf);
} catch(e) { res.writeHead(500,{"Content-Type":"application/json"}); res.end(JSON.stringify({error:e.message})); }
return;
}
if (url.pathname === "/generate/voice" && req.method === "POST") {
const {text="Bonjour",persona="pharmacius"} = JSON.parse(await readBody(req));
try {
const r = await fetch(`${TTS_URL}/synthesize`,{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify({text,persona}),signal:AbortSignal.timeout(30000)});
if (!r.ok) throw new Error(`TTS ${r.status}`);
const buf = Buffer.from(await r.arrayBuffer());
res.writeHead(200,{"Content-Type":"audio/wav","Content-Length":buf.length}); res.end(buf);
} catch(e) { res.writeHead(500,{"Content-Type":"application/json"}); res.end(JSON.stringify({error:e.message})); }
return;
}
if (url.pathname === "/generate/noise" && req.method === "POST") {
const {type="pink",duration=10} = JSON.parse(await readBody(req));
const types = {white:"anoisesrc=d=DUR:c=white",pink:"anoisesrc=d=DUR:c=pink",brown:"anoisesrc=d=DUR:c=brown",sine:"sine=frequency=220:duration=DUR",drone:"sine=frequency=55:duration=DUR,tremolo=f=0.1:d=0.7"};
const filter = (types[type]||types.pink).replace(/DUR/g,String(duration));
const tmp = `/tmp/ai-noise-${Date.now()}.wav`;
try {
execFileSync("ffmpeg",["-f","lavfi","-i",filter,"-t",String(duration),"-ar","44100","-ac","2","-y",tmp],{timeout:15000});
const buf = fs.readFileSync(tmp); fs.unlinkSync(tmp);
res.writeHead(200,{"Content-Type":"audio/wav","Content-Length":buf.length}); res.end(buf);
} catch(e) { res.writeHead(500,{"Content-Type":"application/json"}); res.end(JSON.stringify({error:e.message})); }
return;
}
if (url.pathname === "/generate/suggest" && req.method === "POST") {
const {tracks=[]} = JSON.parse(await readBody(req));
const list = tracks.map((t,i)=>`#${i+1} [${t.type}] ${t.name} (${t.duration}s)`).join("\n");
try {
const r = await fetch(`${OLLAMA_URL}/api/chat`,{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify({model:"qwen3.5:9b",messages:[{role:"user",content:`Compositeur. Pistes:\n${list}\nSuggere en JSON: {"type":"music|voice|noise","prompt":"...","duration":30}`}],stream:false,options:{num_predict:100},keep_alive:"30m",think:false}),signal:AbortSignal.timeout(15000)});
const d = await r.json();
res.writeHead(200,{"Content-Type":"application/json"}); res.end(d.message?.content||'{"type":"noise","prompt":"pink","duration":10}');
} catch { res.writeHead(200,{"Content-Type":"application/json"}); res.end('{"type":"noise","prompt":"pink","duration":10}'); }
return;
}
if (url.pathname === "/personas") {
try { const r = await fetch("http://localhost:3333/api/personas"); const d = await r.json(); res.writeHead(200,{"Content-Type":"application/json"}); res.end(JSON.stringify(d)); }
catch { res.writeHead(200,{"Content-Type":"application/json"}); res.end('{"data":[]}'); }
return;
}
res.writeHead(404); res.end("Not found");
});
server.listen(PORT, () => console.log(`[ai-bridge] :${PORT}`));