Spaces:
No application file
No application file
| class VideoDubbingApp { | |
| constructor() { | |
| this.initializeElements(); | |
| this.bindEvents(); | |
| this.notificationManager = new NotificationManager(); | |
| } | |
| initializeElements() { | |
| this.videoUrlInput = document.getElementById('videoUrl'); | |
| this.generateBtn = document.getElementById('generateBtn'); | |
| this.loadingSection = document.getElementById('loadingSection'); | |
| this.outputSection = document.getElementById('outputSection'); | |
| this.dubbedVideo = document.getElementById('dubbedVideo'); | |
| this.downloadBtn = document.getElementById('downloadBtn'); | |
| this.hindiTranscript = document.getElementById('hindiTranscript'); | |
| this.playBtn = document.getElementById('playBtn'); | |
| this.pauseBtn = document.getElementById('pauseBtn'); | |
| this.restartBtn = document.getElementById('restartBtn'); | |
| this.addSubtitlesCheckbox = document.getElementById('addSubtitles'); | |
| this.voiceStyleSelect = document.getElementById('voiceStyle'); | |
| this.targetLanguageSelect = document.getElementById('targetLanguage'); | |
| } | |
| bindEvents() { | |
| this.generateBtn.addEventListener('click', () => this.handleGenerate()); | |
| this.downloadBtn.addEventListener('click', () => this.handleDownload()); | |
| this.playBtn.addEventListener('click', () => this.playVideo()); | |
| this.pauseBtn.addEventListener('click', () => this.pauseVideo()); | |
| this.restartBtn.addEventListener('click', () => this.restartVideo()); | |
| } | |
| async handleGenerate() { | |
| const videoUrl = this.videoUrlInput.value.trim(); | |
| if (!videoUrl) { | |
| this.notificationManager.show('Please enter a valid YouTube URL', 'error'); | |
| return; | |
| } | |
| if (!this.isValidYouTubeUrl(videoUrl)) { | |
| this.notificationManager.show('Please enter a valid YouTube URL', 'error'); | |
| return; | |
| } | |
| this.showLoading(); | |
| try { | |
| // Simulate processing time | |
| await this.simulateProcessing(); | |
| this.showOutput(); | |
| this.notificationManager.show('Video processing completed successfully!', 'success'); | |
| } catch (error) { | |
| this.hideLoading(); | |
| this.notificationManager.show('Error processing video. Please try again.', 'error'); | |
| } | |
| } | |
| isValidYouTubeUrl(url) { | |
| const youtubeRegex = /^(https?\:\/\/)?(www\.)?(youtube\.com|youtu\.be)\/.+/; | |
| return youtubeRegex.test(url); | |
| } | |
| showLoading() { | |
| this.loadingSection.style.display = 'block'; | |
| this.outputSection.style.display = 'none'; | |
| this.generateBtn.disabled = true; | |
| } | |
| hideLoading() { | |
| this.loadingSection.style.display = 'none'; | |
| this.generateBtn.disabled = false; | |
| } | |
| async simulateProcessing() { | |
| // Simulate API calls and processing time | |
| return new Promise(resolve => { | |
| setTimeout(resolve, 3000); | |
| }); | |
| } | |
| showOutput() { | |
| this.hideLoading(); | |
| this.outputSection.style.display = 'block'; | |
| // Set demo transcript based on selected language | |
| const selectedLanguage = this.targetLanguageSelect.value; | |
| const demoTranscripts = { | |
| hindi: 'यह एक डेमो हिंदी ट्रांसक्रिप्ट है। वास्तविक एप्लिकेशन में, यह वीडियो से ट्रांसक्राइब और अनुवादित टेक्स्ट होगा।', | |
| tamil: 'இது ஒரு டெமோ தமிழ் டிரான்ஸ்கிரிப்ட் ஆகும். உண்மையான பயன்பாட்டில், இது வீடியோவில் இருந்து டிரான்ஸ்கிரைப் செய்யப்பட்ட மற்றும் மொழிபெயர்க்கப்பட்ட உரையாக இருக்கும்.', | |
| bengali: 'এটি একটি ডেমো বাংলা ট্রান্সক্রিপ্ট। প্রকৃত অ্যাপ্লিকেশনে, এটি ভিডিও থেকে ট্রান্সক্রিপ্ট এবং অনুবাদিত টেক্সট হবে।', | |
| telugu: 'ఇది ఒక డెమో తెలుగు ట్రాన్స్క్రిప్ట్. వాస్తవ అప్లికేషన్లో, ఇది వీడియో నుండి ట్రాన్స్క్రైబ్ చేయబడిన మరియు అనువదించబడిన టెక్స్ట్ అవుతుంది.', | |
| marathi: 'हे एक डेमो मराठी ट्रान्स्क्रिप्ट आहे. वास्तविक अनुप्रयोगात, हे व्हिडिओमधून ट्रान्सक्राइब केलेले आणि भाषांतरित मजकूर असेल।' | |
| }; | |
| this.hindiTranscript.value = demoTranscripts[selectedLanguage] || demoTranscripts.hindi; | |
| // Set demo video source (placeholder) | |
| this.dubbedVideo.src = 'data:video/mp4;base64,'; | |
| } | |
| handleDownload() { | |
| this.notificationManager.show('Download functionality would be implemented here', 'info'); | |
| } | |
| playVideo() { | |
| if (this.dubbedVideo.src) { | |
| this.dubbedVideo.play(); | |
| } else { | |
| this.notificationManager.show('No video available to play', 'warning'); | |
| } | |
| } | |
| pauseVideo() { | |
| this.dubbedVideo.pause(); | |
| } | |
| restartVideo() { | |
| this.dubbedVideo.currentTime = 0; | |
| this.dubbedVideo.play(); | |
| } | |
| } | |
| class NotificationManager { | |
| constructor() { | |
| this.container = this.createContainer(); | |
| } | |
| createContainer() { | |
| const container = document.createElement('div'); | |
| container.style.cssText = ` | |
| position: fixed; | |
| top: 20px; | |
| right: 20px; | |
| z-index: 10000; | |
| max-width: 300px; | |
| `; | |
| document.body.appendChild(container); | |
| return container; | |
| } | |
| show(message, type = 'info') { | |
| const notification = document.createElement('div'); | |
| notification.style.cssText = ` | |
| background: ${this.getNotificationColor(type)}; | |
| color: white; | |
| padding: 15px 20px; | |
| border-radius: 8px; | |
| margin-bottom: 10px; | |
| box-shadow: 0 4px 12px rgba(0,0,0,0.2); | |
| animation: slideIn 0.3s ease-out; | |
| display: flex; | |
| align-items: center; | |
| gap: 10px; | |
| `; | |
| notification.innerHTML = ` | |
| <i class="fas fa-${this.getNotificationIcon(type)}"></i> | |
| <span>${message}</span> | |
| `; | |
| this.container.appendChild(notification); | |
| setTimeout(() => { | |
| notification.style.animation = 'slideOut 0.3s ease-in'; | |
| setTimeout(() => { | |
| if (notification.parentNode) { | |
| notification.parentNode.removeChild(notification); | |
| } | |
| }, 300); | |
| }, 3000); | |
| } | |
| getNotificationIcon(type) { | |
| const icons = { | |
| success: 'check-circle', | |
| error: 'exclamation-circle', | |
| info: 'info-circle', | |
| warning: 'exclamation-triangle' | |
| }; | |
| return icons[type] || 'info-circle'; | |
| } | |
| getNotificationColor(type) { | |
| const colors = { | |
| success: '#28a745', | |
| error: '#dc3545', | |
| info: '#17a2b8', | |
| warning: '#ffc107' | |
| }; | |
| return colors[type] || '#17a2b8'; | |
| } | |
| } | |
| // Add CSS animations for notifications | |
| const style = document.createElement('style'); | |
| style.textContent = ` | |
| @keyframes slideIn { | |
| from { | |
| transform: translateX(100%); | |
| opacity: 0; | |
| } | |
| to { | |
| transform: translateX(0); | |
| opacity: 1; | |
| } | |
| } | |
| @keyframes slideOut { | |
| from { | |
| transform: translateX(0); | |
| opacity: 1; | |
| } | |
| to { | |
| transform: translateX(100%); | |
| opacity: 0; | |
| } | |
| } | |
| `; | |
| document.head.appendChild(style); | |
| // Initialize the app when DOM is loaded | |
| document.addEventListener('DOMContentLoaded', () => { | |
| new VideoDubbingApp(); | |
| }); | |
| // Add some demo data for testing | |
| window.addEventListener('load', () => { | |
| console.log('🎬 AI Video Dubbing App Loaded'); | |
| console.log('📝 This is a demo interface. In production, it would integrate with:'); | |
| console.log(' • YouTube API for video downloading'); | |
| console.log(' • Speech-to-text API for transcription'); | |
| console.log(' • Translation API for language conversion'); | |
| console.log(' • Text-to-speech API for voice synthesis'); | |
| console.log(' • Video processing for audio replacement'); | |
| }); | |