🎬 短剧批量生成器

剧本 / 分镜图 / 视频 — 一站式AI短剧创作

💳 ShortDrama Generator Pricing

$0
Free
Script & Characters
$9
900 Credits
~90 Images
$29.90
3000 Credits
Popular
$79.90
9000 Credits
Enterprise
📝 Script generation: FREE | 👤 Character profiles: FREE | 🖼️ Scene images: $0.1 each | 🎬 Video: $0.2/s

Taxes may apply and will be calculated at checkout.

📥 导入



⚠️ ZIP文件大小不超过99MB

✏️ 创作配置

// Authentication & Internationalization let currentUser = null; let currentLang = localStorage.getItem("language") || "zh"; // Translations const translations = { zh: { login: '登录', register: '注册', email: '邮箱', password: '密码', name: '昵称', loginBtn: '登录', registerBtn: '注册', noAccount: '还没有账号?', hasAccount: '已有账号?', registerNow: '立即注册', loginNow: '立即登录', logout: '退出', welcome: '欢迎', loginRequired: '请先登录', loginSuccess: '登录成功', registerSuccess: '注册成功', invalidCredentials: '邮箱或密码错误', emailExists: '邮箱已注册', title: '短剧批量生成器', subtitle: '剧本 / 分镜图 / 视频 — 一站式AI短剧创作', generate: '开始创作', scenes: '场景数', prompt: '输入你的创意...', scriptReview: '剧本审核', characters: '角色设定', generateImages: '生成分镜图', generateVideo: '生成视频', download: '下载', pricing: '💳 ShortDrama Generator Pricing', free: 'Free', popular: 'Popular', enterprise: 'Enterprise', buyCredits: '购买积分', viewPricing: '查看价格', scriptGenFree: '剧本生成: 免费', charProfileFree: '角色档案: 免费', sceneImagePrice: '场景图片: $0.1/张', videoPrice: '视频: $0.2/秒' }, en: { login: 'Login', register: 'Register', email: 'Email', password: 'Password', name: 'Name', loginBtn: 'Login', registerBtn: 'Register', noAccount: "Don't have an account?", hasAccount: 'Already have an account?', registerNow: 'Register now', loginNow: 'Login now', logout: 'Logout', welcome: 'Welcome', loginRequired: 'Please login first', loginSuccess: 'Login successful', registerSuccess: 'Registration successful', invalidCredentials: 'Invalid email or password', emailExists: 'Email already registered', title: 'ShortDrama Generator', subtitle: 'Script / Storyboard / Video — AI Short Drama Creation', generate: 'Start Creating', scenes: 'Scenes', prompt: 'Enter your idea...', scriptReview: 'Script Review', characters: 'Character Settings', generateImages: 'Generate Storyboard', generateVideo: 'Generate Video', download: 'Download', pricing: '💳 ShortDrama Generator Pricing', free: 'Free', popular: 'Popular', enterprise: 'Enterprise', buyCredits: 'Buy Credits', viewPricing: 'View Pricing', scriptGenFree: 'Script generation: FREE', charProfileFree: 'Character profiles: FREE', sceneImagePrice: 'Scene images: $0.1 each', videoPrice: 'Video: $0.2/s' } }; // Get translation function t(key) { return translations[currentLang][key] || key; } // Toggle language function toggleLanguage() { currentLang = currentLang === 'zh' ? 'en' : 'zh'; localStorage.setItem('language', currentLang); updateLanguage(); } // Update UI language function updateLanguage() { const langBtn = document.getElementById('langBtn'); if (langBtn) { langBtn.textContent = currentLang === 'zh' ? '🌐 中文' : '🌐 English'; } // Update title const title = document.querySelector('header h1'); if (title) title.textContent = '🎬 ' + t('title'); const subtitle = document.querySelector('header p'); if (subtitle) subtitle.textContent = t('subtitle'); // Update buttons const generateBtn = document.getElementById('generateBtn'); if (generateBtn) generateBtn.textContent = '🚀 ' + t('generate'); const loginBtn = document.getElementById('loginBtn'); if (loginBtn) loginBtn.textContent = t('login'); // Update login modal const loginTitle = document.getElementById('loginTitle'); if (loginTitle) loginTitle.textContent = isRegisterMode ? t('register') : t('login'); const loginSubmitBtn = document.getElementById('loginSubmitBtn'); if (loginSubmitBtn) loginSubmitBtn.textContent = isRegisterMode ? t('registerBtn') : t('loginBtn'); const loginToggleText = document.getElementById('loginToggleText'); if (loginToggleText) loginToggleText.textContent = isRegisterMode ? t('hasAccount') : t('noAccount'); const loginToggleLink = document.getElementById('loginToggleLink'); if (loginToggleLink) loginToggleLink.textContent = isRegisterMode ? t('loginNow') : t('registerNow'); // Update document language document.documentElement.lang = currentLang === 'zh' ? 'zh-CN' : 'en'; } // Show login modal let isRegisterMode = false; function showLoginModal() { document.getElementById('loginModal').style.display = 'flex'; isRegisterMode = false; updateLoginModal(); } function closeLoginModal() { document.getElementById('loginModal').style.display = 'none'; } function toggleLoginMode() { isRegisterMode = !isRegisterMode; updateLoginModal(); } function updateLoginModal() { const title = document.getElementById('loginTitle'); const submitBtn = document.getElementById('loginSubmitBtn'); const registerFields = document.getElementById('registerFields'); const toggleText = document.getElementById('loginToggleText'); const toggleLink = document.getElementById('loginToggleLink'); if (isRegisterMode) { title.textContent = t('register'); submitBtn.textContent = t('registerBtn'); registerFields.style.display = 'block'; toggleText.textContent = t('hasAccount'); toggleLink.textContent = t('loginNow'); } else { title.textContent = t('login'); submitBtn.textContent = t('loginBtn'); registerFields.style.display = 'none'; toggleText.textContent = t('noAccount'); toggleLink.textContent = t('registerNow'); } } // Handle login/register async function handleLogin() { const email = document.getElementById('loginEmail').value; const password = document.getElementById('loginPassword').value; if (!email || !password) { showToast(t('loginRequired'), 'warning'); return; } try { if (isRegisterMode) { // Register const name = document.getElementById('registerName').value; const res = await fetch('/api/auth/register', { method: 'POST', headers: { 'Content-Type': 'application/json' }, body: JSON.stringify({ email, password, name }) }); const data = await res.json(); if (data.success) { localStorage.setItem('auth_token', data.token); currentUser = data.user; updateUserUI(); closeLoginModal(); showToast(t('registerSuccess'), 'success'); } else { showToast(data.error || t('emailExists'), 'error'); } } else { // Login const res = await fetch('/api/auth/login', { method: 'POST', headers: { 'Content-Type': 'application/json' }, body: JSON.stringify({ email, password }) }); const data = await res.json(); if (data.success) { localStorage.setItem('auth_token', data.token); currentUser = data.user; if (data.user.language) { currentLang = data.user.language; localStorage.setItem('language', currentLang); } updateUserUI(); updateLanguage(); closeLoginModal(); showToast(t('loginSuccess'), 'success'); } else { showToast(data.error || t('invalidCredentials'), 'error'); } } } catch (err) { console.error('Auth error:', err); showToast('Error: ' + err.message, 'error'); } } // Update user UI function updateUserUI() { const userInfo = document.getElementById('userInfo'); const loginBtn = document.getElementById('loginBtn'); const userName = document.getElementById('userName'); if (currentUser) { userInfo.style.display = 'flex'; loginBtn.style.display = 'none'; userName.textContent = (currentLang === 'zh' ? t('welcome') + ', ' : t('welcome') + ', ') + (currentUser.name || currentUser.email); } else { userInfo.style.display = 'none'; loginBtn.style.display = 'block'; } } // Logout function logout() { localStorage.removeItem('auth_token'); currentUser = null; updateUserUI(); showToast(t('logout'), 'info'); } // Check auth status on load async function checkAuth() { const token = localStorage.getItem('auth_token'); if (!token) return; try { const res = await fetch('/api/auth/me', { headers: { 'Authorization': 'Bearer ' + token } }); const data = await res.json(); if (data.success) { currentUser = data.user; if (data.user.language) { currentLang = data.user.language; localStorage.setItem('language', currentLang); } updateUserUI(); updateLanguage(); } else { localStorage.removeItem('auth_token'); } } catch (err) { console.error('Auth check error:', err); } } // Initialize document.addEventListener('DOMContentLoaded', function() { checkAuth(); updateLanguage(); });