Spaces:
Runtime error
Runtime error
Update server.js
Browse files
server.js
CHANGED
@@ -570,14 +570,13 @@ app.post('/api/generate/anime-uc', authenticateToken, async (req, res) => {
|
|
570 |
}
|
571 |
});
|
572 |
|
573 |
-
// Flux Generation endpoint (now
|
574 |
app.get('/api/generate/flux', authenticateToken, async (req, res) => {
|
575 |
try {
|
576 |
const { prompt, aspect } = req.query;
|
577 |
if (!prompt) {
|
578 |
return res.status(400).json({ success: false, error: 'Prompt is required' });
|
579 |
}
|
580 |
-
|
581 |
// Aspect ratio logic
|
582 |
let width = 1280, height = 720;
|
583 |
if (aspect === '9:16') {
|
@@ -586,106 +585,39 @@ app.get('/api/generate/flux', authenticateToken, async (req, res) => {
|
|
586 |
width = 1024; height = 1024;
|
587 |
}
|
588 |
|
589 |
-
|
590 |
-
|
591 |
-
|
592 |
-
|
593 |
-
|
594 |
-
|
595 |
-
data: [
|
596 |
-
prompt,
|
597 |
-
null, // id_image (null for no ID image)
|
598 |
-
0, // start_step
|
599 |
-
4, // guidance
|
600 |
-
"-1", // seed
|
601 |
-
1, // true_cfg
|
602 |
-
width,
|
603 |
-
height,
|
604 |
-
20, // num_steps
|
605 |
-
1, // id_weight
|
606 |
-
"bad quality, worst quality, text, signature, watermark, extra limbs", // neg_prompt
|
607 |
-
1, // timestep_to_start_cfg
|
608 |
-
128 // max_sequence_length
|
609 |
-
],
|
610 |
-
event_data: null,
|
611 |
-
fn_index: 4,
|
612 |
-
trigger_id: 21,
|
613 |
-
session_hash: sessionHash
|
614 |
-
}, {
|
615 |
-
headers: {
|
616 |
-
'Content-Type': 'application/json',
|
617 |
-
'Referer': 'https://yanze-pulid-flux.hf.space/'
|
618 |
-
}
|
619 |
-
});
|
620 |
-
|
621 |
-
console.log(`[Flux] Queue joined, event_id: ${joinResponse.data?.event_id}`);
|
622 |
-
|
623 |
-
// Poll for results
|
624 |
-
let attempts = 0;
|
625 |
-
const maxAttempts = 60;
|
626 |
-
|
627 |
-
while (attempts < maxAttempts) {
|
628 |
-
try {
|
629 |
-
const dataResponse = await axios.get(
|
630 |
-
`https://yanze-pulid-flux.hf.space/queue/data?session_hash=${encodeURIComponent(sessionHash)}`,
|
631 |
-
{
|
632 |
-
headers: {
|
633 |
-
'Accept': 'text/event-stream',
|
634 |
-
'Referer': 'https://yanze-pulid-flux.hf.space/'
|
635 |
-
},
|
636 |
-
timeout: 10000
|
637 |
-
}
|
638 |
-
);
|
639 |
-
|
640 |
-
const data = dataResponse.data;
|
641 |
-
console.log(`[Flux] Poll attempt ${attempts + 1}, data length: ${data.length}`);
|
642 |
-
|
643 |
-
// Parse the event stream data
|
644 |
-
const lines = data.split('\n');
|
645 |
-
let eventData = '';
|
646 |
-
|
647 |
-
for (const line of lines) {
|
648 |
-
if (line.startsWith('data: ')) {
|
649 |
-
eventData += line.substring(6);
|
650 |
-
} else if (line === '') {
|
651 |
-
if (eventData) {
|
652 |
-
try {
|
653 |
-
const json = JSON.parse(eventData);
|
654 |
-
console.log(`[Flux] Parsed event: ${json.msg}`);
|
655 |
-
|
656 |
-
if (json.msg === 'process_completed' && json.output?.data?.[0]?.url) {
|
657 |
-
const imageUrl = json.output.data[0].url;
|
658 |
-
console.log(`[Flux] Found image:`, imageUrl);
|
659 |
-
|
660 |
-
res.json({ success: true, imageUrl: imageUrl });
|
661 |
-
return;
|
662 |
-
}
|
663 |
-
|
664 |
-
} catch (error) {
|
665 |
-
console.error('[Flux] Error parsing event data:', error, 'Raw data:', eventData);
|
666 |
-
}
|
667 |
-
eventData = '';
|
668 |
-
}
|
669 |
-
} else if (line.startsWith(':')) {
|
670 |
-
continue;
|
671 |
-
} else if (line !== '') {
|
672 |
-
eventData += line;
|
673 |
-
}
|
674 |
-
}
|
675 |
-
|
676 |
-
} catch (pollError) {
|
677 |
-
console.error(`[Flux] Poll error on attempt ${attempts + 1}:`, pollError.message);
|
678 |
-
}
|
679 |
-
|
680 |
-
await new Promise(resolve => setTimeout(resolve, 2000)); // Wait 2 seconds between polls
|
681 |
-
attempts++;
|
682 |
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
683 |
|
684 |
-
|
685 |
-
res.
|
686 |
-
|
687 |
} catch (error) {
|
688 |
-
console.error('[Flux]
|
689 |
res.status(500).json({ success: false, error: error.message || 'Failed to generate image' });
|
690 |
}
|
691 |
});
|
@@ -922,14 +854,15 @@ app.post('/api/admin/process-old', async (req, res) => {
|
|
922 |
}
|
923 |
});
|
924 |
|
925 |
-
// Proxy route for HuggingFace/Gradio images
|
926 |
app.get('/proxy-image', async (req, res) => {
|
927 |
const { url, proxied } = req.query;
|
928 |
if (!url) {
|
929 |
return res.status(400).send('Missing url parameter');
|
930 |
}
|
931 |
-
|
932 |
-
|
|
|
933 |
}
|
934 |
try {
|
935 |
const response = await fetch(url, {
|
@@ -960,6 +893,58 @@ app.get('/proxy-image', async (req, res) => {
|
|
960 |
}
|
961 |
});
|
962 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
963 |
app.listen(port, () => {
|
964 |
console.log(`Server running on port ${port}`);
|
965 |
});
|
|
|
570 |
}
|
571 |
});
|
572 |
|
573 |
+
// Flux Generation endpoint (now uses UNO-FLUX model)
|
574 |
app.get('/api/generate/flux', authenticateToken, async (req, res) => {
|
575 |
try {
|
576 |
const { prompt, aspect } = req.query;
|
577 |
if (!prompt) {
|
578 |
return res.status(400).json({ success: false, error: 'Prompt is required' });
|
579 |
}
|
|
|
580 |
// Aspect ratio logic
|
581 |
let width = 1280, height = 720;
|
582 |
if (aspect === '9:16') {
|
|
|
585 |
width = 1024; height = 1024;
|
586 |
}
|
587 |
|
588 |
+
// Use a default image for all required image_prompt1-4
|
589 |
+
const defaultImageUrl = 'https://raw.githubusercontent.com/gradio-app/gradio/main/test/test_files/bus.png';
|
590 |
+
async function fetchImageBlob(url) {
|
591 |
+
const response = await fetch(url);
|
592 |
+
if (!response.ok) throw new Error('Failed to fetch image: ' + url);
|
593 |
+
return await response.blob();
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
594 |
}
|
595 |
+
const [img1, img2, img3, img4] = await Promise.all([
|
596 |
+
fetchImageBlob(defaultImageUrl),
|
597 |
+
fetchImageBlob(defaultImageUrl),
|
598 |
+
fetchImageBlob(defaultImageUrl),
|
599 |
+
fetchImageBlob(defaultImageUrl)
|
600 |
+
]);
|
601 |
+
|
602 |
+
// Connect to UNO-FLUX Gradio client
|
603 |
+
const client = await Client.connect("bytedance-research/UNO-FLUX");
|
604 |
+
const result = await client.predict("/gradio_generate", {
|
605 |
+
prompt,
|
606 |
+
width,
|
607 |
+
height,
|
608 |
+
guidance: 4,
|
609 |
+
num_steps: 25,
|
610 |
+
seed: -1,
|
611 |
+
image_prompt1: img1,
|
612 |
+
image_prompt2: img2,
|
613 |
+
image_prompt3: img3,
|
614 |
+
image_prompt4: img4
|
615 |
+
});
|
616 |
|
617 |
+
// result.data[0] is the generated image URL
|
618 |
+
res.json({ success: true, imageUrl: result.data[0] });
|
|
|
619 |
} catch (error) {
|
620 |
+
console.error('[Flux] UNO-FLUX endpoint error:', error);
|
621 |
res.status(500).json({ success: false, error: error.message || 'Failed to generate image' });
|
622 |
}
|
623 |
});
|
|
|
854 |
}
|
855 |
});
|
856 |
|
857 |
+
// Proxy route for HuggingFace/Gradio images (update to allow UNO-FLUX output URLs)
|
858 |
app.get('/proxy-image', async (req, res) => {
|
859 |
const { url, proxied } = req.query;
|
860 |
if (!url) {
|
861 |
return res.status(400).send('Missing url parameter');
|
862 |
}
|
863 |
+
// Allow proxying from yanze-pulid-flux.hf.space and UNO-FLUX output URLs
|
864 |
+
if (!url.startsWith('https://yanze-pulid-flux.hf.space/') && !url.startsWith('https://hf.space/')) {
|
865 |
+
return res.status(403).send('Forbidden: Only allowed to proxy from yanze-pulid-flux.hf.space or hf.space');
|
866 |
}
|
867 |
try {
|
868 |
const response = await fetch(url, {
|
|
|
893 |
}
|
894 |
});
|
895 |
|
896 |
+
// UNO-FLUX model generation endpoint
|
897 |
+
app.post('/api/generate/uno-flux', async (req, res) => {
|
898 |
+
try {
|
899 |
+
const {
|
900 |
+
prompt = "handsome woman in the city",
|
901 |
+
width = 512,
|
902 |
+
height = 512,
|
903 |
+
guidance = 4,
|
904 |
+
num_steps = 25,
|
905 |
+
seed = -1,
|
906 |
+
image_prompt1,
|
907 |
+
image_prompt2,
|
908 |
+
image_prompt3,
|
909 |
+
image_prompt4
|
910 |
+
} = req.body;
|
911 |
+
|
912 |
+
// Helper to fetch image as blob
|
913 |
+
async function fetchImageBlob(url) {
|
914 |
+
const response = await fetch(url);
|
915 |
+
if (!response.ok) throw new Error('Failed to fetch image: ' + url);
|
916 |
+
return await response.blob();
|
917 |
+
}
|
918 |
+
|
919 |
+
// Fetch all image prompts as blobs
|
920 |
+
const [img1, img2, img3, img4] = await Promise.all([
|
921 |
+
fetchImageBlob(image_prompt1),
|
922 |
+
fetchImageBlob(image_prompt2),
|
923 |
+
fetchImageBlob(image_prompt3),
|
924 |
+
fetchImageBlob(image_prompt4)
|
925 |
+
]);
|
926 |
+
|
927 |
+
// Connect to UNO-FLUX Gradio client
|
928 |
+
const client = await Client.connect("bytedance-research/UNO-FLUX");
|
929 |
+
const result = await client.predict("/gradio_generate", {
|
930 |
+
prompt,
|
931 |
+
width,
|
932 |
+
height,
|
933 |
+
guidance,
|
934 |
+
num_steps,
|
935 |
+
seed,
|
936 |
+
image_prompt1: img1,
|
937 |
+
image_prompt2: img2,
|
938 |
+
image_prompt3: img3,
|
939 |
+
image_prompt4: img4
|
940 |
+
});
|
941 |
+
|
942 |
+
res.json({ success: true, data: result.data });
|
943 |
+
} catch (err) {
|
944 |
+
res.status(500).json({ success: false, error: err.message });
|
945 |
+
}
|
946 |
+
});
|
947 |
+
|
948 |
app.listen(port, () => {
|
949 |
console.log(`Server running on port ${port}`);
|
950 |
});
|