shell / index.html
Alexey7878's picture
Update index.html
2cd33b4 verified
Raw History Blame
10.4 kB
<!DOCTYPE html>
<html lang="ru">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
```
<title>Hugging Face — Генерация изображений</title>
<style>
body {
font-family: system-ui, sans-serif;
max-width: 600px;
margin: 40px auto;
padding: 20px;
background: #f9fafb;
color: #111827;
}
h2 {
margin-top: 0;
}
label {
display: block;
margin-bottom: 5px;
font-weight: 500;
font-size: 14px;
}
input,
textarea,
select,
button {
width: 100%;
padding: 12px;
margin-bottom: 15px;
border-radius: 6px;
border: 1px solid #d1d5db;
box-sizing: border-box;
font-size: 15px;
}
textarea {
resize: vertical;
min-height: 90px;
}
button {
background: #10b981;
color: white;
border: none;
font-weight: bold;
cursor: pointer;
font-size: 16px;
}
button:hover {
background: #059669;
}
button:disabled {
background: #9ca3af;
cursor: not-allowed;
}
#outputImage {
max-width: 100%;
border-radius: 8px;
display: none;
margin-top: 15px;
box-shadow: 0 4px 6px rgba(0, 0, 0, 0.1);
}
#statusText {
color: #4b5563;
margin-bottom: 10px;
min-height: 20px;
}
.error-block {
background: #fef2f2;
border: 2px solid #dc2626;
border-radius: 8px;
padding: 15px;
margin-top: 10px;
white-space: pre-wrap;
word-wrap: break-word;
}
.error-block h3 {
margin: 0 0 10px 0;
color: #dc2626;
font-size: 16px;
}
.error-block .code {
background: #1f2937;
color: #f9fafb;
padding: 10px;
border-radius: 4px;
font-family: "Courier New", monospace;
font-size: 13px;
overflow-x: auto;
}
.info {
background: #eff6ff;
border: 1px solid #bfdbfe;
color: #1e40af;
padding: 12px;
border-radius: 6px;
margin-bottom: 20px;
font-size: 14px;
}
</style>
```
</head>
<body>
```
<h2>Генерация изображений через Hugging Face</h2>
<div class="info">
Для работы нужен Hugging Face Access Token
с разрешением Inference Providers.
</div>
<label for="hf-token">
Hugging Face Access Token:
</label>
<input
type="password"
id="hf-token"
placeholder="hf_..."
autocomplete="off"
>
<label for="modelSelect">
Модель:
</label>
<select id="modelSelect">
<option value="black-forest-labs/FLUX.1-schnell">
FLUX.1-schnell
</option>
<option value="black-forest-labs/FLUX.1-dev">
FLUX.1-dev
</option>
</select>
<label for="prompt">
Промпт:
</label>
<textarea
id="prompt"
rows="4"
placeholder="A cinematic shot of a cyberpunk city at night, neon lights, rain, highly detailed..."
></textarea>
<button id="generateBtn">
Сгенерировать
</button>
<div id="statusText"></div>
<div id="errorContainer"></div>
<img
id="outputImage"
alt="Сгенерированное изображение"
>
```
<script>
const btn =
document.getElementById("generateBtn");
const tokenInput =
document.getElementById("hf-token");
const modelSelect =
document.getElementById("modelSelect");
const promptInput =
document.getElementById("prompt");
const statusText =
document.getElementById("statusText");
const errorContainer =
document.getElementById("errorContainer");
const outputImage =
document.getElementById("outputImage");
let currentImageUrl = null;
// ----------------------------------------
// Показ ошибки
// ----------------------------------------
function showError(title, details) {
errorContainer.innerHTML = "";
const block =
document.createElement("div");
block.className =
"error-block";
const heading =
document.createElement("h3");
heading.textContent =
"⚠️ " + title;
const code =
document.createElement("div");
code.className =
"code";
code.textContent =
details;
block.appendChild(heading);
block.appendChild(code);
errorContainer.appendChild(block);
}
// ----------------------------------------
// Очистка ошибки
// ----------------------------------------
function clearError() {
errorContainer.innerHTML = "";
}
// ----------------------------------------
// Очистка предыдущего изображения
// ----------------------------------------
function clearImage() {
outputImage.style.display =
"none";
outputImage.removeAttribute("src");
if (currentImageUrl) {
URL.revokeObjectURL(
currentImageUrl
);
currentImageUrl = null;
}
}
// ----------------------------------------
// Разбор ошибки API
// ----------------------------------------
async function getErrorText(response) {
const text =
await response.text();
if (!text) {
return "Сервер вернул пустой ответ.";
}
try {
const json =
JSON.parse(text);
return JSON.stringify(
json,
null,
2
);
} catch {
return text;
}
}
// ----------------------------------------
// Генерация изображения
// ----------------------------------------
btn.addEventListener(
"click",
async () => {
const token =
tokenInput.value.trim();
const model =
modelSelect.value;
const prompt =
promptInput.value.trim();
clearError();
clearImage();
// Проверка токена
if (!token) {
showError(
"Ошибка",
"Введите Hugging Face Access Token."
);
return;
}
// Проверка промпта
if (!prompt) {
showError(
"Ошибка",
"Введите промпт для генерации."
);
return;
}
btn.disabled =
true;
statusText.textContent =
"Генерируем изображение...";
try {
/*
* Hugging Face Inference Providers.
*
* fal-ai выбран явно.
*
* Важно:
* provider должен поддерживать
* выбранную модель.
*/
const apiUrl =
`https://router.huggingface.co/fal-ai/models/${model}`;
const response =
await fetch(
apiUrl,
{
method: "POST",
headers: {
"Authorization":
`Bearer ${token}`,
"Content-Type":
"application/json",
"Accept":
"image/png"
},
body:
JSON.stringify({
inputs:
prompt,
parameters: {
num_inference_steps:
4
}
})
}
);
// --------------------------------
// Обработка ошибки
// --------------------------------
if (!response.ok) {
const errorText =
await getErrorText(
response
);
showError(
`Ошибка ${response.status} ${response.statusText}`,
`URL: ${apiUrl}\n\nОтвет сервера:\n${errorText}`
);
statusText.textContent =
"Генерация не удалась.";
return;
}
statusText.textContent =
"Изображение получено. Отображаем...";
// --------------------------------
// Получаем изображение как Blob
// --------------------------------
const blob =
await response.blob();
// Проверяем MIME-тип
if (
!blob.type ||
!blob.type.startsWith("image/")
) {
const text =
await blob.text();
showError(
"API вернул не изображение",
text
);
return;
}
// --------------------------------
// Создаём URL изображения
// --------------------------------
currentImageUrl =
URL.createObjectURL(
blob
);
outputImage.src =
currentImageUrl;
outputImage.style.display =
"block";
statusText.textContent =
"✅ Изображение готово!";
}
catch (error) {
console.error(
error
);
showError(
"Ошибка соединения",
error.message ||
String(error)
);
statusText.textContent =
"Произошла ошибка.";
}
finally {
btn.disabled =
false;
}
}
);
</script>
</body>
</html>