PL-9410440
  • اتصل بنا
  • سياسة الخصوصية
  • من نحن

🎨 شكل الهيدر

style
التحكم في المظهر:
غيّر رقم style:
0: الافتراضي (الموجي).
1: الإخباري (أحمر). 2: التقني (أزرق/كحلي). 3: الزجاجي العائم (Tech Glass).
4: الحواف الحادة (Neo-Brutalism).

محرر نصوص ذكي

  • الرئيسية
  • تدوينات

محرر الفيديو الاحترافي لدمج الصور والموسيقى

بواسطة morbah | مايو 28, 2026 | لا تعليقات
CINEMATIC STUDIO v11.0

استوديو المونتاج السينمائي الذكي فائق السلاسة

تحليل تلقائي للمشاهد، حساب ذكي للمدد حسب طول النص، زوم متناوب، وقطع فوري فائق الاستقرار.

1

محلل الاسكريبت والسيناريو

2

لوحة التحكم برفع صور المشاهد وتعديل المدد

3

غرفة المؤثرات والجماليات البصرية

جاري تحضير المحرك... 0%
يرجى رفع صور المشاهد لتنشيط الرندرة...

شاشة العرض النهائية

تحميل الفيديو بجودتك المختارة MP4

لم تفهم نقطة معينة؟

اسأل المساعد الذكي وسيجيبك بناءً على محتوى هذا المقال.

