Update templates/video.html
Browse files- templates/video.html +21 -12
templates/video.html
CHANGED
|
@@ -561,11 +561,11 @@
|
|
| 561 |
|
| 562 |
function setAiLoaderText(text) { if (loaderTextOverlay) loaderTextOverlay.textContent = text; }
|
| 563 |
|
| 564 |
-
// تایمر
|
| 565 |
function startFakeProgress() {
|
| 566 |
clearInterval(fakeProgressInterval);
|
| 567 |
let currentProg = 0;
|
| 568 |
-
const targetSeconds =
|
| 569 |
const intervalMs = 200;
|
| 570 |
const increment = 100 / (targetSeconds * 1000 / intervalMs);
|
| 571 |
|
|
@@ -721,7 +721,6 @@
|
|
| 721 |
e.preventDefault();
|
| 722 |
const vData = videoBlobs.get(videoId);
|
| 723 |
const targetUrl = vData.remoteUrl ? vData.remoteUrl : vData.objectURL;
|
| 724 |
-
// ارسال لینک به برنامه اصلی اندروید از طریق postMessage
|
| 725 |
parent.postMessage({
|
| 726 |
type: 'DOWNLOAD_REQUEST',
|
| 727 |
url: targetUrl
|
|
@@ -855,6 +854,9 @@
|
|
| 855 |
const mergedBlob = await mergeVideosOnServer(baseVideoToMerge, newClipBlob);
|
| 856 |
if (!mergedBlob) return;
|
| 857 |
finalBlob = mergedBlob;
|
|
|
|
|
|
|
|
|
|
| 858 |
infoText = `ویدیوی تمدید شده (ترکیب ${clipCount + 1} کلیپ)`;
|
| 859 |
} else {
|
| 860 |
finalBlob = newClipBlob;
|
|
@@ -901,7 +903,6 @@
|
|
| 901 |
latestResultWrapper.innerHTML = '';
|
| 902 |
latestResultWrapper.appendChild(videoCard);
|
| 903 |
|
| 904 |
-
// ذخیره در ایندکس دیبی با آدرس ریموت
|
| 905 |
await projectDB.save('galleryState', { latestVideoId: newVideoId, videos: Array.from(videoBlobs.entries()).map(([id, data]) => ({id, blob: data.blob, infoText: data.infoText, remoteUrl: data.remoteUrl})) }).catch(err => console.error("Failed to save gallery state:", err));
|
| 906 |
|
| 907 |
addStatusMessage('ویدیو شما آماده شد! 🎉', 'success');
|
|
@@ -930,7 +931,7 @@
|
|
| 930 |
const { imageFile, userPrompt, duration, isExtension } = lastAttemptedPayload;
|
| 931 |
|
| 932 |
try {
|
| 933 |
-
setAiLoaderText('۱/۳: آپلود تصویر و
|
| 934 |
|
| 935 |
const formData = new FormData();
|
| 936 |
formData.append('image', imageFile, 'image.png');
|
|
@@ -978,6 +979,19 @@
|
|
| 978 |
|
| 979 |
async function startGenerationProcess() {
|
| 980 |
let imageToProcess, promptToUse, isExtensionRequest, baseVideoBlob, clipCount;
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 981 |
if (extensionJob) {
|
| 982 |
isExtensionRequest = true;
|
| 983 |
if (manualFrameBlob) {
|
|
@@ -995,7 +1009,7 @@
|
|
| 995 |
setUiLock(false); return;
|
| 996 |
}
|
| 997 |
}
|
| 998 |
-
promptToUse =
|
| 999 |
baseVideoBlob = extensionJob.baseVideoBlob;
|
| 1000 |
clipCount = extensionJob.clipCount;
|
| 1001 |
} else {
|
|
@@ -1008,12 +1022,10 @@
|
|
| 1008 |
return;
|
| 1009 |
}
|
| 1010 |
imageToProcess = currentImageFile;
|
| 1011 |
-
promptToUse = promptInput.value.trim();
|
| 1012 |
}
|
| 1013 |
|
| 1014 |
lastAttemptedPayload = { imageFile: imageToProcess, userPrompt: promptToUse, duration: parseFloat(durationSlider.value), isExtension: isExtensionRequest, baseVideoBlob, clipCount };
|
| 1015 |
|
| 1016 |
-
// چک کردن سیستم اعتبار برای کاربران رایگان قبل از شروع پردازش
|
| 1017 |
if (userSubscriptionStatus !== 'paid') {
|
| 1018 |
try {
|
| 1019 |
const response = await fetch('/api/check-credit', { method: 'POST', headers: { 'Content-Type': 'application/json' }, body: JSON.stringify({ fingerprint: userFingerprint }) });
|
|
@@ -1036,13 +1048,10 @@
|
|
| 1036 |
generateButton.addEventListener('click', async () => {
|
| 1037 |
if (generateButton.disabled) return;
|
| 1038 |
|
| 1039 |
-
// نمایش هشدار در صورت وجود پروژه قبلی و تلاش برای ساخت ویدیوی جدید بدون طولانی کردن
|
| 1040 |
if (!extensionJob && videoBlobs.size > 0) {
|
| 1041 |
projectWarningBox.style.display = 'block';
|
| 1042 |
generateButton.classList.add('shake-animation');
|
| 1043 |
-
setTimeout(() => {
|
| 1044 |
-
generateButton.classList.remove('shake-animation');
|
| 1045 |
-
}, 400);
|
| 1046 |
return;
|
| 1047 |
}
|
| 1048 |
projectWarningBox.style.display = 'none';
|
|
|
|
| 561 |
|
| 562 |
function setAiLoaderText(text) { if (loaderTextOverlay) loaderTextOverlay.textContent = text; }
|
| 563 |
|
| 564 |
+
// تایمر برای نوار پیشرفت تلویزیون
|
| 565 |
function startFakeProgress() {
|
| 566 |
clearInterval(fakeProgressInterval);
|
| 567 |
let currentProg = 0;
|
| 568 |
+
const targetSeconds = 140;
|
| 569 |
const intervalMs = 200;
|
| 570 |
const increment = 100 / (targetSeconds * 1000 / intervalMs);
|
| 571 |
|
|
|
|
| 721 |
e.preventDefault();
|
| 722 |
const vData = videoBlobs.get(videoId);
|
| 723 |
const targetUrl = vData.remoteUrl ? vData.remoteUrl : vData.objectURL;
|
|
|
|
| 724 |
parent.postMessage({
|
| 725 |
type: 'DOWNLOAD_REQUEST',
|
| 726 |
url: targetUrl
|
|
|
|
| 854 |
const mergedBlob = await mergeVideosOnServer(baseVideoToMerge, newClipBlob);
|
| 855 |
if (!mergedBlob) return;
|
| 856 |
finalBlob = mergedBlob;
|
| 857 |
+
|
| 858 |
+
remoteUrl = null; // برای دانلود مستقیم ویدیوی میکس شده
|
| 859 |
+
|
| 860 |
infoText = `ویدیوی تمدید شده (ترکیب ${clipCount + 1} کلیپ)`;
|
| 861 |
} else {
|
| 862 |
finalBlob = newClipBlob;
|
|
|
|
| 903 |
latestResultWrapper.innerHTML = '';
|
| 904 |
latestResultWrapper.appendChild(videoCard);
|
| 905 |
|
|
|
|
| 906 |
await projectDB.save('galleryState', { latestVideoId: newVideoId, videos: Array.from(videoBlobs.entries()).map(([id, data]) => ({id, blob: data.blob, infoText: data.infoText, remoteUrl: data.remoteUrl})) }).catch(err => console.error("Failed to save gallery state:", err));
|
| 907 |
|
| 908 |
addStatusMessage('ویدیو شما آماده شد! 🎉', 'success');
|
|
|
|
| 931 |
const { imageFile, userPrompt, duration, isExtension } = lastAttemptedPayload;
|
| 932 |
|
| 933 |
try {
|
| 934 |
+
setAiLoaderText('۱/۳: آپلود تصویر و بهینه سازی دستور...');
|
| 935 |
|
| 936 |
const formData = new FormData();
|
| 937 |
formData.append('image', imageFile, 'image.png');
|
|
|
|
| 979 |
|
| 980 |
async function startGenerationProcess() {
|
| 981 |
let imageToProcess, promptToUse, isExtensionRequest, baseVideoBlob, clipCount;
|
| 982 |
+
|
| 983 |
+
promptToUse = promptInput.value.trim();
|
| 984 |
+
const promptToUseLower = promptToUse.toLowerCase();
|
| 985 |
+
const forbiddenWords = ["sex", "sexy", "porn", "nude", "erotic", "سکس", "سکسی", "پورن", "شهوانی", "برهنه", "لخت"];
|
| 986 |
+
|
| 987 |
+
if (forbiddenWords.some(word => promptToUseLower.includes(word))) {
|
| 988 |
+
showCriticalError("متن ورودی شما حاوی کلمات نامناسب است. لطفاً آن را اصلاح کرده و مجدداً تلاش کنید.");
|
| 989 |
+
setUiLock(false);
|
| 990 |
+
statusSection.classList.remove('active');
|
| 991 |
+
aiLoader.style.display = 'none';
|
| 992 |
+
return;
|
| 993 |
+
}
|
| 994 |
+
|
| 995 |
if (extensionJob) {
|
| 996 |
isExtensionRequest = true;
|
| 997 |
if (manualFrameBlob) {
|
|
|
|
| 1009 |
setUiLock(false); return;
|
| 1010 |
}
|
| 1011 |
}
|
| 1012 |
+
promptToUse = promptToUse || originalUserPromptForExtension;
|
| 1013 |
baseVideoBlob = extensionJob.baseVideoBlob;
|
| 1014 |
clipCount = extensionJob.clipCount;
|
| 1015 |
} else {
|
|
|
|
| 1022 |
return;
|
| 1023 |
}
|
| 1024 |
imageToProcess = currentImageFile;
|
|
|
|
| 1025 |
}
|
| 1026 |
|
| 1027 |
lastAttemptedPayload = { imageFile: imageToProcess, userPrompt: promptToUse, duration: parseFloat(durationSlider.value), isExtension: isExtensionRequest, baseVideoBlob, clipCount };
|
| 1028 |
|
|
|
|
| 1029 |
if (userSubscriptionStatus !== 'paid') {
|
| 1030 |
try {
|
| 1031 |
const response = await fetch('/api/check-credit', { method: 'POST', headers: { 'Content-Type': 'application/json' }, body: JSON.stringify({ fingerprint: userFingerprint }) });
|
|
|
|
| 1048 |
generateButton.addEventListener('click', async () => {
|
| 1049 |
if (generateButton.disabled) return;
|
| 1050 |
|
|
|
|
| 1051 |
if (!extensionJob && videoBlobs.size > 0) {
|
| 1052 |
projectWarningBox.style.display = 'block';
|
| 1053 |
generateButton.classList.add('shake-animation');
|
| 1054 |
+
setTimeout(() => { generateButton.classList.remove('shake-animation'); }, 400);
|
|
|
|
|
|
|
| 1055 |
return;
|
| 1056 |
}
|
| 1057 |
projectWarningBox.style.display = 'none';
|