Files
freecut/static/index.html
T

243 lines
12 KiB
HTML
Raw Permalink Normal View History

<!DOCTYPE html>
<html lang="zh-CN">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>FreeCut 自由剪辑 · 免费开源视频编辑器</title>
<link rel="stylesheet" href="/css/style.css">
<link rel="icon" href="data:image/svg+xml,<svg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 100 100'><text y='.9em' font-size='90'>✂️</text></svg>">
<meta name="description" content="FreeCut 自由剪辑 —— 完全免费开源的视频编辑器,精美特效+优秀配乐,自媒体人放心用,企业/AI短剧才付费。">
</head>
<body>
<nav class="land-nav">
<span class="logo">✂️ FreeCut 自由剪辑</span>
<span class="spacer"></span>
<span id="nav-user" style="font-size:13px"></span>
<button class="btn small" id="nav-login">登录 / 注册</button>
<button class="btn small ghost hidden" id="nav-logout">退出</button>
<button class="btn small ghost hidden" id="nav-admin">后台</button>
</nav>
<section class="hero">
<h1>免费开源,<span class="grad">剪出大片</span><br>自媒体人的剪辑神器</h1>
<p>FreeCut 是一套完全免费的在线视频编辑器:精美特效、程序化原创配乐、文字字幕、转场动画,浏览器直接出片。
<b>个人自媒体永久免费</b>,视频制作公司与 AI 短剧批量生产才需要付费。</p>
<div class="cta">
<button class="btn" id="hero-start">🎬 立即开始创作</button>
<a class="btn ghost" href="#pricing">查看免费额度</a>
</div>
</section>
<section class="features">
<div class="feature"><div class="ic">🎨</div><h3>精美特效</h3><p>12 款一键滤镜:电影、复古、赛博、梦幻… 转场动画与文字动画任你选。</p></div>
<div class="feature"><div class="ic">🎼</div><h3>优秀配乐</h3><p>6 大情绪原创配乐,浏览器端实时合成、零版权风险,随时商用。</p></div>
<div class="feature"><div class="ic">✂️</div><h3>专业剪辑</h3><p>多轨道时间线、剪辑分割、拖动修剪、音量控制、画布比例(9:16/16:9/1:1)。</p></div>
<div class="feature"><div class="ic">🔒</div><h3>本地渲染</h3><p>视频在浏览器本地编码,素材隐私不出设备,服务器只存工程文件。</p></div>
<div class="feature"><div class="ic">💎</div><h3>个人免费</h3><p>个人自媒体每天 30 次导出额度,无水印、全功能,足够日常使用。</p></div>
<div class="feature"><div class="ic">🌱</div><h3>开源可部署</h3><p>纯 Flask + 原生前端,开源代码随意部署,数据都在自己手里。</p></div>
</section>
<section class="pricing" id="pricing">
<h2>💰 定价:普通人免费,生产方付费</h2>
<div class="price-grid">
<div class="price-card">
<div class="p-name">🆓 个人免费版</div>
<div class="p-price">¥0<small> / 永久</small></div>
<ul>
<li>全部功能免费使用</li>
<li>每天 30 次导出额度(够用)</li>
<li>无水印、可商用</li>
<li>特效 / 配乐 / 字幕全开放</li>
</ul>
<button class="btn block" data-go-editor>免费开始</button>
</div>
<div class="price-card hot">
<div class="p-name">🏢 企业版</div>
<div class="p-price">¥299<small> / 月</small></div>
<ul>
<li>不限量导出</li>
<li>团队协作(规划中)</li>
<li>优先渲染通道(规划中)</li>
<li>商用授权 + 技术支持</li>
</ul>
<button class="btn block" data-apply="business">申请企业版</button>
</div>
<div class="price-card">
<div class="p-name">🎬 AI 短剧版</div>
<div class="p-price">¥499<small> / 月</small></div>
<ul>
<li>不限量导出</li>
<li>批量生产流水线(规划中)</li>
<li>独享高速编码(规划中)</li>
<li>商用授权 + 专属支持</li>
</ul>
<button class="btn block" data-apply="ai_short">申请 AI 短剧版</button>
</div>
</div>
</section>
<section class="features" style="padding-top:0">
<div class="feature" style="grid-column:1/-1;text-align:center"><div class="ic">🧭</div><h3>创作流程</h3><p style="margin:0 auto;max-width:640px">① 上传或选择素材 → ② 拖入时间线,点击修剪分割 → ③ 一键加特效、配乐、转场、字幕 → ④ 导出 WebM 视频,直接发布。全部在浏览器完成。</p></div>
</section>
<footer class="footer">
<div>✂️ FreeCut 自由剪辑 · 免费开源 · 个人自媒体免费,企业与 AI 短剧付费</div>
<div style="margin-top:6px">构建于 Flask + 原生 JS + Web Audio / Canvas / MediaRecorder · 浏览器本地渲染</div>
<div style="margin-top:6px">© 2026 FreeCut · 开源协议(MIT)· 部署:<a href="/admin">管理后台</a></div>
</footer>
<!-- 登录/注册弹窗 -->
<div class="modal-mask hidden" id="auth-modal">
<div class="modal">
<h3 id="auth-title">登录 FreeCut</h3>
<div class="row"><label>用户名</label><input id="auth-user" autocomplete="username"></div>
<div class="row"><label>密码</label><input id="auth-pass" type="password" autocomplete="current-password"></div>
<div class="row hidden" id="auth-nick-row"><label>昵称</label><input id="auth-nick"></div>
<div id="auth-err" class="muted" style="color:var(--err);font-size:12px;min-height:16px"></div>
<button class="btn block" id="auth-submit">登录</button>
<p class="muted" style="text-align:center;margin-top:10px;font-size:12px">没有账号?<a href="#" id="auth-switch">注册一个(免费)</a></p>
</div>
</div>
<!-- 申请企业/AI版弹窗 -->
<div class="modal-mask hidden" id="apply-modal">
<div class="modal">
<h3 id="apply-title">申请开通</h3>
<div class="row" id="apply-desc" class="muted" style="font-size:13px"></div>
<div class="row"><label>联系方式(邮箱/微信/电话)</label><input id="apply-contact" placeholder="管理员审核通过后开通"></div>
<div id="apply-err" class="muted" style="color:var(--err);font-size:12px;min-height:16px"></div>
<div style="display:flex;gap:10px;justify-content:flex-end">
<button class="btn ghost" id="apply-close">取消</button>
<button class="btn" id="apply-submit">提交申请</button>
</div>
</div>
</div>
<script src="/js/common.js"></script>
<script>
(() => {
let mode = 'login';
let me = null;
const $ = s => document.querySelector(s);
function updateNav() {
if (me) {
$('#nav-user').textContent = `👤 ${me.nickname} · ${me.tier_name}`;
$('#nav-login').classList.add('hidden');
$('#nav-logout').classList.remove('hidden');
if (me.username === 'admin') $('#nav-admin').classList.remove('hidden');
else $('#nav-admin').classList.add('hidden');
} else {
$('#nav-user').textContent = '';
$('#nav-login').classList.remove('hidden');
$('#nav-logout').classList.add('hidden');
$('#nav-admin').classList.add('hidden');
}
}
async function loadMe() {
try { const r = await FC.api('/api/me'); me = { ...r.quota, username: r.quota.username }; updateNav(); }
catch (e) { me = null; updateNav(); }
}
function openAuth(m) {
mode = m || 'login';
$('#auth-title').textContent = mode === 'login' ? '登录 FreeCut' : '注册 FreeCut(免费)';
$('#auth-submit').textContent = mode === 'login' ? '登录' : '注册并开始';
$('#auth-nick-row').classList.toggle('hidden', mode === 'login');
$('#auth-err').textContent = '';
$('#auth-modal').classList.remove('hidden');
}
async function goEditor() {
if (!me) { openAuth('register'); FC.toast('请先注册(免费)'); return; }
try {
const r = await FC.api('/api/projects', { method: 'POST', body: { name: '我的新作品' } });
location.href = '/editor?id=' + r.id;
} catch (e) { FC.toast(e.message, 'err'); }
}
function renderProjects(list) {
const grid = $('#proj-grid');
if (!grid) return;
if (!list.length) {
grid.innerHTML = '<div class="empty">还没有作品,点右上角「新建作品」开始创作 ✂️</div>';
return;
}
grid.innerHTML = list.map(p => `
<div class="proj-card" data-id="${p.id}">
${p.thumb ? `<img class="proj-thumb" src="${p.thumb}" style="width:100%;aspect-ratio:16/9;object-fit:cover">` : '<div class="proj-thumb">🎬</div>'}
<div class="proj-info"><div class="t">${FC.esc(p.name)}</div><div class="s">${new Date(p.updated_at * 1000).toLocaleString()}</div></div>
</div>`).join('');
grid.querySelectorAll('.proj-card').forEach(c => c.addEventListener('click', () => {
location.href = '/editor?id=' + c.dataset.id;
}));
}
async function loadProjects() {
const r = await FC.api('/api/projects');
renderProjects(r.projects);
}
// 首页加载后如果有账号显示作品区
async function boot() {
await loadMe();
if (me) {
const sec = document.createElement('section');
sec.className = 'app-shell';
sec.innerHTML = `<h2 style="display:flex;align-items:center;gap:12px">📁 我的作品 <button class="btn small" id="new-proj"> 新建作品</button></h2><div class="proj-grid" id="proj-grid"></div>`;
document.querySelector('.features').after(sec);
$('#new-proj').addEventListener('click', goEditor);
loadProjects();
}
}
document.addEventListener('DOMContentLoaded', () => {
boot();
$('#nav-login').addEventListener('click', () => openAuth('login'));
$('#nav-logout').addEventListener('click', async () => { await FC.api('/api/auth/logout', { method: 'POST' }); me = null; updateNav(); location.reload(); });
$('#nav-admin').addEventListener('click', () => location.href = '/admin');
$('#hero-start').addEventListener('click', goEditor);
document.querySelectorAll('[data-go-editor]').forEach(b => b.addEventListener('click', goEditor));
// 认证
$('#auth-switch').addEventListener('click', e => { e.preventDefault(); mode = mode === 'login' ? 'register' : 'login'; openAuth(mode); });
$('#auth-submit').addEventListener('click', async () => {
const user = $('#auth-user').value.trim(), pass = $('#auth-pass').value, nick = $('#auth-nick').value.trim();
$('#auth-err').textContent = '';
try {
if (mode === 'login') {
await FC.api('/api/auth/login', { method: 'POST', body: { username: user, password: pass } });
} else {
await FC.api('/api/auth/register', { method: 'POST', body: { username: user, password: pass, nickname: nick } });
await FC.api('/api/auth/login', { method: 'POST', body: { username: user, password: pass } });
}
$('#auth-modal').classList.add('hidden');
FC.toast('欢迎回来!开始创作吧 🎉', 'ok');
location.reload();
} catch (e) { $('#auth-err').textContent = e.message; }
});
$('#auth-pass').addEventListener('keydown', e => { if (e.key === 'Enter') $('#auth-submit').click(); });
// 申请
let applyTier = 'business';
document.querySelectorAll('[data-apply]').forEach(b => b.addEventListener('click', () => {
if (!me) { openAuth('register'); return; }
applyTier = b.dataset.apply;
const isBiz = applyTier === 'business';
$('#apply-title').textContent = isBiz ? '🏢 申请企业版' : '🎬 申请 AI 短剧版';
$('#apply-desc').textContent = isBiz ? '企业版 ¥299/月 · 不限量导出、商用授权、团队协作(规划中)' : 'AI短剧版 ¥499/月 · 不限量导出、批量生产流水线(规划中)、商用授权';
$('#apply-err').textContent = '';
$('#apply-modal').classList.remove('hidden');
}));
$('#apply-close').addEventListener('click', () => $('#apply-modal').classList.add('hidden'));
$('#apply-submit').addEventListener('click', async () => {
try {
await FC.api('/api/upgrade/apply', { method: 'POST', body: { tier: applyTier, contact: $('#apply-contact').value.trim() } });
$('#apply-modal').classList.add('hidden');
FC.toast('申请已提交,管理员审核通过后自动开通 ✅', 'ok');
} catch (e) { $('#apply-err').textContent = e.message; }
});
});
})();
</script>
</body>
</html>