Created
July 22, 2024 23:41
-
-
Save ariviere/2187c4ce7c96eade872734df11e892a1 to your computer and use it in GitHub Desktop.
Theta EdgeCloud Sketch to Object JS API
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
const url = 'YOUR_API_URL'; | |
let eventSource = null; | |
/** | |
* Generate a 2D image from a sketch | |
* @param {File} file - The sketch image file | |
* @param {string} prompt - The prompt for the image generation | |
* @param {string} negativePrompt - The negative prompt for the image generation | |
* @returns {string} the path of the generated 2D image | |
*/ | |
export const generate2d = async (file, prompt, negativePrompt) => { | |
const sessionHash = Math.random().toString(36).substring(2, 12); | |
const sketchPath = await uploadImage(file); | |
const sketchPngPath = await createEventSource( | |
sessionHash, | |
0, | |
sketchToSketchPngBody(sketchPath, getUrlFromPath(sketchPath), file, sessionHash)) | |
const image2dPath = await createEventSource( | |
sessionHash, | |
1, | |
sketchPngTo2dBody(sketchPngPath, getUrlFromPath(sketchPngPath), file, sessionHash, prompt, negativePrompt)) | |
return await createEventSource( | |
sessionHash, | |
url, | |
2, | |
image2dToImage2d2Body(image2dPath, getUrlFromPath(image2dPath), file, sessionHash)); | |
} | |
/** | |
* Generate a 3D object from a 2D image | |
* @param {string} imagePath - The path of the 2D image | |
* @returns {string} the path of the generated 3D object | |
*/ | |
const generate3d = async (imagePath) => { | |
const sessionHash = Math.random().toString(36).substring(2, 12); | |
return await createEventSource( | |
sessionHash, | |
4, | |
image2dToObjBody(imagePath, getUrlFromPath(imagePath), sessionHash)); | |
} | |
const uploadImage = async (file) => { | |
const formData = new FormData(); | |
formData.append('files', file, file.name); | |
try { | |
const response = await fetch(`${url}/upload`, { | |
method: 'POST', | |
body: formData | |
}) | |
const json = await response?.json(); | |
return json?.[0] | |
} catch (e) { | |
console.log(e) | |
} | |
} | |
const createEventSource = async (sessionHash, fnIndex, body) => { | |
return new Promise((resolve) => { | |
if (eventSource) { | |
eventSource.close() | |
eventSource = null | |
} | |
eventSource = new EventSource(`${url}/queue/join?fn_index=${fnIndex}&session_hash=${sessionHash}`); | |
eventSource.onmessage = (e) => { | |
const data = JSON.parse(e.data) | |
switch (data.msg) { | |
case 'process_completed': | |
if (data.success) { | |
resolve(data.output.data[0].path) | |
} else { | |
// onError event | |
} | |
eventSource.close() | |
break; | |
case 'send_data': | |
queueData(url, body, data.event_id) | |
break; | |
case 'estimation': | |
// onEstimation event | |
break; | |
default: | |
break; | |
} | |
}; | |
eventSource.onerror = (e) => { | |
if (e.readyState === EventSource.CONNECTING) { | |
return | |
} | |
// onError event | |
eventSource.close() | |
}; | |
}); | |
} | |
const queueData = async (body, eventId) => { | |
const response = await fetch(`${url}/queue/data`, { | |
method: "POST", | |
headers: {"Content-Type": "application/json"}, | |
body: JSON.stringify({...body, event_id: eventId}), | |
}); | |
const json = await response?.json(); | |
if (!response.ok) { | |
let errorMessage = json?.detail || 'Failed to generate' | |
if (errorMessage.toLowerCase().includes('queue is full')) { | |
errorMessage = 'The queue is currently full. Please try again later.' | |
} | |
throw new Error(errorMessage) | |
} | |
} | |
const getUrlFromPath = (path) => { | |
return `${url}/file=${path}` | |
} | |
const sketchToSketchPngBody = (sketchPath, sketchUrl, file, sessionHash) => { | |
return { | |
data: [ | |
{ | |
"background": { | |
"mime_type": "", | |
"orig_name": "background.png", | |
"path": sketchPath, | |
"size": file.size, | |
"url": sketchUrl | |
}, | |
"composite": { | |
"mime_type": "", | |
"orig_name": "composite.png", | |
"path": sketchPath, | |
"size": file.size, | |
"url": sketchUrl | |
}, | |
} | |
], | |
session_hash: sessionHash, | |
fn_index: 0, | |
trigger_id: 30, | |
event_data: null, | |
} | |
} | |
const sketchPngTo2dBody = (sketchPath, sketchUrl, file, sessionHash, prompt, negativePrompt) => { | |
return { | |
"data": [ | |
{ | |
"mime_type": null, | |
"orig_name": "image.png", | |
"path": sketchPath, | |
"size": null, | |
"url": sketchUrl | |
}, | |
"stablediffusionapi/rev-animated-v122-eol", | |
"lllyasviel/control_v11p_sd15_lineart", | |
512, | |
512, | |
true, | |
1, | |
prompt, | |
negativePrompt, | |
1, | |
7.5, | |
30, | |
"DDIM", | |
0, | |
"Lineart" | |
], | |
"event_data": null, | |
"fn_index": 1, | |
"session_hash": sessionHash, | |
"trigger_id": 30 | |
} | |
} | |
const image2dToImage2d2Body = (image2dPath, image2dUrl, file, sessionHash) => { | |
return { | |
"data": [ | |
{ | |
"mime_type": null, | |
"orig_name": "image.png", | |
"path": image2dPath, | |
"size": null, | |
"url": image2dUrl | |
}, | |
true, | |
0.85, | |
], | |
"event_data": null, | |
"fn_index": 2, | |
"session_hash": sessionHash, | |
"trigger_id": 30 | |
} | |
} | |
const image2dToObjBody = (image2dPath, image2dUrl, sessionHash) => { | |
return { | |
"data": [ | |
{ | |
"mime_type": null, | |
"orig_name": "image.png", | |
"path": image2dPath, | |
"size": null, | |
"url": image2dUrl | |
}, | |
256, | |
], | |
"event_data": null, | |
"fn_index": 4, | |
"session_hash": sessionHash, | |
"trigger_id": 35 | |
} | |
} |
Also queue/data?fn_index=1&session_hash= ...
{
"detail": [
{
"type": "model_attributes_type",
"loc": [
"body"
],
"msg": "Input should be a valid dictionary or object to extract fields from",
The JS code uses an EventSource object to keep the connection open. The equivalent using curl for your case is
curl -N -H "Accept: text/event-stream" {{URL}}/queue/join?fn_index=1&session_hash=4f227bb3-fd53-402c-b140-e69ee4e0f1ca
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
was able to upload using curl from your js
curl --location '{{URL}}}/upload' \ --header 'Content-Type: application/json' \ --form 'files=@"{{FILE}}"'
returns
[ "{{server local filename}}" ]
and this can be accessed as a URL
{{URL}}/file={{server local filename}}"
however can't seem to get the meat of the API endpoints to work
{{URL}}/queue/join?fn_index=1&session_hash=4f227bb3-fd53-402c-b140-e69ee4e0f1ca
{
"detail": "Method Not Allowed"
}