<!-- استدعاء مكتبة إصلاح ميتاداتا التوقيت للفيديو --> <script src="https://cdn.jsdelivr.net/npm/fix-webm-duration@1.0.6/fix-webm-duration.js"></script> <div class="pro-studio-container"> <div class="studio-header"> <div class="brand-tag">CINEMATIC STUDIO v11.0</div> <h2>استوديو المونتاج السينمائي الذكي فائق السلاسة</h2> <p class="subtitle font-cairo">تحليل تلقائي للمشاهد، حساب ذكي للمدد حسب طول النص، زوم متناوب، وقطع فوري فائق الاستقرار.</p> </div> <!-- خطوة 1: إدخال السيناريو وتفكيكه --> <div class="studio-section"> <div class="section-title"> <span class="step-badge">1</span> <h3>محلل الاسكريبت والسيناريو</h3> </div> <div class="script-input-area"> <label for="fullScript">ضع النص الكامل للفيديو هنا (يقبل "نهاية المشهد" أو "نهايه المشهد" بالتساوي):</label> <textarea id="fullScript" placeholder="اكتب الاسكريبت هنا...">You’re waiting for the "perfect moment" to start, aren't you? Waiting for the stars to align. Waiting to feel "ready." Here’s a cold truth: That feeling is a lie. The perfect moment is a myth designed to keep you comfortable. نهايه المشهد 1 Look at your life right now. Are you actually making progress, or are you just pretending? You watch the videos. You read the quotes. You make the plans. But when it’s time to actually sweat... You find an excuse. نهايه المشهد 2</textarea> <!-- خيار تحديد طريقة حساب المدة --> <div class="duration-method-box" style="margin-top: 15px;"> <label style="font-size: 13px; color: #94a3b8; display: block; margin-bottom: 8px;">طريقة تحديد مدة عرض المشاهد:</label> <select id="durationMethod" style="background-color: #15192c; color: white; border: 1px solid #1e2540; padding: 10px; border-radius: 6px; font-size: 12px; outline: none; width: 100%; max-width: 350px;"> <option value="auto" selected>وضع تلقائي ذكي (حساب المدة تلقائياً بناءً على طول النص)</option> <option value="manual">وضع يدوي ثابت (4 ثوانٍ افتراضية لكل مشهد)</option> </select> </div> <button id="parseScriptBtn" class="btn-primary">تحليل النص وتوليد المشاهد تلقائياً</button> </div> </div> <!-- خطوة 2: لوحة تحرير المشاهد الديناميكية (تظهر بعد التحليل) --> <div class="studio-section" id="scenesEditingSection" style="display:none;"> <div class="section-title"> <span class="step-badge">2</span> <h3>لوحة التحكم برفع صور المشاهد وتعديل المدد</h3> </div> <div id="scenesContainer" class="scenes-grid"> <!-- توليد المشاهد برمجياً وصورها المخصصة دون أي تعارض --> </div> </div> <!-- خطوة 3: التعديلات الاحترافية والمؤثرات البصرية --> <div class="studio-section"> <div class="section-title"> <span class="step-badge">3</span> <h3>غرفة المؤثرات والجماليات البصرية</h3> </div> <div class="effects-grid"> <!-- أبعاد الفيديو المتقدمة --> <div class="effect-card"> <label>أبعاد الفيديو (Aspect Ratio)</label> <select id="aspectRatio"> <option value="9_16" selected>طولي للجوال Reels/TikTok (9:16)</option> <option value="16_9">عرضي لليوتيوب (16:9)</option> <option value="1_1">مربع للإنستقرام (1:1)</option> </select> </div> <!-- اختيار الخطوط --> <div class="effect-card"> <label>نوع خط النصوص</label> <select id="textFont"> <option value="Arial, sans-serif">Kufi (Arial Simplified)</option> <option value="'Times New Roman', serif">Classic Serif</option> <option value="monospace">Digital Typewriter</option> </select> </div> <!-- تأثيرات بصرية حية --> <div class="effect-card checkbox-card"> <label><input type="checkbox" id="enableParticles" checked> تفعيل تأثير جزيئات الغبار النجمي المتطايرة</label> <label><input type="checkbox" id="enableKenBurns" checked> تفعيل زوم تقريبي سينمائي متناوب (داخل وخارج)</label> </div> <!-- الملف الصوتي --> <div class="effect-card"> <label>الصوت والخلفية الموسيقية</label> <input type="file" id="audioInput" accept="audio/*"> <audio id="bgAudio" controls style="display:none; width:100%; margin-top:10px;"></audio> </div> </div> </div> <!-- منطقة الرندرة والتصدير المتقدم --> <div class="render-zone"> <button id="generateBtn" disabled>البدء في تصدير الفيديو فائق النعومة</button> <div class="progress-wrapper" id="progressWrapper"> <div class="progress-info"> <span id="progressStep">جاري تحضير المحرك...</span> <span id="progressPercent">0%</span> </div> <div class="progress-bar-bg"> <div class="progress-bar-fill" id="progressBarFill"></div> </div> </div> <div id="status">يرجى رفع صور المشاهد لتنشيط الرندرة...</div> </div> <!-- شاشة العرض النهائية والتحميل --> <div class="output-zone" id="outputZone" style="display:none;"> <div class="divider"></div> <h3>شاشة العرض النهائية</h3> <video id="previewVideo" controls></video> <div class="download-action"> <a class="btn-download" id="downloadLink">تحميل الفيديو بجودتك المختارة MP4</a> </div> </div> <canvas id="videoCanvas" style="display:none;"></canvas> </div> <style> /* تصميم سينمائي متكامل واحترافي بمفهوم الاستوديو المظلم */ .pro-studio-container { direction: rtl; font-family: 'Segoe UI', Tahoma, Geneva, sans-serif; background-color: #080a10; color: #e2e8f0; border-radius: 20px; padding: 30px; max-width: 1000px; margin: 20px auto; box-shadow: 0 20px 50px rgba(0,0,0,0.9); border: 1px solid #1a2035; } .studio-header { text-align: center; margin-bottom: 35px; } .brand-tag { display: inline-block; background: linear-gradient(135deg, #00ffcc, #0055ff); color: #080a10; padding: 4px 15px; font-size: 11px; font-weight: bold; border-radius: 20px; margin-bottom: 12px; } .studio-header h2 { font-size: 28px; margin: 0; background: linear-gradient(to left, #00ffcc, #00a2ff); -webkit-background-clip: text; -webkit-text-fill-color: transparent; } .studio-header .subtitle { color: #94a3b8; font-size: 13px; margin-top: 8px; } .studio-section { background-color: #111422; padding: 24px; border-radius: 14px; border: 1px solid #1e2540; margin-bottom: 25px; } .section-title { display: flex; align-items: center; gap: 12px; margin-bottom: 20px; border-bottom: 1px solid #1e2540; padding-bottom: 12px; } .step-badge { background: #00ffcc; color: #080a10; width: 26px; height: 26px; border-radius: 50%; display: flex; align-items: center; justify-content: center; font-weight: bold; font-size: 13px; } .section-title h3 { margin: 0; font-size: 16px; color: #fff; } textarea { width: 100%; height: 180px; background-color: #080a10; border: 1px solid #1e2540; color: #fff; border-radius: 8px; padding: 15px; font-size: 13px; line-height: 1.6; outline: none; resize: vertical; box-sizing: border-box; } textarea:focus { border-color: #00ffcc; } .btn-primary { background: linear-gradient(135deg, #00ffcc, #0088ff); color: #080a10; border: none; padding: 12px 30px; font-size: 14px; font-weight: bold; border-radius: 8px; cursor: pointer; margin-top: 15px; transition: 0.3s; } .btn-primary:hover { transform: translateY(-2px); box-shadow: 0 4px 15px rgba(0,255,204,0.4); } .scenes-grid { display: grid; grid-template-columns: repeat(auto-fill, minmax(280px, 1fr)); gap: 20px; } .scene-card { background-color: #080a10; border: 1px solid #1e2540; border-radius: 10px; padding: 15px; display: flex; flex-direction: column; gap: 12px; } .scene-card h4 { margin: 0; color: #00ffcc; font-size: 14px; border-bottom: 1px solid #1e2540; padding-bottom: 6px; } .scene-card textarea { height: 80px; font-size: 11px; } .custom-file-upload { position: relative; display: flex; align-items: center; justify-content: center; background-color: #15192c; border: 1px dashed #3a457a; border-radius: 6px; padding: 10px; cursor: pointer; } .custom-file-upload input[type="file"] { position: absolute; left: 0; top: 0; opacity: 0; width: 100%; height: 100%; cursor: pointer; } .upload-text { font-size: 11px; color: #00ffcc; font-weight: bold; text-overflow: ellipsis; overflow: hidden; white-space: nowrap; max-width: 100%; } .img-preview { height: 120px; background-size: cover; background-repeat: no-repeat; background-position: center; background-color: #030407; border-radius: 6px; border: 1px solid #1e2540; } .scene-dur { display: flex; justify-content: space-between; align-items: center; font-size: 12px; color: #94a3b8; } .scene-dur input { width: 50px; background: #111422; color: white; border: 1px solid #1e2540; padding: 4px; border-radius: 4px; text-align: center; } .effects-grid { display: grid; grid-template-columns: repeat(auto-fill, minmax(200px, 1fr)); gap: 20px; } .effect-card { background-color: #080a10; padding: 15px; border-radius: 10px; border: 1px solid #1e2540; } .effect-card label { display: block; font-size: 12px; color: #94a3b8; margin-bottom: 8px; } .effect-card select, .effect-card input[type="file"] { width: 100%; background-color: #111422; color: #fff; border: 1px solid #1e2540; padding: 8px; border-radius: 6px; outline: none; font-size: 12px; box-sizing: border-box; } .checkbox-card { display: flex; flex-direction: column; gap: 12px; justify-content: center; } .checkbox-card label { display: flex; align-items: center; gap: 8px; cursor: pointer; margin: 0; font-size: 11px; } .render-zone { text-align: center; margin-top: 30px; background-color: #111422; padding: 25px; border-radius: 14px; border: 1px solid #1e2540; } #generateBtn { background: linear-gradient(135deg, #00ffcc, #0055ff); color: #080a10; border: none; padding: 15px 45px; font-size: 15px; font-weight: bold; border-radius: 30px; cursor: pointer; box-shadow: 0 4px 15px rgba(0,255,204,0.3); transition: 0.3s; } #generateBtn:disabled { background: #202438; color: #5d637c; cursor: not-allowed; box-shadow: none; } .progress-wrapper { margin-top: 20px; display: none; } .progress-info { display: flex; justify-content: space-between; font-size: 12px; color: #94a3b8; margin-bottom: 6px; } .progress-bar-bg { width: 100%; background-color: #080a10; height: 10px; border-radius: 10px; overflow: hidden; border: 1px solid #1e2540; } .progress-bar-fill { width: 0%; height: 100%; background: linear-gradient(to right, #00ffcc, #0055ff); border-radius: 10px; } #status { margin-top: 12px; font-size: 13px; color: #94a3b8; } .output-zone { margin-top: 30px; text-align: center; } .divider { border-top: 1px solid #1e2540; margin-bottom: 20px; } #previewVideo { max-width: 100%; border-radius: 10px; border: 1px solid #1e2540; background-color: #000; } .btn-download { display: inline-block; background: linear-gradient(135deg, #00ffcc, #28a745); color: #080a10 !important; text-decoration: none; padding: 14px 40px; border-radius: 30px; font-weight: bold; font-size: 15px; margin-top: 20px; } </style> <script> const fullScript = document.getElementById('fullScript'); const parseScriptBtn = document.getElementById('parseScriptBtn'); const scenesEditingSection = document.getElementById('scenesEditingSection'); const scenesContainer = document.getElementById('scenesContainer'); const generateBtn = document.getElementById('generateBtn'); const canvas = document.getElementById('videoCanvas'); const ctx = canvas.getContext('2d'); const status = document.getElementById('status'); const previewVideo = document.getElementById('previewVideo'); const downloadLink = document.getElementById('downloadLink'); const progressWrapper = document.getElementById('progressWrapper'); const progressBarFill = document.getElementById('progressBarFill'); const progressPercent = document.getElementById('progressPercent'); const progressStep = document.getElementById('progressStep'); const outputZone = document.getElementById('outputZone'); const audioInput = document.getElementById('audioInput'); const bgAudio = document.getElementById('bgAudio'); let parsedScenes = []; let audioFile = null; let particlesArray = []; // دالة حساب المدة تلقائياً بناءً على طول النص (الوضع التلقائي الذكي) function calculateAutoDuration(text) { const words = text.trim().split(/\s+/).filter(w => w.length > 0); const wordCount = words.length; // القاعدة: كل كلمة تأخذ 0.6 ثانية تقريباً للقراءة، مع حد أدنى 3 ثوانٍ وحد أقصى 15 ثانية للمشهد const duration = Math.max(3, Math.min(15, Math.ceil(wordCount * 0.6 + 1.5))); return duration; } // محلل الاسكريبت والسيناريو لإنشاء بطاقات تحرير المشاهد برمجياً وديناميكياً parseScriptBtn.addEventListener('click', () => { const text = fullScript.value; // تحليل الاسكريبت ودعم هاء وتاء المشاهد المكتوبة برمتها const chunks = text.split(/(?:نهاية|نهايه)\s*المشهد\s*\d*/gi); scenesContainer.innerHTML = ''; parsedScenes = []; const durationMethod = document.getElementById('durationMethod').value; let count = 0; chunks.forEach((chunk) => { const cleanText = chunk.trim(); if (cleanText !== "") { count++; // حساب المدة تلقائياً أو وضعها كـ 4 ثوانٍ يدوية let initialDuration = 4; if (durationMethod === 'auto') { initialDuration = calculateAutoDuration(cleanText); } const sceneData = { id: count, text: cleanText, imgObj: new Image(), imgLoaded: false, duration: initialDuration }; parsedScenes.push(sceneData); const sceneCard = document.createElement('div'); sceneCard.className = 'scene-card'; sceneCard.innerHTML = ` <h4>المشهد ${count}</h4> <textarea id="sceneText-${count}">${cleanText}</textarea> <div class="custom-file-upload"> <!-- استخدام data-scene-id لضمان عدم حدوث تعارض في قنوات رفع الصور --> <input type="file" class="scene-file-input" data-scene-id="${count}" id="sceneFile-${count}" accept="image/*"> <span class="upload-text" id="uploadText-${count}">اختر صورة المشهد</span> </div> <div id="scenePreview-${count}" class="img-preview" style="display:none;"></div> <div class="scene-dur"> <label>المدة (ثوانٍ):</label> <input type="number" id="sceneDuration-${count}" value="${initialDuration}" min="1" max="20"> </div> `; scenesContainer.appendChild(sceneCard); } }); scenesEditingSection.style.display = 'block'; status.innerText = `تم استخراج ${count} مشاهد. يرجى رفع صورة مخصصة لكل مشهد بالأسفل لتنشيط التصدير.`; }); // نظام الـ Event Delegation المضمون 100% لإسناد الصورة المرفوعة لبطاقة المشهد الصحيحة بلا تداخل scenesContainer.addEventListener('change', (e) => { if (e.target.classList.contains('scene-file-input')) { const fileInput = e.target; const sceneId = parseInt(fileInput.getAttribute('data-scene-id')); const file = fileInput.files[0]; if (file) { const scene = parsedScenes.find(s => s.id === sceneId); if (scene) { const uploadTextSpan = document.getElementById(`uploadText-${sceneId}`); const previewDiv = document.getElementById(`scenePreview-${sceneId}`); uploadTextSpan.innerText = file.name; const reader = new FileReader(); reader.onload = (ev) => { scene.imgObj.onload = () => { scene.imgLoaded = true; previewDiv.style.backgroundImage = `url('${ev.target.result}')`; previewDiv.style.display = 'block'; validateAllScenesReady(); }; scene.imgObj.src = ev.target.result; }; reader.readAsDataURL(file); } } } }); audioInput.addEventListener('change', (e) => { const file = e.target.files[0]; if (file) { audioFile = file; bgAudio.src = URL.createObjectURL(file); bgAudio.style.display = 'block'; } }); function validateAllScenesReady() { const allReady = parsedScenes.every(s => s.imgLoaded); if (allReady && parsedScenes.length > 0) { generateBtn.disabled = false; status.innerText = "كافة صور المشاهد مجهزة بالكامل! يمكنك الضغط على زر التصدير للرندرة."; } else { generateBtn.disabled = true; } } function initParticles(w, h) { particlesArray = []; for (let i = 0; i < 40; i++) { particlesArray.push({ x: Math.random() * w, y: Math.random() * h, vx: (Math.random() - 0.5) * 1.5, vy: -Math.random() * 1.2 - 0.4, size: Math.random() * 2.5 + 1, alpha: Math.random() * 0.6 + 0.2, decay: Math.random() * 0.005 + 0.002 }); } } function drawParticles(targetCtx, w, h) { targetCtx.save(); particlesArray.forEach((p) => { p.x += p.vx; p.y += p.vy; p.alpha -= p.decay; if (p.alpha <= 0 || p.y < 0 || p.x < 0 || p.x > w) { p.x = Math.random() * w; p.y = h; p.alpha = Math.random() * 0.6 + 0.4; p.vy = -Math.random() * 1.2 - 0.4; } targetCtx.fillStyle = `rgba(0, 255, 204, ${p.alpha})`; targetCtx.beginPath(); targetCtx.arc(p.x, p.y, p.size, 0, Math.PI * 2); targetCtx.fill(); }); targetCtx.restore(); } function preRenderImage(targetCtx, img, w, h) { targetCtx.clearRect(0, 0, w, h); targetCtx.fillStyle = "#000000"; targetCtx.fillRect(0, 0, w, h); const canvasRatio = w / h; const imgRatio = img.naturalWidth / img.naturalHeight; let dW, dH, oX, oY; if (imgRatio > canvasRatio) { dW = w; dH = w / imgRatio; oX = 0; oY = (h - dH) / 2; } else { dH = h; dW = h * imgRatio; oX = (w - dW) / 2; oY = 0; } targetCtx.drawImage(img, oX, oY, dW, dH); } generateBtn.addEventListener('click', async () => { progressStep.innerText = "جاري تهيئة وتحضير المشاهد للرندرة الفائقة..."; status.innerText = "بدأ محرك المونتاج التلقائي المعالجة المباشرة..."; generateBtn.disabled = true; outputZone.style.display = 'none'; progressWrapper.style.display = 'block'; progressBarFill.style.width = '0%'; progressPercent.innerText = '0%'; const ratio = document.getElementById('aspectRatio').value; let width, height; if (ratio === '9_16') { width = 1080; height = 1920; } else if (ratio === '16_9') { width = 1920; height = 1080; } else { width = 1080; height = 1080; } canvas.width = width; canvas.height = height; initParticles(width, height); // تحديث القيم اللوجيستية لكل مشهد وتجهيز لوحات الرندرة الخلفية المعزولة let totalDurationMs = 0; parsedScenes.forEach((scene) => { scene.text = document.getElementById(`sceneText-${scene.id}`).value.trim(); const durSec = parseFloat(document.getElementById(`sceneDuration-${scene.id}`).value) || 4; scene.durationMs = durSec * 1000; scene.startTime = totalDurationMs; scene.endTime = totalDurationMs + scene.durationMs; totalDurationMs += scene.durationMs; scene.offCanvas = document.createElement('canvas'); scene.offCanvas.width = width; scene.offCanvas.height = height; const offCtx = scene.offCanvas.getContext('2d'); preRenderImage(offCtx, scene.imgObj, width, height); }); // معدل 30 إطاراً لحماية العتاد واستقرار المخطط الزمني const fps = 30; const canvasStream = canvas.captureStream(fps); let outputStream = canvasStream; let audioContext = null; let audioSource = null; let audioDestination = null; if (audioFile) { try { audioContext = new (window.AudioContext || window.webkitAudioContext)(); audioSource = audioContext.createMediaElementSource(bgAudio); audioDestination = audioContext.createMediaStreamDestination(); audioSource.connect(audioDestination); audioSource.connect(audioContext.destination); const videoTrack = canvasStream.getVideoTracks()[0]; const audioTrack = audioDestination.stream.getAudioTracks()[0]; outputStream = new MediaStream([videoTrack, audioTrack]); } catch (e) { console.warn("تنبيه: فشل دمج الصوت، سيتم التصدير صامتاً:", e); } } let options = { mimeType: 'video/mp4;codecs=avc1' }; if (!MediaRecorder.isTypeSupported(options.mimeType)) { options = { mimeType: 'video/webm;codecs=vp9' }; } if (!MediaRecorder.isTypeSupported(options.mimeType)) { options = { mimeType: 'video/webm' }; } let mediaRecorder; try { mediaRecorder = new MediaRecorder(outputStream, options); mediaRecorder.onerror = (e) => { console.error("خطأ عتادي في مسجل الفيديو:", e); status.innerText = "خطأ في تشفير ملف الفيديو عتادياً: " + e.error.name; }; } catch (err) { status.innerText = "الترميز غير مدعوم في هذا المتصفح: " + err.message; generateBtn.disabled = false; return; } const chunks = []; mediaRecorder.ondataavailable = (e) => { if (e.data.size > 0) chunks.push(e.data); }; mediaRecorder.onstop = () => { progressStep.innerText = "جاري معالجة وحقن الميتاداتا..."; status.innerText = "تجميع ملف الـ MP4 وإصلاح الميتاداتا لمنع مشكلة توقيت الجوال 0:00..."; if (audioFile) { bgAudio.pause(); if (audioContext && audioContext.state !== 'closed') { audioContext.close(); } } const buggyBlob = new Blob(chunks, { type: options.mimeType }); if (typeof ysFixWebmDuration === 'function') { ysFixWebmDuration(buggyBlob, totalDurationMs, (fixedBlob) => { finalizeVideo(fixedBlob); }); } else { finalizeVideo(buggyBlob); } }; function finalizeVideo(finalBlob) { const videoURL = URL.createObjectURL(finalBlob); previewVideo.src = videoURL; outputZone.style.display = 'block'; if (ratio === '9_16') { previewVideo.style.width = "340px"; previewVideo.style.height = "604px"; } else { previewVideo.style.width = "640px"; previewVideo.style.height = "360px"; } downloadLink.href = videoURL; downloadLink.download = `cinematic_video_stable_${ratio}.mp4`; status.innerText = "اكتمل التصدير بنجاح! تم تطبيق الرندرة المتسلسلة الآمنة والقطع المباشر الفوري."; progressPercent.innerText = "100%"; progressBarFill.style.width = '100%'; progressStep.innerText = "اكتمل بنجاح!"; generateBtn.disabled = false; } if (audioFile) { bgAudio.currentTime = 0; bgAudio.play(); } mediaRecorder.start(); const enableParticles = document.getElementById('enableParticles').checked; const enableKenBurns = document.getElementById('enableKenBurns').checked; const selectedFont = document.getElementById('textFont').value; // الرندرة المتسلسلة الآمنة منخفضة التحميل العتادي تضمن انسيابية مطلقة const frameIntervalMs = 1000 / fps; const totalFrames = Math.ceil(totalDurationMs / frameIntervalMs); let currentFrame = 0; function renderFrameStep() { try { if (currentFrame >= totalFrames) { mediaRecorder.stop(); return; } const elapsed = currentFrame * frameIntervalMs; const progressPercentVal = Math.min((currentFrame / totalFrames) * 100, 100); progressBarFill.style.width = `${progressPercentVal.toFixed(0)}%`; progressPercent.innerText = `${progressPercentVal.toFixed(0)}%`; progressStep.innerText = `جاري رندرة الإطارات الحتمية... (${progressPercentVal.toFixed(0)}%)`; // رسم كادر المشهد الحالي بالتوقيت الحتمي drawFrame(elapsed); currentFrame++; // الفاصل الزمني المجهري (18ms) المانع لتوقف وجمود الجافا سكريبت في الهواتف setTimeout(() => { requestAnimationFrame(renderFrameStep); }, 18); } catch (err) { console.error("خطأ برمجي أثناء المونتاج المباشر:", err); status.innerText = "خطأ برمجي أثناء الرندرة: " + err.message; progressStep.innerText = "فشلت العملية"; generateBtn.disabled = false; if (mediaRecorder && mediaRecorder.state !== "inactive") { mediaRecorder.stop(); } } } // دالة الرندرة المعيارية المنضبطة (القطع المباشر الفوري الحاسم والآمن) function drawFrame(elapsed) { ctx.clearRect(0, 0, width, height); ctx.fillStyle = "#000000"; ctx.fillRect(0, 0, width, height); // البحث اللوجيستي الدقيق عن المشهد النشط let currentSceneIndex = parsedScenes.findIndex(s => elapsed >= s.startTime && elapsed < s.endTime); if (currentSceneIndex === -1) currentSceneIndex = parsedScenes.length - 1; const currentScene = parsedScenes[currentSceneIndex]; const sceneElapsed = elapsed - currentScene.startTime; // حساب أبعاد الزوم المتناوب بدقة سينمائية خطية تتماشى مع الفهرس المكتشف let zoomScale = 1.0; if (enableKenBurns) { const progress = sceneElapsed / currentScene.durationMs; if (currentSceneIndex % 2 === 0) { zoomScale = 1.0 + progress * 0.12; // زوم للداخل للمشهد الفردي } else { zoomScale = 1.12 - progress * 0.12; // زوم للخارج للمشهد الزوجي } } // رسم المشهد النشط مباشرة (قطع فوري ولحظي بدون تداخل أو تأثيرات تسبب بطء المعالجة) ctx.save(); const zoomW = width * zoomScale; const zoomH = height * zoomScale; const zoomX = (width - zoomW) / 2; const zoomY = (height - zoomH) / 2; ctx.drawImage(currentScene.offCanvas, zoomX, zoomY, zoomW, zoomH); ctx.restore(); if (enableParticles) { drawParticles(ctx, width, height); } // كتابة ترجمة نصوص المشهد النشط سطراً تلو الآخر تلقائياً const rawLines = currentScene.text.split('\n').map(l => l.trim()).filter(l => l !== ""); if (rawLines.length > 0) { const lineDuration = currentScene.durationMs / rawLines.length; const activeLineIndex = Math.floor(sceneElapsed / lineDuration); const activeText = rawLines[activeLineIndex] || rawLines[rawLines.length - 1]; ctx.save(); ctx.direction = 'rtl'; ctx.fillStyle = "#ffffff"; const fontSize = (height / 1080) * 52; ctx.font = `bold ${fontSize}px ${selectedFont}`; ctx.textAlign = 'center'; let textX = width / 2; let textY = height * 0.88; ctx.shadowColor = "rgba(0, 0, 0, 0.9)"; ctx.shadowBlur = 10; ctx.shadowOffsetX = 3; ctx.shadowOffsetY = 3; ctx.fillText(activeText, textX, textY); ctx.restore(); } } // بدء تشغيل الرندرة المتسلسلة renderFrameStep(); }); </script>

