Spaces:
No application file
No application file
Create Script.js
Browse files
Script.js
ADDED
@@ -0,0 +1,235 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
class VideoDubbingApp {
|
2 |
+
constructor() {
|
3 |
+
this.initializeElements();
|
4 |
+
this.bindEvents();
|
5 |
+
this.notificationManager = new NotificationManager();
|
6 |
+
}
|
7 |
+
|
8 |
+
initializeElements() {
|
9 |
+
this.videoUrlInput = document.getElementById('videoUrl');
|
10 |
+
this.generateBtn = document.getElementById('generateBtn');
|
11 |
+
this.loadingSection = document.getElementById('loadingSection');
|
12 |
+
this.outputSection = document.getElementById('outputSection');
|
13 |
+
this.dubbedVideo = document.getElementById('dubbedVideo');
|
14 |
+
this.downloadBtn = document.getElementById('downloadBtn');
|
15 |
+
this.hindiTranscript = document.getElementById('hindiTranscript');
|
16 |
+
this.playBtn = document.getElementById('playBtn');
|
17 |
+
this.pauseBtn = document.getElementById('pauseBtn');
|
18 |
+
this.restartBtn = document.getElementById('restartBtn');
|
19 |
+
this.addSubtitlesCheckbox = document.getElementById('addSubtitles');
|
20 |
+
this.voiceStyleSelect = document.getElementById('voiceStyle');
|
21 |
+
this.targetLanguageSelect = document.getElementById('targetLanguage');
|
22 |
+
}
|
23 |
+
|
24 |
+
bindEvents() {
|
25 |
+
this.generateBtn.addEventListener('click', () => this.handleGenerate());
|
26 |
+
this.downloadBtn.addEventListener('click', () => this.handleDownload());
|
27 |
+
this.playBtn.addEventListener('click', () => this.playVideo());
|
28 |
+
this.pauseBtn.addEventListener('click', () => this.pauseVideo());
|
29 |
+
this.restartBtn.addEventListener('click', () => this.restartVideo());
|
30 |
+
}
|
31 |
+
|
32 |
+
async handleGenerate() {
|
33 |
+
const videoUrl = this.videoUrlInput.value.trim();
|
34 |
+
|
35 |
+
if (!videoUrl) {
|
36 |
+
this.notificationManager.show('Please enter a valid YouTube URL', 'error');
|
37 |
+
return;
|
38 |
+
}
|
39 |
+
|
40 |
+
if (!this.isValidYouTubeUrl(videoUrl)) {
|
41 |
+
this.notificationManager.show('Please enter a valid YouTube URL', 'error');
|
42 |
+
return;
|
43 |
+
}
|
44 |
+
|
45 |
+
this.showLoading();
|
46 |
+
|
47 |
+
try {
|
48 |
+
// Simulate processing time
|
49 |
+
await this.simulateProcessing();
|
50 |
+
this.showOutput();
|
51 |
+
this.notificationManager.show('Video processing completed successfully!', 'success');
|
52 |
+
} catch (error) {
|
53 |
+
this.hideLoading();
|
54 |
+
this.notificationManager.show('Error processing video. Please try again.', 'error');
|
55 |
+
}
|
56 |
+
}
|
57 |
+
|
58 |
+
isValidYouTubeUrl(url) {
|
59 |
+
const youtubeRegex = /^(https?\:\/\/)?(www\.)?(youtube\.com|youtu\.be)\/.+/;
|
60 |
+
return youtubeRegex.test(url);
|
61 |
+
}
|
62 |
+
|
63 |
+
showLoading() {
|
64 |
+
this.loadingSection.style.display = 'block';
|
65 |
+
this.outputSection.style.display = 'none';
|
66 |
+
this.generateBtn.disabled = true;
|
67 |
+
}
|
68 |
+
|
69 |
+
hideLoading() {
|
70 |
+
this.loadingSection.style.display = 'none';
|
71 |
+
this.generateBtn.disabled = false;
|
72 |
+
}
|
73 |
+
|
74 |
+
async simulateProcessing() {
|
75 |
+
// Simulate API calls and processing time
|
76 |
+
return new Promise(resolve => {
|
77 |
+
setTimeout(resolve, 3000);
|
78 |
+
});
|
79 |
+
}
|
80 |
+
|
81 |
+
showOutput() {
|
82 |
+
this.hideLoading();
|
83 |
+
this.outputSection.style.display = 'block';
|
84 |
+
|
85 |
+
// Set demo transcript based on selected language
|
86 |
+
const selectedLanguage = this.targetLanguageSelect.value;
|
87 |
+
const demoTranscripts = {
|
88 |
+
hindi: 'यह एक डेमो हिंदी ट्रांसक्रिप्ट है। वास्तविक एप्लिकेशन में, यह वीडियो से ट्रांसक्राइब और अनुवादित टेक्स्ट होगा।',
|
89 |
+
tamil: 'இது ஒரு டெமோ தமிழ் டிரான்ஸ்கிரிப்ட் ஆகும். உண்மையான பயன்பாட்டில், இது வீடியோவில் இருந்து டிரான்ஸ்கிரைப் செய்யப்பட்ட மற்றும் மொழிபெயர்க்கப்பட்ட உரையாக இருக்கும்.',
|
90 |
+
bengali: 'এটি একটি ডেমো বাংলা ট্রান্সক্রিপ্ট। প্রকৃত অ্যাপ্লিকেশনে, এটি ভিডিও থেকে ট্রান্সক্রিপ্ট এবং অনুবাদিত টেক্সট হবে।',
|
91 |
+
telugu: 'ఇది ఒక డెమో తెలుగు ట్రాన్స్క్రిప్ట్. వాస్తవ అప్లికేషన్లో, ఇది వీడియో నుండి ట్రాన్స్క్రైబ్ చేయబడిన మరియు అనువదించబడిన టెక్స్ట్ అవుతుంది.',
|
92 |
+
marathi: 'हे एक डेमो मराठी ट्रान्स्क्रिप्ट आहे. वास्तविक अनुप्रयोगात, हे व्हिडिओमधून ट���रान्सक्राइब केलेले आणि भाषांतरित मजकूर असेल।'
|
93 |
+
};
|
94 |
+
|
95 |
+
this.hindiTranscript.value = demoTranscripts[selectedLanguage] || demoTranscripts.hindi;
|
96 |
+
|
97 |
+
// Set demo video source (placeholder)
|
98 |
+
this.dubbedVideo.src = 'data:video/mp4;base64,';
|
99 |
+
}
|
100 |
+
|
101 |
+
handleDownload() {
|
102 |
+
this.notificationManager.show('Download functionality would be implemented here', 'info');
|
103 |
+
}
|
104 |
+
|
105 |
+
playVideo() {
|
106 |
+
if (this.dubbedVideo.src) {
|
107 |
+
this.dubbedVideo.play();
|
108 |
+
} else {
|
109 |
+
this.notificationManager.show('No video available to play', 'warning');
|
110 |
+
}
|
111 |
+
}
|
112 |
+
|
113 |
+
pauseVideo() {
|
114 |
+
this.dubbedVideo.pause();
|
115 |
+
}
|
116 |
+
|
117 |
+
restartVideo() {
|
118 |
+
this.dubbedVideo.currentTime = 0;
|
119 |
+
this.dubbedVideo.play();
|
120 |
+
}
|
121 |
+
}
|
122 |
+
|
123 |
+
class NotificationManager {
|
124 |
+
constructor() {
|
125 |
+
this.container = this.createContainer();
|
126 |
+
}
|
127 |
+
|
128 |
+
createContainer() {
|
129 |
+
const container = document.createElement('div');
|
130 |
+
container.style.cssText = `
|
131 |
+
position: fixed;
|
132 |
+
top: 20px;
|
133 |
+
right: 20px;
|
134 |
+
z-index: 10000;
|
135 |
+
max-width: 300px;
|
136 |
+
`;
|
137 |
+
document.body.appendChild(container);
|
138 |
+
return container;
|
139 |
+
}
|
140 |
+
|
141 |
+
show(message, type = 'info') {
|
142 |
+
const notification = document.createElement('div');
|
143 |
+
notification.style.cssText = `
|
144 |
+
background: ${this.getNotificationColor(type)};
|
145 |
+
color: white;
|
146 |
+
padding: 15px 20px;
|
147 |
+
border-radius: 8px;
|
148 |
+
margin-bottom: 10px;
|
149 |
+
box-shadow: 0 4px 12px rgba(0,0,0,0.2);
|
150 |
+
animation: slideIn 0.3s ease-out;
|
151 |
+
display: flex;
|
152 |
+
align-items: center;
|
153 |
+
gap: 10px;
|
154 |
+
`;
|
155 |
+
|
156 |
+
notification.innerHTML = `
|
157 |
+
<i class="fas fa-${this.getNotificationIcon(type)}"></i>
|
158 |
+
<span>${message}</span>
|
159 |
+
`;
|
160 |
+
|
161 |
+
this.container.appendChild(notification);
|
162 |
+
|
163 |
+
setTimeout(() => {
|
164 |
+
notification.style.animation = 'slideOut 0.3s ease-in';
|
165 |
+
setTimeout(() => {
|
166 |
+
if (notification.parentNode) {
|
167 |
+
notification.parentNode.removeChild(notification);
|
168 |
+
}
|
169 |
+
}, 300);
|
170 |
+
}, 3000);
|
171 |
+
}
|
172 |
+
|
173 |
+
getNotificationIcon(type) {
|
174 |
+
const icons = {
|
175 |
+
success: 'check-circle',
|
176 |
+
error: 'exclamation-circle',
|
177 |
+
info: 'info-circle',
|
178 |
+
warning: 'exclamation-triangle'
|
179 |
+
};
|
180 |
+
return icons[type] || 'info-circle';
|
181 |
+
}
|
182 |
+
|
183 |
+
getNotificationColor(type) {
|
184 |
+
const colors = {
|
185 |
+
success: '#28a745',
|
186 |
+
error: '#dc3545',
|
187 |
+
info: '#17a2b8',
|
188 |
+
warning: '#ffc107'
|
189 |
+
};
|
190 |
+
return colors[type] || '#17a2b8';
|
191 |
+
}
|
192 |
+
}
|
193 |
+
|
194 |
+
// Add CSS animations for notifications
|
195 |
+
const style = document.createElement('style');
|
196 |
+
style.textContent = `
|
197 |
+
@keyframes slideIn {
|
198 |
+
from {
|
199 |
+
transform: translateX(100%);
|
200 |
+
opacity: 0;
|
201 |
+
}
|
202 |
+
to {
|
203 |
+
transform: translateX(0);
|
204 |
+
opacity: 1;
|
205 |
+
}
|
206 |
+
}
|
207 |
+
|
208 |
+
@keyframes slideOut {
|
209 |
+
from {
|
210 |
+
transform: translateX(0);
|
211 |
+
opacity: 1;
|
212 |
+
}
|
213 |
+
to {
|
214 |
+
transform: translateX(100%);
|
215 |
+
opacity: 0;
|
216 |
+
}
|
217 |
+
}
|
218 |
+
`;
|
219 |
+
document.head.appendChild(style);
|
220 |
+
|
221 |
+
// Initialize the app when DOM is loaded
|
222 |
+
document.addEventListener('DOMContentLoaded', () => {
|
223 |
+
new VideoDubbingApp();
|
224 |
+
});
|
225 |
+
|
226 |
+
// Add some demo data for testing
|
227 |
+
window.addEventListener('load', () => {
|
228 |
+
console.log('🎬 AI Video Dubbing App Loaded');
|
229 |
+
console.log('📝 This is a demo interface. In production, it would integrate with:');
|
230 |
+
console.log(' • YouTube API for video downloading');
|
231 |
+
console.log(' • Speech-to-text API for transcription');
|
232 |
+
console.log(' • Translation API for language conversion');
|
233 |
+
console.log(' • Text-to-speech API for voice synthesis');
|
234 |
+
console.log(' • Video processing for audio replacement');
|
235 |
+
});
|