| <!DOCTYPE html> |
| <html lang="fa" dir="rtl"> |
| <head> |
| <meta charset="UTF-8"> |
| <meta name="viewport" content="width=device-width, initial-scale=1.0"> |
| <title>ساخت ویدیو با هوش مصنوعی - Hugging Face</title> |
| <link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.4.0/css/all.min.css"> |
| <script src="https://cdn.jsdelivr.net/npm/@huggingface/inference@2.6.4"></script> |
| <style> |
| * { |
| margin: 0; |
| padding: 0; |
| box-sizing: border-box; |
| font-family: 'Segoe UI', Tahoma, Geneva, Verdana, sans-serif; |
| } |
| |
| body { |
| background: linear-gradient(135deg, #1a2a6c, #b21f1f, #fdbb2d); |
| color: #fff; |
| min-height: 100vh; |
| padding: 20px; |
| } |
| |
| .container { |
| max-width: 1200px; |
| margin: 0 auto; |
| } |
| |
| header { |
| text-align: center; |
| padding: 30px 0; |
| margin-bottom: 30px; |
| } |
| |
| h1 { |
| font-size: 2.5rem; |
| margin-bottom: 10px; |
| text-shadow: 2px 2px 4px rgba(0, 0, 0, 0.3); |
| } |
| |
| .subtitle { |
| font-size: 1.2rem; |
| opacity: 0.9; |
| } |
| |
| .card { |
| background: rgba(255, 255, 255, 0.1); |
| backdrop-filter: blur(10px); |
| border-radius: 15px; |
| padding: 25px; |
| margin-bottom: 25px; |
| box-shadow: 0 8px 32px rgba(0, 0, 0, 0.2); |
| border: 1px solid rgba(255, 255, 255, 0.2); |
| } |
| |
| .card-title { |
| display: flex; |
| align-items: center; |
| margin-bottom: 20px; |
| font-size: 1.5rem; |
| } |
| |
| .card-title i { |
| margin-left: 10px; |
| font-size: 1.8rem; |
| } |
| |
| .form-group { |
| margin-bottom: 20px; |
| } |
| |
| label { |
| display: block; |
| margin-bottom: 8px; |
| font-weight: 500; |
| } |
| |
| input, textarea, select { |
| width: 100%; |
| padding: 12px 15px; |
| border-radius: 8px; |
| border: 1px solid rgba(255, 255, 255, 0.3); |
| background: rgba(255, 255, 255, 0.1); |
| color: #fff; |
| font-size: 1rem; |
| transition: all 0.3s ease; |
| } |
| |
| input:focus, textarea:focus, select:focus { |
| outline: none; |
| border-color: #4dabf7; |
| box-shadow: 0 0 0 3px rgba(77, 171, 247, 0.3); |
| } |
| |
| textarea { |
| min-height: 120px; |
| resize: vertical; |
| } |
| |
| .btn { |
| display: inline-flex; |
| align-items: center; |
| justify-content: center; |
| padding: 12px 25px; |
| background: linear-gradient(45deg, #ff6b6b, #ff8e53); |
| color: white; |
| border: none; |
| border-radius: 8px; |
| font-size: 1rem; |
| font-weight: 600; |
| cursor: pointer; |
| transition: all 0.3s ease; |
| box-shadow: 0 4px 15px rgba(0, 0, 0, 0.2); |
| } |
| |
| .btn:hover { |
| transform: translateY(-2px); |
| box-shadow: 0 6px 20px rgba(0, 0, 0, 0.3); |
| } |
| |
| .btn i { |
| margin-right: 8px; |
| } |
| |
| .btn-primary { |
| background: linear-gradient(45deg, #4dabf7, #3bc9db); |
| } |
| |
| .btn-success { |
| background: linear-gradient(45deg, #51cf66, #94d82d); |
| } |
| |
| .flex-container { |
| display: flex; |
| gap: 25px; |
| flex-wrap: wrap; |
| } |
| |
| .flex-item { |
| flex: 1; |
| min-width: 300px; |
| } |
| |
| .result-container { |
| display: none; |
| text-align: center; |
| padding: 20px; |
| } |
| |
| .video-preview { |
| width: 100%; |
| max-width: 600px; |
| height: 300px; |
| background: rgba(0, 0, 0, 0.3); |
| border-radius: 10px; |
| margin: 20px auto; |
| display: flex; |
| align-items: center; |
| justify-content: center; |
| overflow: hidden; |
| } |
| |
| .video-preview video { |
| max-width: 100%; |
| max-height: 100%; |
| border-radius: 8px; |
| } |
| |
| .loading { |
| display: none; |
| text-align: center; |
| padding: 20px; |
| } |
| |
| .spinner { |
| width: 50px; |
| height: 50px; |
| border: 5px solid rgba(255, 255, 255, 0.3); |
| border-radius: 50%; |
| border-top-color: #4dabf7; |
| animation: spin 1s linear infinite; |
| margin: 0 auto 15px; |
| } |
| |
| @keyframes spin { |
| to { transform: rotate(360deg); } |
| } |
| |
| .file-input-container { |
| position: relative; |
| overflow: hidden; |
| display: inline-block; |
| width: 100%; |
| } |
| |
| .file-input-container input[type=file] { |
| position: absolute; |
| left: 0; |
| top: 0; |
| opacity: 0; |
| width: 100%; |
| height: 100%; |
| cursor: pointer; |
| } |
| |
| .file-input-label { |
| display: flex; |
| align-items: center; |
| justify-content: center; |
| padding: 12px; |
| background: rgba(255, 255, 255, 0.1); |
| border: 2px dashed rgba(255, 255, 255, 0.3); |
| border-radius: 8px; |
| cursor: pointer; |
| transition: all 0.3s ease; |
| } |
| |
| .file-input-label:hover { |
| background: rgba(255, 255, 255, 0.2); |
| } |
| |
| .file-input-label i { |
| margin-left: 8px; |
| font-size: 1.5rem; |
| } |
| |
| .image-preview { |
| margin-top: 15px; |
| text-align: center; |
| } |
| |
| .image-preview img { |
| max-width: 100%; |
| max-height: 200px; |
| border-radius: 8px; |
| box-shadow: 0 4px 15px rgba(0, 0, 0, 0.2); |
| } |
| |
| .instructions { |
| margin-top: 30px; |
| font-size: 0.9rem; |
| opacity: 0.8; |
| line-height: 1.6; |
| } |
| |
| .error { |
| background: rgba(255, 0, 0, 0.2); |
| border: 1px solid rgba(255, 0, 0, 0.5); |
| border-radius: 8px; |
| padding: 15px; |
| margin: 15px 0; |
| display: none; |
| } |
| |
| @media (max-width: 768px) { |
| .flex-container { |
| flex-direction: column; |
| } |
| |
| h1 { |
| font-size: 2rem; |
| } |
| } |
| </style> |
| </head> |
| <body> |
| <div class="container"> |
| <header> |
| <h1>ساخت ویدیو با هوش مصنوعی</h1> |
| <p class="subtitle">تبدیل متن و تصویر به ویدیو با استفاده از مدل VEO از Hugging Face</p> |
| </header> |
| |
| <div class="card"> |
| <div class="card-title"> |
| <i class="fas fa-key"></i> |
| <h2>تنظیمات احراز هویت</h2> |
| </div> |
| <div class="form-group"> |
| <label for="token">توکن Hugging Face</label> |
| <input type="text" id="token" placeholder="توکن خود را اینجا وارد کنید" required> |
| <p class="instructions">برای استفاده از این سرویس، نیاز به یک توکن معتبر از Hugging Face دارید. اگر توکن ندارید، از <a href="https://huggingface.co/settings/tokens" target="_blank" style="color: #4dabf7;">این لینک</a> میتوانید ایجاد کنید.</p> |
| </div> |
| </div> |
| |
| <div class="flex-container"> |
| <div class="flex-item"> |
| <div class="card"> |
| <div class="card-title"> |
| <i class="fas fa-font"></i> |
| <h2>تبدیل متن به ویدیو</h2> |
| </div> |
| <div class="form-group"> |
| <label for="text-input">متن خود را وارد کنید</label> |
| <textarea id="text-input" placeholder="مثلاً: یک مرد جوان در خیابان در حال راه رفتن است"></textarea> |
| </div> |
| <button class="btn btn-primary" id="text-to-video-btn"> |
| <i class="fas fa-film"></i> |
| ساخت ویدیو از متن |
| </button> |
| </div> |
| </div> |
| |
| <div class="flex-item"> |
| <div class="card"> |
| <div class="card-title"> |
| <i class="fas fa-image"></i> |
| <h2>تبدیل تصویر به ویدیو</h2> |
| </div> |
| <div class="form-group"> |
| <label for="image-input">تصویر خود را انتخاب کنید</label> |
| <div class="file-input-container"> |
| <div class="file-input-label"> |
| <i class="fas fa-cloud-upload-alt"></i> |
| <span>انتخاب تصویر</span> |
| </div> |
| <input type="file" id="image-input" accept="image/*"> |
| </div> |
| <div class="image-preview" id="image-preview"></div> |
| </div> |
| <div class="form-group"> |
| <label for="image-prompt">توضیح برای ویدیو (اختیاری)</label> |
| <input type="text" id="image-prompt" placeholder="مثلاً: گربه شروع به رقصیدن میکند"> |
| </div> |
| <button class="btn btn-success" id="image-to-video-btn"> |
| <i class="fas fa-video"></i> |
| ساخت ویدیو از تصویر |
| </button> |
| </div> |
| </div> |
| </div> |
| |
| <div class="loading" id="loading"> |
| <div class="spinner"></div> |
| <p>در حال ساخت ویدیو، لطفاً منتظر بمانید...</p> |
| <p class="instructions">این فرآیند ممکن است چند دقیقه طول بکشد</p> |
| </div> |
| |
| <div class="error" id="error-message"> |
| <i class="fas fa-exclamation-triangle"></i> |
| <span id="error-text">خطایی رخ داده است</span> |
| </div> |
| |
| <div class="card result-container" id="result-container"> |
| <div class="card-title"> |
| <i class="fas fa-check-circle"></i> |
| <h2>ویدیو شما آماده است!</h2> |
| </div> |
| <div class="video-preview" id="video-preview"> |
| <video controls id="generated-video"> |
| مرورگر شما از تگ ویدیو پشتیبانی نمیکند. |
| </video> |
| </div> |
| <button class="btn btn-primary" id="download-btn"> |
| <i class="fas fa-download"></i> |
| دانلود ویدیو |
| </button> |
| </div> |
| </div> |
|
|
| <script> |
| |
| const tokenInput = document.getElementById('token'); |
| const textInput = document.getElementById('text-input'); |
| const imageInput = document.getElementById('image-input'); |
| const imagePrompt = document.getElementById('image-prompt'); |
| const textToVideoBtn = document.getElementById('text-to-video-btn'); |
| const imageToVideoBtn = document.getElementById('image-to-video-btn'); |
| const loading = document.getElementById('loading'); |
| const resultContainer = document.getElementById('result-container'); |
| const videoPreview = document.getElementById('video-preview'); |
| const generatedVideo = document.getElementById('generated-video'); |
| const downloadBtn = document.getElementById('download-btn'); |
| const imagePreview = document.getElementById('image-preview'); |
| const errorMessage = document.getElementById('error-message'); |
| const errorText = document.getElementById('error-text'); |
| |
| |
| imageInput.addEventListener('change', function(e) { |
| const file = e.target.files[0]; |
| if (file) { |
| const reader = new FileReader(); |
| reader.onload = function(e) { |
| imagePreview.innerHTML = `<img src="${e.target.result}" alt="تصویر آپلود شده">`; |
| }; |
| reader.readAsDataURL(file); |
| } |
| }); |
| |
| |
| textToVideoBtn.addEventListener('click', async function() { |
| if (!tokenInput.value) { |
| showError('لطفاً توکن Hugging Face خود را وارد کنید'); |
| return; |
| } |
| |
| if (!textInput.value) { |
| showError('لطفاً متنی برای تبدیل به ویدیو وارد کنید'); |
| return; |
| } |
| |
| hideError(); |
| loading.style.display = 'block'; |
| resultContainer.style.display = 'none'; |
| |
| try { |
| |
| const { InferenceClient } = window.HfInference; |
| const client = new InferenceClient(tokenInput.value); |
| |
| const videoBlob = await client.textToVideo({ |
| provider: "fal-ai", |
| model: "akhaliq/veo3.1-fast", |
| inputs: textInput.value, |
| }); |
| |
| |
| const videoUrl = URL.createObjectURL(videoBlob); |
| generatedVideo.src = videoUrl; |
| loading.style.display = 'none'; |
| resultContainer.style.display = 'block'; |
| |
| |
| downloadBtn.onclick = function() { |
| const a = document.createElement('a'); |
| a.href = videoUrl; |
| a.download = `text-to-video-${Date.now()}.mp4`; |
| document.body.appendChild(a); |
| a.click(); |
| document.body.removeChild(a); |
| }; |
| |
| } catch (error) { |
| console.error('خطا در ساخت ویدیو:', error); |
| showError('خطا در ساخت ویدیو: ' + error.message); |
| loading.style.display = 'none'; |
| } |
| }); |
| |
| |
| imageToVideoBtn.addEventListener('click', async function() { |
| if (!tokenInput.value) { |
| showError('لطفاً توکن Hugging Face خود را وارد کنید'); |
| return; |
| } |
| |
| if (!imageInput.files[0]) { |
| showError('لطفاً تصویری برای تبدیل به ویدیو انتخاب کنید'); |
| return; |
| } |
| |
| hideError(); |
| loading.style.display = 'block'; |
| resultContainer.style.display = 'none'; |
| |
| try { |
| |
| const imageFile = imageInput.files[0]; |
| |
| |
| const { InferenceClient } = window.HfInference; |
| const client = new InferenceClient(tokenInput.value); |
| |
| const videoBlob = await client.imageToVideo({ |
| provider: "fal-ai", |
| model: "akhaliq/veo3.1-fast-image-to-video", |
| inputs: imageFile, |
| parameters: { |
| prompt: imagePrompt.value || "The image comes to life" |
| }, |
| }); |
| |
| |
| const videoUrl = URL.createObjectURL(videoBlob); |
| generatedVideo.src = videoUrl; |
| loading.style.display = 'none'; |
| resultContainer.style.display = 'block'; |
| |
| |
| downloadBtn.onclick = function() { |
| const a = document.createElement('a'); |
| a.href = videoUrl; |
| a.download = `image-to-video-${Date.now()}.mp4`; |
| document.body.appendChild(a); |
| a.click(); |
| document.body.removeChild(a); |
| }; |
| |
| } catch (error) { |
| console.error('خطا در ساخت ویدیو:', error); |
| showError('خطا در ساخت ویدیو: ' + error.message); |
| loading.style.display = 'none'; |
| } |
| }); |
| |
| |
| function showError(message) { |
| errorText.textContent = message; |
| errorMessage.style.display = 'block'; |
| } |
| |
| |
| function hideError() { |
| errorMessage.style.display = 'none'; |
| } |
| </script> |
| </body> |
| </html> |