شارك المقال مع أصدقائك

Whatsapp Twitter X Facebook
Author

الكاتب : morbah

انا مهتم بمجال التقنية والربح من الانترنت واتطلع لنشر المزيد من المقالات التي تفيدكم

تعليقات

إرسال تعليق

⚙️ التحكم:
- data-active: اجعلها "true" للتفعيل أو "false" للإيقاف.
- data-time: مدة العداد بالثواني.
- data-page-url: رابط الصفحة التي أنشأتها للتحويل (يجب إنشاؤها يدوياً).

إعلان أول المقال

(يظهر تحت العنوان مباشرة - الحجم الموصى به: متجاوب)

إعلان وسط المقال

(الحجم الموصى به: متجاوب أو 336x280)

إعلان أسفل المقال

(الحجم الموصى به: متجاوب أو 336x280)

إعلان القائمة الجانبية

(الحجم الموصى به: 300x250)

مواقع التواصل الاجتماعي

المشاركات الشائعة

مشاركة مميزة

No Image
مايو 30, 2026

تحويل النص إلى صوت مباشرة على بلوجر تحدث الآن

إعلان أسفل الجانبية

(الحجم الموصى به: 300x250)

جميع الحقوق محفوظة © محرر نصوص ذكي
تنبيهات جديدة
جاري التحميل...

المساعد الذكي للمدونة

أهلاً بك! أنا مساعدك الشخصي في مدونة محرر نصوص ذكي. كيف يمكنني مساعدتك اليوم؟ يمكنك سؤالي عن أي مقال أو موضوع في المدونة.

مدعوم بواسطة MOPlus

شرح وتوضيح الفقرة

مشاركة في التطبيقات الأخرى

Telegram
Whatsapp
Twitter
Facebook
Tumblr
Reddit
LinkedIn
Pinterest
Email
نسخ رابط المقال
1523646181930228110