Compare commits
5 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
d7b827f28d | ||
|
|
0b6472b810 | ||
|
|
7ddebce93b | ||
|
|
c9041bde01 | ||
| 069dfc0ae4 |
66
.github/workflows/build-windows.yml
vendored
Normal file
66
.github/workflows/build-windows.yml
vendored
Normal file
@@ -0,0 +1,66 @@
|
|||||||
|
name: BatchTube Windows Build
|
||||||
|
|
||||||
|
on:
|
||||||
|
push:
|
||||||
|
tags:
|
||||||
|
- 'v*'
|
||||||
|
workflow_dispatch:
|
||||||
|
inputs:
|
||||||
|
version:
|
||||||
|
description: 'Version tag (e.g. v1.0.0)'
|
||||||
|
required: false
|
||||||
|
default: 'v1.0.0'
|
||||||
|
|
||||||
|
jobs:
|
||||||
|
build-windows:
|
||||||
|
runs-on: windows-latest
|
||||||
|
steps:
|
||||||
|
- name: Checkout
|
||||||
|
uses: actions/checkout@v4
|
||||||
|
|
||||||
|
- name: Setup Python 3.11
|
||||||
|
uses: actions/setup-python@v5
|
||||||
|
with:
|
||||||
|
python-version: '3.11'
|
||||||
|
|
||||||
|
- name: Install dependencies
|
||||||
|
run: |
|
||||||
|
cd backend
|
||||||
|
pip install --upgrade pip
|
||||||
|
pip install -r requirements.txt
|
||||||
|
pip install pyinstaller
|
||||||
|
|
||||||
|
- name: Download yt-dlp.exe
|
||||||
|
run: |
|
||||||
|
mkdir -p tools
|
||||||
|
curl -L https://github.com/yt-dlp/yt-dlp/releases/latest/download/yt-dlp.exe -o tools/yt-dlp.exe
|
||||||
|
|
||||||
|
- name: Create empty database
|
||||||
|
run: |
|
||||||
|
cd backend
|
||||||
|
python -c "import sqlite3; sqlite3.connect('youtube_sipoc.db').close()"
|
||||||
|
|
||||||
|
- name: Build Windows EXE
|
||||||
|
run: |
|
||||||
|
cd backend
|
||||||
|
pyinstaller batchtube-windows.spec --clean --noconfirm
|
||||||
|
|
||||||
|
- name: Install NSIS
|
||||||
|
run: choco install nsis -y
|
||||||
|
|
||||||
|
- name: Build NSIS Installer
|
||||||
|
run: makensis installer.nsi
|
||||||
|
|
||||||
|
- name: Upload EXE artifact
|
||||||
|
uses: actions/upload-artifact@v4
|
||||||
|
with:
|
||||||
|
name: BatchTube-Windows-EXE
|
||||||
|
path: backend/dist/BatchTube.exe
|
||||||
|
retention-days: 30
|
||||||
|
|
||||||
|
- name: Upload Installer artifact
|
||||||
|
uses: actions/upload-artifact@v4
|
||||||
|
with:
|
||||||
|
name: BatchTube-Windows-Installer
|
||||||
|
path: BatchTube-Setup-*.exe
|
||||||
|
retention-days: 30
|
||||||
116
WINDOWS_BUILD_README.md
Normal file
116
WINDOWS_BUILD_README.md
Normal file
@@ -0,0 +1,116 @@
|
|||||||
|
# BatchTube Windows Build Guide
|
||||||
|
Intentures LLC | https://batchtube.com | v1.0.0
|
||||||
|
|
||||||
|
## Files In This Package
|
||||||
|
|
||||||
|
| File | Location | Purpose |
|
||||||
|
|------|----------|---------|
|
||||||
|
| batchtube-launcher.py | backend/ | Windows entry point - starts FastAPI + opens browser |
|
||||||
|
| batchtube-windows.spec | backend/ | PyInstaller spec - single-file EXE with all deps |
|
||||||
|
| version_info.txt | backend/ | Windows EXE metadata |
|
||||||
|
| installer.nsi | project root | NSIS installer script |
|
||||||
|
| build_windows.bat | project root | One-click build script |
|
||||||
|
|
||||||
|
## Prerequisites
|
||||||
|
|
||||||
|
- Python 3.11+ (64-bit) - https://python.org/downloads
|
||||||
|
- NSIS 3.x - https://nsis.sourceforge.io/
|
||||||
|
- Git - https://git-scm.com
|
||||||
|
|
||||||
|
## Quick Build
|
||||||
|
|
||||||
|
Double-click build_windows.bat - it handles everything:
|
||||||
|
1. Creates virtual environment
|
||||||
|
2. Installs all Python dependencies
|
||||||
|
3. Downloads yt-dlp.exe
|
||||||
|
4. Runs PyInstaller -> backend/dist/BatchTube.exe
|
||||||
|
5. Runs NSIS -> BatchTube-Setup-1.0.0.exe
|
||||||
|
|
||||||
|
## Manual Build Steps
|
||||||
|
|
||||||
|
### Step 1 - Get Source
|
||||||
|
|
||||||
|
scp -r root@212.28.188.26:/root/batchtube-tauri ./batchtube
|
||||||
|
cd batchtube
|
||||||
|
|
||||||
|
### Step 2 - Fix config.py DB Path
|
||||||
|
|
||||||
|
Edit backend/config.py - replace the DB_PATH line:
|
||||||
|
|
||||||
|
# Before:
|
||||||
|
DB_PATH = os.path.join(os.path.dirname(__file__), "youtube_sipoc.db")
|
||||||
|
|
||||||
|
# After:
|
||||||
|
DB_PATH = os.environ.get(
|
||||||
|
'BATCHTUBE_DB_PATH',
|
||||||
|
os.path.join(os.path.dirname(__file__), "youtube_sipoc.db")
|
||||||
|
)
|
||||||
|
|
||||||
|
### Step 3 - Install Dependencies
|
||||||
|
|
||||||
|
cd backend
|
||||||
|
python -m venv venv
|
||||||
|
venv\Scripts\activate
|
||||||
|
pip install -r requirements.txt
|
||||||
|
pip install pyinstaller
|
||||||
|
|
||||||
|
### Step 4 - Download yt-dlp
|
||||||
|
|
||||||
|
mkdir ..\tools
|
||||||
|
curl -L https://github.com/yt-dlp/yt-dlp/releases/latest/download/yt-dlp.exe -o ..\tools\yt-dlp.exe
|
||||||
|
|
||||||
|
### Step 5 - Build EXE
|
||||||
|
|
||||||
|
pyinstaller batchtube-windows.spec --clean
|
||||||
|
# Output: backend/dist/BatchTube.exe
|
||||||
|
|
||||||
|
### Step 6 - Test EXE
|
||||||
|
|
||||||
|
dist\BatchTube.exe
|
||||||
|
# Browser should open to http://127.0.0.1:8765
|
||||||
|
|
||||||
|
### Step 7 - Build Installer
|
||||||
|
|
||||||
|
cd ..
|
||||||
|
makensis installer.nsi
|
||||||
|
# Output: BatchTube-Setup-1.0.0.exe
|
||||||
|
|
||||||
|
## Troubleshooting
|
||||||
|
|
||||||
|
| Problem | Fix |
|
||||||
|
|---------|-----|
|
||||||
|
| ModuleNotFoundError at runtime | Add to hiddenimports in batchtube-windows.spec |
|
||||||
|
| Web UI 404 | Check datas path ('web','backend/web') in spec |
|
||||||
|
| DB crash on launch | Apply config.py DB_PATH fix in Step 2 |
|
||||||
|
| App closes instantly | Set console=True in spec temporarily to see errors |
|
||||||
|
| SmartScreen warning | Code-sign BatchTube.exe with a Windows cert |
|
||||||
|
|
||||||
|
## After Install
|
||||||
|
|
||||||
|
| Path | Contents |
|
||||||
|
|------|----------|
|
||||||
|
| C:\Program Files\BatchTube\BatchTube.exe | Application |
|
||||||
|
| %APPDATA%\BatchTube\batchtube.db | SQLite database |
|
||||||
|
| Start Menu -> BatchTube | Launch shortcut |
|
||||||
|
| Desktop | Launch shortcut |
|
||||||
|
|
||||||
|
## GitHub Actions - Automated Windows Build
|
||||||
|
|
||||||
|
Add to .github/workflows/build.yml:
|
||||||
|
|
||||||
|
build-windows:
|
||||||
|
runs-on: windows-latest
|
||||||
|
steps:
|
||||||
|
- uses: actions/checkout@v4
|
||||||
|
- uses: actions/setup-python@v5
|
||||||
|
with: { python-version: '3.11' }
|
||||||
|
- run: pip install -r backend/requirements.txt pyinstaller
|
||||||
|
- run: cd backend && pyinstaller batchtube-windows.spec --clean
|
||||||
|
- run: choco install nsis -y && makensis installer.nsi
|
||||||
|
- uses: actions/upload-artifact@v4
|
||||||
|
with:
|
||||||
|
name: BatchTube-Windows
|
||||||
|
path: BatchTube-Setup-*.exe
|
||||||
|
|
||||||
|
---
|
||||||
|
Generated 2026-03-07 by Agent Developer - Intentures LLC
|
||||||
@@ -118,6 +118,40 @@ async def create_job(req: CreateJobRequest):
|
|||||||
if not req.input_value.strip():
|
if not req.input_value.strip():
|
||||||
raise HTTPException(status_code=400, detail="input_value is required")
|
raise HTTPException(status_code=400, detail="input_value is required")
|
||||||
|
|
||||||
|
|
||||||
|
# ── Free Tier Enforcement ─────────────────────────────────────────────────
|
||||||
|
plan = config.BATCHTUBE_PLAN
|
||||||
|
limits = config.PLAN_LIMITS.get(plan, config.PLAN_LIMITS["free"])
|
||||||
|
|
||||||
|
# Cap resolution for free tier
|
||||||
|
resolution = req.resolution
|
||||||
|
max_res = limits.get("max_resolution")
|
||||||
|
if max_res and max_res != "best":
|
||||||
|
res_order = config.AVAILABLE_RESOLUTIONS # ["best", "4320", ..., "144"]
|
||||||
|
# Lower index = higher quality; cap if requested res is higher than allowed
|
||||||
|
def res_index(r):
|
||||||
|
try:
|
||||||
|
return res_order.index(r)
|
||||||
|
except ValueError:
|
||||||
|
return len(res_order)
|
||||||
|
if res_index(resolution) < res_index(max_res):
|
||||||
|
logger.info(f"Free tier: capping resolution from {resolution} to {max_res}")
|
||||||
|
resolution = max_res
|
||||||
|
else:
|
||||||
|
resolution = req.resolution
|
||||||
|
|
||||||
|
# For CSV input: enforce max_videos limit upfront
|
||||||
|
max_videos = limits.get("max_videos")
|
||||||
|
if max_videos is not None and req.input_type == "csv":
|
||||||
|
csv_lines = [ln.strip() for ln in req.input_value.strip().splitlines() if ln.strip()]
|
||||||
|
if len(csv_lines) > max_videos:
|
||||||
|
raise HTTPException(
|
||||||
|
status_code=403,
|
||||||
|
detail=f"Free tier is limited to {max_videos} videos per batch. "
|
||||||
|
f"Upgrade to Creator or Pro for larger batches. "
|
||||||
|
f"({len(csv_lines)} URLs submitted)"
|
||||||
|
)
|
||||||
|
|
||||||
# Create the folder if it doesn't exist
|
# Create the folder if it doesn't exist
|
||||||
try:
|
try:
|
||||||
Path(output_folder).mkdir(parents=True, exist_ok=True)
|
Path(output_folder).mkdir(parents=True, exist_ok=True)
|
||||||
@@ -128,7 +162,7 @@ async def create_job(req: CreateJobRequest):
|
|||||||
job_id = db.create_job(
|
job_id = db.create_job(
|
||||||
output_folder=output_folder,
|
output_folder=output_folder,
|
||||||
selections=req.selections,
|
selections=req.selections,
|
||||||
resolution=req.resolution,
|
resolution=resolution, # may be capped by free tier enforcement
|
||||||
delay_min=req.delay_min,
|
delay_min=req.delay_min,
|
||||||
delay_max=req.delay_max,
|
delay_max=req.delay_max,
|
||||||
input_type=req.input_type,
|
input_type=req.input_type,
|
||||||
|
|||||||
34
backend/batchtube-launcher.py
Normal file
34
backend/batchtube-launcher.py
Normal file
@@ -0,0 +1,34 @@
|
|||||||
|
import sys, os, time, socket, threading, webbrowser
|
||||||
|
if getattr(sys, 'frozen', False):
|
||||||
|
BASE_DIR = sys._MEIPASS
|
||||||
|
APP_DIR = os.path.dirname(sys.executable)
|
||||||
|
else:
|
||||||
|
BASE_DIR = os.path.dirname(os.path.abspath(__file__))
|
||||||
|
APP_DIR = BASE_DIR
|
||||||
|
BACKEND_DIR = os.path.join(BASE_DIR,'backend') if os.path.isdir(os.path.join(BASE_DIR,'backend')) else BASE_DIR
|
||||||
|
sys.path.insert(0, BACKEND_DIR)
|
||||||
|
sys.path.insert(0, BASE_DIR)
|
||||||
|
APPDATA_DIR = os.path.join(os.environ.get('APPDATA', APP_DIR), 'BatchTube')
|
||||||
|
os.makedirs(APPDATA_DIR, exist_ok=True)
|
||||||
|
os.environ['BATCHTUBE_DB_PATH'] = os.path.join(APPDATA_DIR, 'batchtube.db')
|
||||||
|
for c in [os.path.join(APP_DIR,'yt-dlp.exe'), os.path.join(BASE_DIR,'yt-dlp.exe')]:
|
||||||
|
if os.path.exists(c): os.environ['YTDLP_PATH'] = c; break
|
||||||
|
for d in [os.path.join(APP_DIR,'ffmpeg'), os.path.join(BASE_DIR,'ffmpeg')]:
|
||||||
|
if os.path.isdir(d): os.environ['PATH'] = d + os.pathsep + os.environ.get('PATH',''); break
|
||||||
|
HOST, PORT = '127.0.0.1', 8765
|
||||||
|
URL = f'http://{HOST}:{PORT}'
|
||||||
|
def is_open(h, p, t=0.5):
|
||||||
|
try:
|
||||||
|
with socket.create_connection((h,p), timeout=t): return True
|
||||||
|
except: return False
|
||||||
|
def open_browser():
|
||||||
|
for _ in range(60):
|
||||||
|
if is_open(HOST, PORT): time.sleep(0.3); webbrowser.open(URL); return
|
||||||
|
time.sleep(0.5)
|
||||||
|
def run_server():
|
||||||
|
import uvicorn
|
||||||
|
os.chdir(BACKEND_DIR)
|
||||||
|
uvicorn.run('api_server:app', host=HOST, port=PORT, log_level='warning', access_log=False)
|
||||||
|
if __name__ == '__main__':
|
||||||
|
threading.Thread(target=open_browser, daemon=True).start()
|
||||||
|
run_server()
|
||||||
54
backend/batchtube-windows.spec
Normal file
54
backend/batchtube-windows.spec
Normal file
@@ -0,0 +1,54 @@
|
|||||||
|
# batchtube-windows.spec
|
||||||
|
# PyInstaller spec for Windows single-file EXE
|
||||||
|
# Run from backend/ directory: pyinstaller batchtube-windows.spec --clean
|
||||||
|
# Output: dist/BatchTube.exe
|
||||||
|
|
||||||
|
from PyInstaller.utils.hooks import collect_all
|
||||||
|
block_cipher = None
|
||||||
|
datas, binaries, hiddenimports = [], [], []
|
||||||
|
for pkg in ['yt_dlp','uvicorn','fastapi','starlette','anyio','sse_starlette','youtube_transcript_api','openai','pydantic']:
|
||||||
|
d,b,h = collect_all(pkg)
|
||||||
|
datas+=d; binaries+=b; hiddenimports+=h
|
||||||
|
datas += [('web','backend/web')]
|
||||||
|
hiddenimports += [
|
||||||
|
'uvicorn.logging','uvicorn.loops','uvicorn.loops.auto','uvicorn.loops.asyncio',
|
||||||
|
'uvicorn.protocols','uvicorn.protocols.http','uvicorn.protocols.http.auto',
|
||||||
|
'uvicorn.protocols.http.h11_impl','uvicorn.protocols.http.httptools_impl',
|
||||||
|
'uvicorn.protocols.websockets','uvicorn.protocols.websockets.auto',
|
||||||
|
'uvicorn.lifespan','uvicorn.lifespan.off','uvicorn.lifespan.on',
|
||||||
|
'fastapi','fastapi.middleware.cors','starlette.middleware.cors',
|
||||||
|
'sse_starlette','sse_starlette.sse',
|
||||||
|
'pydantic','pydantic.v1','pydantic_core','annotated_types','typing_extensions',
|
||||||
|
'h11','httptools','httpx','anyio','anyio._backends._asyncio','sniffio',
|
||||||
|
'multipart','python_multipart','aiofiles','aiofiles.os','aiofiles.threadpool',
|
||||||
|
'yt_dlp','yt_dlp.extractor','yt_dlp.downloader','yt_dlp.postprocessor',
|
||||||
|
'youtube_transcript_api','youtube_transcript_api._transcripts',
|
||||||
|
'openai','openai.resources',
|
||||||
|
'requests','urllib3','certifi','charset_normalizer',
|
||||||
|
'slugify','python_slugify','tqdm','tqdm.auto',
|
||||||
|
'sqlite3','_sqlite3','asyncio','concurrent.futures','threading','queue',
|
||||||
|
'websockets','click','rich','watchfiles','mcp',
|
||||||
|
'api_server','worker','database','extractors','config',
|
||||||
|
]
|
||||||
|
a = Analysis(
|
||||||
|
['batchtube-launcher.py'],
|
||||||
|
pathex=['.'],
|
||||||
|
binaries=binaries,
|
||||||
|
datas=datas,
|
||||||
|
hiddenimports=hiddenimports,
|
||||||
|
hookspath=[],
|
||||||
|
runtime_hooks=[],
|
||||||
|
excludes=['tkinter','matplotlib','numpy','pandas','torch','tensorflow','PyQt5','PyQt6'],
|
||||||
|
cipher=block_cipher,
|
||||||
|
noarchive=False,
|
||||||
|
)
|
||||||
|
pyz = PYZ(a.pure, a.zipped_data, cipher=block_cipher)
|
||||||
|
exe = EXE(
|
||||||
|
pyz, a.scripts, a.binaries, a.zipfiles, a.datas, [],
|
||||||
|
name='BatchTube',
|
||||||
|
debug=False, strip=False, upx=True,
|
||||||
|
runtime_tmpdir=None,
|
||||||
|
console=False,
|
||||||
|
icon='../src-tauri/icons/icon.ico',
|
||||||
|
version='version_info.txt',
|
||||||
|
)
|
||||||
@@ -1,5 +1,5 @@
|
|||||||
"""
|
"""
|
||||||
config.py - Default configuration for YouTube SIPOC Tool
|
config.py - Default configuration for BatchTube
|
||||||
"""
|
"""
|
||||||
import os
|
import os
|
||||||
|
|
||||||
@@ -32,7 +32,40 @@ SUMMARY_MAX_TOKENS = 1024
|
|||||||
MAX_TITLE_LENGTH = 80 # characters - truncate long titles in filenames
|
MAX_TITLE_LENGTH = 80 # characters - truncate long titles in filenames
|
||||||
|
|
||||||
# ── Database ──────────────────────────────────────────────────────────────────
|
# ── Database ──────────────────────────────────────────────────────────────────
|
||||||
DB_PATH = os.path.join(os.path.dirname(__file__), "youtube_sipoc.db")
|
# Windows-safe: allow override via env var (avoids path issues in PyInstaller bundles)
|
||||||
|
DB_PATH = os.environ.get(
|
||||||
|
"BATCHTUBE_DB_PATH",
|
||||||
|
os.path.join(os.path.dirname(__file__), "youtube_sipoc.db")
|
||||||
|
)
|
||||||
|
|
||||||
# ── Artifact Types ────────────────────────────────────────────────────────────
|
# ── Artifact Types ────────────────────────────────────────────────────────────
|
||||||
ARTIFACT_TYPES = ["title", "stats", "transcript", "summary", "thumbnail", "mp3", "mp4"]
|
ARTIFACT_TYPES = ["title", "stats", "transcript", "summary", "thumbnail", "mp3", "mp4"]
|
||||||
|
|
||||||
|
# ── Licensing / Plan Tiers ────────────────────────────────────────────────────
|
||||||
|
# Plan is set via environment variable BATCHTUBE_PLAN.
|
||||||
|
# Valid values: free | creator | pro | studio | lifetime
|
||||||
|
# Defaults to 'free' — license validation layer overrides this at runtime.
|
||||||
|
BATCHTUBE_PLAN = os.environ.get("BATCHTUBE_PLAN", "free").lower()
|
||||||
|
|
||||||
|
# ── Free Tier Limits (updated 2026-03-07) ─────────────────────────────────────
|
||||||
|
# Free tier: 3 videos/batch max (tightened from 5), 720p max resolution
|
||||||
|
FREE_TIER_MAX_VIDEOS = 3 # max videos per batch job on free plan
|
||||||
|
FREE_TIER_MAX_RESOLUTION = "720" # max resolution on free plan (was 1080p)
|
||||||
|
|
||||||
|
# ── Plan Limits Map ───────────────────────────────────────────────────────────
|
||||||
|
# Maps plan name -> {max_videos, max_resolution}; None = unlimited
|
||||||
|
PLAN_LIMITS = {
|
||||||
|
"free": {"max_videos": FREE_TIER_MAX_VIDEOS, "max_resolution": FREE_TIER_MAX_RESOLUTION},
|
||||||
|
"creator": {"max_videos": 100, "max_resolution": "1080"},
|
||||||
|
"pro": {"max_videos": None, "max_resolution": "best"},
|
||||||
|
"studio": {"max_videos": None, "max_resolution": "best"},
|
||||||
|
"lifetime": {"max_videos": None, "max_resolution": "best"},
|
||||||
|
}
|
||||||
|
|
||||||
|
# ── Pricing Reference (2026-03-07 approved) ───────────────────────────────────
|
||||||
|
# Free: 3 videos/batch, 720p max
|
||||||
|
# Creator: $19/mo or $149/yr — 100 videos/batch, 1080p
|
||||||
|
# Pro: $39/mo or $299/yr — unlimited, 4K
|
||||||
|
# Studio: $79/mo — 3 seats, API access
|
||||||
|
# Lifetime: $197 one-time — unlimited, all features
|
||||||
|
# AppSumo: $79 one-time — limited launch deal
|
||||||
|
|||||||
16
backend/version_info.txt
Normal file
16
backend/version_info.txt
Normal file
@@ -0,0 +1,16 @@
|
|||||||
|
VSVersionInfo(
|
||||||
|
ffi=FixedFileInfo(filevers=(1,0,0,0),prodvers=(1,0,0,0),mask=0x3f,flags=0x0,OS=0x40004,fileType=0x1,subtype=0x0,date=(0,0)),
|
||||||
|
kids=[
|
||||||
|
StringFileInfo([StringTable(u'040904B0',[
|
||||||
|
StringStruct(u'CompanyName',u'Intentures LLC'),
|
||||||
|
StringStruct(u'FileDescription',u'BatchTube - Batch YouTube Content Extractor'),
|
||||||
|
StringStruct(u'FileVersion',u'1.0.0.0'),
|
||||||
|
StringStruct(u'InternalName',u'BatchTube'),
|
||||||
|
StringStruct(u'LegalCopyright',u'Copyright (C) 2026 Intentures LLC'),
|
||||||
|
StringStruct(u'OriginalFilename',u'BatchTube.exe'),
|
||||||
|
StringStruct(u'ProductName',u'BatchTube'),
|
||||||
|
StringStruct(u'ProductVersion',u'1.0.0.0'),
|
||||||
|
])]),
|
||||||
|
VarFileInfo([VarStruct(u'Translation',[1033,1200])])
|
||||||
|
]
|
||||||
|
)
|
||||||
@@ -171,6 +171,27 @@ def run_job(job_id: str):
|
|||||||
unique_videos.append(v)
|
unique_videos.append(v)
|
||||||
videos = unique_videos
|
videos = unique_videos
|
||||||
|
|
||||||
|
# ── Free Tier: Enforce max videos per batch ───────────────────────────
|
||||||
|
plan = config.BATCHTUBE_PLAN
|
||||||
|
limits = config.PLAN_LIMITS.get(plan, config.PLAN_LIMITS["free"])
|
||||||
|
max_videos = limits.get("max_videos")
|
||||||
|
if max_videos is not None and len(videos) > max_videos:
|
||||||
|
db.add_log(
|
||||||
|
job_id,
|
||||||
|
f"Free tier limit: truncating batch from {len(videos)} to {max_videos} videos. "
|
||||||
|
f"Upgrade to Creator or Pro for larger batches.",
|
||||||
|
level="WARN"
|
||||||
|
)
|
||||||
|
_emit(job_id, "tier_limit", {
|
||||||
|
"job_id": job_id,
|
||||||
|
"plan": plan,
|
||||||
|
"requested": len(videos),
|
||||||
|
"allowed": max_videos,
|
||||||
|
"message": f"Free tier: batch limited to {max_videos} videos. Upgrade for more."
|
||||||
|
})
|
||||||
|
videos = videos[:max_videos]
|
||||||
|
|
||||||
|
|
||||||
# ── Step 2: Register videos in DB ────────────────────────────────────
|
# ── Step 2: Register videos in DB ────────────────────────────────────
|
||||||
for i, v in enumerate(videos):
|
for i, v in enumerate(videos):
|
||||||
db.upsert_video(job_id, v["video_id"], v["url"], v.get("title", ""), i)
|
db.upsert_video(job_id, v["video_id"], v["url"], v.get("title", ""), i)
|
||||||
|
|||||||
45
build_windows.bat
Normal file
45
build_windows.bat
Normal file
@@ -0,0 +1,45 @@
|
|||||||
|
@echo off
|
||||||
|
title BatchTube Windows Build
|
||||||
|
echo.
|
||||||
|
echo ============================================================
|
||||||
|
echo BatchTube Windows Installer Builder v1.0.0
|
||||||
|
echo Intentures LLC - https://batchtube.com
|
||||||
|
echo ============================================================
|
||||||
|
echo.
|
||||||
|
|
||||||
|
python --version >nul 2>&1
|
||||||
|
if errorlevel 1 (echo ERROR: Python not found. Install Python 3.11+ && pause && exit /b 1)
|
||||||
|
|
||||||
|
echo [1/5] Creating virtual environment...
|
||||||
|
if exist build_venv rmdir /s /q build_venv
|
||||||
|
python -m venv build_venv
|
||||||
|
call build_venv\Scripts\activate.bat
|
||||||
|
|
||||||
|
echo [2/5] Installing dependencies...
|
||||||
|
pip install --upgrade pip -q
|
||||||
|
pip install -r backend\requirements.txt -q
|
||||||
|
pip install pyinstaller -q
|
||||||
|
|
||||||
|
echo [3/5] Downloading yt-dlp...
|
||||||
|
if not exist tools mkdir tools
|
||||||
|
curl -L https://github.com/yt-dlp/yt-dlp/releases/latest/download/yt-dlp.exe -o tools\yt-dlp.exe
|
||||||
|
|
||||||
|
echo [4/5] Building with PyInstaller...
|
||||||
|
cd backend
|
||||||
|
pyinstaller batchtube-windows.spec --clean --noconfirm
|
||||||
|
cd ..
|
||||||
|
|
||||||
|
if not exist backend\dist\BatchTube.exe (echo ERROR: Build failed && pause && exit /b 1)
|
||||||
|
echo Build successful: backend\dist\BatchTube.exe
|
||||||
|
|
||||||
|
echo [5/5] Creating NSIS installer...
|
||||||
|
makensis /VERSION >nul 2>&1
|
||||||
|
if errorlevel 1 (
|
||||||
|
echo NSIS not found - install from https://nsis.sourceforge.io/
|
||||||
|
echo Your EXE is ready at: backend\dist\BatchTube.exe
|
||||||
|
) else (
|
||||||
|
makensis installer.nsi
|
||||||
|
echo.
|
||||||
|
echo SUCCESS: BatchTube-Setup-1.0.0.exe created
|
||||||
|
)
|
||||||
|
pause
|
||||||
11
deploy-web.sh
Executable file
11
deploy-web.sh
Executable file
@@ -0,0 +1,11 @@
|
|||||||
|
#!/bin/bash
|
||||||
|
# BatchTube Landing Page Deploy Script
|
||||||
|
# Run on server: bash deploy-web.sh
|
||||||
|
set -e
|
||||||
|
SRC_DIR="$(dirname "$0")/web"
|
||||||
|
DEST_DIR="/opt/www/batchtube"
|
||||||
|
echo "Deploying BatchTube landing page..."
|
||||||
|
cp "$SRC_DIR/index.html" "$DEST_DIR/index.html"
|
||||||
|
cp "$SRC_DIR/affiliates.html" "$DEST_DIR/affiliates.html"
|
||||||
|
echo "✅ Deploy complete: $DEST_DIR"
|
||||||
|
ls -lh "$DEST_DIR"
|
||||||
61
installer.nsi
Normal file
61
installer.nsi
Normal file
@@ -0,0 +1,61 @@
|
|||||||
|
; BatchTube NSIS Installer Script - Updated for backend/ structure
|
||||||
|
; Requires NSIS 3.x - https://nsis.sourceforge.io/
|
||||||
|
|
||||||
|
!define APP_NAME "BatchTube"
|
||||||
|
!define APP_VERSION "1.0.0"
|
||||||
|
!define APP_PUBLISHER "Intentures LLC"
|
||||||
|
!define APP_URL "https://batchtube.com"
|
||||||
|
!define APP_EXE "BatchTube.exe"
|
||||||
|
!define INSTALL_DIR "$PROGRAMFILES64\BatchTube"
|
||||||
|
|
||||||
|
Name "${APP_NAME} ${APP_VERSION}"
|
||||||
|
OutFile "BatchTube-Setup-${APP_VERSION}.exe"
|
||||||
|
InstallDir "${INSTALL_DIR}"
|
||||||
|
InstallDirRegKey HKLM "Software\${APP_NAME}" "Install_Dir"
|
||||||
|
RequestExecutionLevel admin
|
||||||
|
|
||||||
|
!include "MUI2.nsh"
|
||||||
|
!define MUI_ABORTWARNING
|
||||||
|
!define MUI_ICON "..\src-tauri\icons\icon.ico"
|
||||||
|
!define MUI_UNICON "..\src-tauri\icons\icon.ico"
|
||||||
|
|
||||||
|
!insertmacro MUI_PAGE_WELCOME
|
||||||
|
!insertmacro MUI_PAGE_LICENSE "..\LICENSE.txt"
|
||||||
|
!insertmacro MUI_PAGE_DIRECTORY
|
||||||
|
!insertmacro MUI_PAGE_INSTFILES
|
||||||
|
!define MUI_FINISHPAGE_RUN "$INSTDIR\${APP_EXE}"
|
||||||
|
!define MUI_FINISHPAGE_RUN_TEXT "Launch BatchTube now"
|
||||||
|
!insertmacro MUI_PAGE_FINISH
|
||||||
|
!insertmacro MUI_UNPAGE_CONFIRM
|
||||||
|
!insertmacro MUI_UNPAGE_INSTFILES
|
||||||
|
!insertmacro MUI_LANGUAGE "English"
|
||||||
|
|
||||||
|
Section "BatchTube" SecMain
|
||||||
|
SetOutPath "$INSTDIR"
|
||||||
|
File "backend\dist\BatchTube.exe"
|
||||||
|
; Optional: bundle yt-dlp
|
||||||
|
; File "tools\yt-dlp.exe"
|
||||||
|
; Optional: bundle ffmpeg
|
||||||
|
; File /r "tools\ffmpeg"
|
||||||
|
WriteRegStr HKLM "Software\${APP_NAME}" "Install_Dir" "$INSTDIR"
|
||||||
|
WriteRegStr HKLM "Software\Microsoft\Windows\CurrentVersion\Uninstall\${APP_NAME}" "DisplayName" "${APP_NAME}"
|
||||||
|
WriteRegStr HKLM "Software\Microsoft\Windows\CurrentVersion\Uninstall\${APP_NAME}" "UninstallString" '"$INSTDIR\Uninstall.exe"'
|
||||||
|
WriteRegStr HKLM "Software\Microsoft\Windows\CurrentVersion\Uninstall\${APP_NAME}" "DisplayVersion" "${APP_VERSION}"
|
||||||
|
WriteRegStr HKLM "Software\Microsoft\Windows\CurrentVersion\Uninstall\${APP_NAME}" "Publisher" "${APP_PUBLISHER}"
|
||||||
|
WriteRegStr HKLM "Software\Microsoft\Windows\CurrentVersion\Uninstall\${APP_NAME}" "URLInfoAbout" "${APP_URL}"
|
||||||
|
WriteRegDWORD HKLM "Software\Microsoft\Windows\CurrentVersion\Uninstall\${APP_NAME}" "NoModify" 1
|
||||||
|
WriteRegDWORD HKLM "Software\Microsoft\Windows\CurrentVersion\Uninstall\${APP_NAME}" "NoRepair" 1
|
||||||
|
WriteUninstaller "$INSTDIR\Uninstall.exe"
|
||||||
|
CreateShortcut "$DESKTOP\BatchTube.lnk" "$INSTDIR\${APP_EXE}"
|
||||||
|
CreateDirectory "$SMPROGRAMS\BatchTube"
|
||||||
|
CreateShortcut "$SMPROGRAMS\BatchTube\BatchTube.lnk" "$INSTDIR\${APP_EXE}"
|
||||||
|
CreateShortcut "$SMPROGRAMS\BatchTube\Uninstall BatchTube.lnk" "$INSTDIR\Uninstall.exe"
|
||||||
|
SectionEnd
|
||||||
|
|
||||||
|
Section "Uninstall"
|
||||||
|
RMDir /r "$INSTDIR"
|
||||||
|
Delete "$DESKTOP\BatchTube.lnk"
|
||||||
|
RMDir /r "$SMPROGRAMS\BatchTube"
|
||||||
|
DeleteRegKey HKLM "Software\Microsoft\Windows\CurrentVersion\Uninstall\${APP_NAME}"
|
||||||
|
DeleteRegKey HKLM "Software\${APP_NAME}"
|
||||||
|
SectionEnd
|
||||||
359
web/affiliates.html
Normal file
359
web/affiliates.html
Normal file
@@ -0,0 +1,359 @@
|
|||||||
|
<!DOCTYPE html>
|
||||||
|
<html lang="en">
|
||||||
|
<head>
|
||||||
|
<meta charset="UTF-8" />
|
||||||
|
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
|
||||||
|
<title>BatchTube Affiliate Program — Earn 30% Commission</title>
|
||||||
|
<meta name="description" content="Join the BatchTube affiliate program and earn 30% commission on every sale — monthly, annual, and lifetime plans. Managed via ThriveCart." />
|
||||||
|
<style>
|
||||||
|
:root {
|
||||||
|
--orange: #ff8822;
|
||||||
|
--orange2: #cc5500;
|
||||||
|
--dark: #0f0f0f;
|
||||||
|
--dark2: #1a1a1a;
|
||||||
|
--dark3: #242424;
|
||||||
|
--border: #2e2e2e;
|
||||||
|
--text: #f0f0f0;
|
||||||
|
--text-dim: #aaa;
|
||||||
|
--radius: 10px;
|
||||||
|
}
|
||||||
|
* { box-sizing: border-box; margin: 0; padding: 0; }
|
||||||
|
body { font-family: 'Segoe UI', system-ui, sans-serif; background: var(--dark); color: var(--text); line-height: 1.6; }
|
||||||
|
a { color: var(--orange); text-decoration: none; }
|
||||||
|
a:hover { text-decoration: underline; }
|
||||||
|
|
||||||
|
/* NAV */
|
||||||
|
nav { display: flex; align-items: center; justify-content: space-between; padding: 16px 40px; border-bottom: 1px solid var(--border); position: sticky; top: 0; background: rgba(15,15,15,0.95); backdrop-filter: blur(8px); z-index: 100; }
|
||||||
|
.nav-logo { font-size: 22px; font-weight: 800; color: var(--text); }
|
||||||
|
.nav-logo span { color: var(--orange); }
|
||||||
|
.nav-links { display: flex; gap: 28px; font-size: 14px; }
|
||||||
|
.nav-links a { color: var(--text-dim); transition: color 0.2s; }
|
||||||
|
.nav-links a:hover, .nav-links a.active { color: var(--text); text-decoration: none; }
|
||||||
|
.nav-cta { background: var(--orange); color: #fff; padding: 10px 20px; border-radius: 8px; font-size: 14px; font-weight: 700; transition: background 0.2s; }
|
||||||
|
.nav-cta:hover { background: var(--orange2); text-decoration: none; }
|
||||||
|
|
||||||
|
/* HERO */
|
||||||
|
.aff-hero { text-align: center; padding: 80px 20px 60px; background: linear-gradient(180deg, rgba(255,136,34,0.06) 0%, transparent 100%); }
|
||||||
|
.aff-badge { display: inline-block; background: rgba(255,136,34,0.15); border: 1px solid rgba(255,136,34,0.3); color: var(--orange); font-size: 12px; font-weight: 700; padding: 6px 16px; border-radius: 20px; margin-bottom: 24px; letter-spacing: 1px; text-transform: uppercase; }
|
||||||
|
.aff-hero h1 { font-size: clamp(32px, 5vw, 60px); font-weight: 800; margin-bottom: 20px; line-height: 1.1; }
|
||||||
|
.aff-hero h1 span { color: var(--orange); }
|
||||||
|
.aff-hero p { font-size: 18px; color: var(--text-dim); max-width: 600px; margin: 0 auto 40px; }
|
||||||
|
.btn-primary { display: inline-block; background: var(--orange); color: #fff; padding: 16px 36px; border-radius: 10px; font-size: 16px; font-weight: 700; transition: background 0.2s; }
|
||||||
|
.btn-primary:hover { background: var(--orange2); text-decoration: none; }
|
||||||
|
.btn-outline { display: inline-block; border: 2px solid var(--border); color: var(--text); padding: 14px 32px; border-radius: 10px; font-size: 15px; font-weight: 600; transition: all 0.2s; margin-left: 12px; }
|
||||||
|
.btn-outline:hover { border-color: var(--orange); color: var(--orange); text-decoration: none; }
|
||||||
|
|
||||||
|
/* STATS BAR */
|
||||||
|
.stats-bar { display: flex; justify-content: center; gap: 60px; padding: 40px 20px; border-top: 1px solid var(--border); border-bottom: 1px solid var(--border); background: var(--dark2); flex-wrap: wrap; }
|
||||||
|
.stat-item { text-align: center; }
|
||||||
|
.stat-num { font-size: 36px; font-weight: 800; color: var(--orange); }
|
||||||
|
.stat-label { font-size: 13px; color: var(--text-dim); margin-top: 4px; }
|
||||||
|
|
||||||
|
/* SECTION */
|
||||||
|
.section { max-width: 1100px; margin: 0 auto; padding: 80px 20px; }
|
||||||
|
.section-label { font-size: 12px; font-weight: 700; letter-spacing: 2px; text-transform: uppercase; color: var(--orange); margin-bottom: 12px; }
|
||||||
|
.section-title { font-size: clamp(26px, 3.5vw, 40px); font-weight: 800; margin-bottom: 16px; }
|
||||||
|
.section-sub { font-size: 17px; color: var(--text-dim); max-width: 600px; margin-bottom: 48px; }
|
||||||
|
|
||||||
|
/* HOW IT WORKS */
|
||||||
|
.steps-grid { display: grid; grid-template-columns: repeat(auto-fit, minmax(220px, 1fr)); gap: 24px; }
|
||||||
|
.step-card { background: var(--dark2); border: 1px solid var(--border); border-radius: var(--radius); padding: 28px; }
|
||||||
|
.step-num { width: 40px; height: 40px; background: var(--orange); border-radius: 50%; display: flex; align-items: center; justify-content: center; font-size: 18px; font-weight: 800; margin-bottom: 16px; }
|
||||||
|
.step-title { font-size: 16px; font-weight: 700; margin-bottom: 8px; }
|
||||||
|
.step-desc { font-size: 14px; color: var(--text-dim); line-height: 1.6; }
|
||||||
|
|
||||||
|
/* COMMISSION TABLE */
|
||||||
|
.commission-table { width: 100%; border-collapse: collapse; margin-bottom: 32px; }
|
||||||
|
.commission-table th { background: var(--dark3); padding: 14px 20px; text-align: left; font-size: 13px; font-weight: 700; letter-spacing: 0.5px; text-transform: uppercase; color: var(--text-dim); border-bottom: 1px solid var(--border); }
|
||||||
|
.commission-table td { padding: 16px 20px; border-bottom: 1px solid var(--border); font-size: 15px; }
|
||||||
|
.commission-table tr:hover td { background: rgba(255,136,34,0.03); }
|
||||||
|
.commission-table .earn { color: var(--orange); font-weight: 700; font-size: 16px; }
|
||||||
|
.commission-table .featured-row td { background: rgba(255,136,34,0.05); }
|
||||||
|
|
||||||
|
/* CALCULATOR */
|
||||||
|
.calculator { background: var(--dark2); border: 1px solid var(--orange); border-radius: var(--radius); padding: 40px; max-width: 700px; margin: 0 auto; }
|
||||||
|
.calculator h3 { font-size: 22px; font-weight: 800; margin-bottom: 8px; }
|
||||||
|
.calculator p { color: var(--text-dim); font-size: 14px; margin-bottom: 28px; }
|
||||||
|
.calc-row { display: flex; align-items: center; gap: 16px; margin-bottom: 20px; flex-wrap: wrap; }
|
||||||
|
.calc-label { font-size: 14px; font-weight: 600; min-width: 160px; }
|
||||||
|
.calc-input { background: var(--dark3); border: 1px solid var(--border); color: var(--text); padding: 10px 16px; border-radius: 8px; font-size: 16px; width: 120px; }
|
||||||
|
.calc-input:focus { outline: none; border-color: var(--orange); }
|
||||||
|
select.calc-input { width: 180px; cursor: pointer; }
|
||||||
|
.calc-result { background: linear-gradient(135deg, rgba(255,136,34,0.15), rgba(255,136,34,0.05)); border: 1px solid rgba(255,136,34,0.3); border-radius: var(--radius); padding: 24px 32px; text-align: center; margin-top: 24px; }
|
||||||
|
.calc-result .monthly-earn { font-size: 42px; font-weight: 800; color: var(--orange); }
|
||||||
|
.calc-result .annual-earn { font-size: 20px; color: var(--text-dim); margin-top: 4px; }
|
||||||
|
.calc-result .label { font-size: 13px; color: var(--text-dim); margin-top: 8px; }
|
||||||
|
|
||||||
|
/* PAYOUTS */
|
||||||
|
.payout-grid { display: grid; grid-template-columns: repeat(auto-fit, minmax(200px, 1fr)); gap: 20px; }
|
||||||
|
.payout-card { background: var(--dark2); border: 1px solid var(--border); border-radius: var(--radius); padding: 24px; text-align: center; }
|
||||||
|
.payout-icon { font-size: 32px; margin-bottom: 12px; }
|
||||||
|
.payout-title { font-size: 15px; font-weight: 700; margin-bottom: 6px; }
|
||||||
|
.payout-desc { font-size: 13px; color: var(--text-dim); }
|
||||||
|
|
||||||
|
/* CTA */
|
||||||
|
.aff-cta { text-align: center; padding: 80px 20px; background: linear-gradient(180deg, transparent, rgba(255,136,34,0.06)); }
|
||||||
|
.aff-cta h2 { font-size: clamp(28px, 4vw, 44px); font-weight: 800; margin-bottom: 16px; }
|
||||||
|
.aff-cta p { font-size: 17px; color: var(--text-dim); max-width: 520px; margin: 0 auto 36px; }
|
||||||
|
|
||||||
|
/* FOOTER */
|
||||||
|
footer { text-align: center; padding: 40px 20px; border-top: 1px solid var(--border); color: var(--text-dim); font-size: 14px; }
|
||||||
|
.footer-logo { font-size: 20px; font-weight: 700; color: var(--text); margin-bottom: 12px; }
|
||||||
|
.footer-logo span { color: var(--orange); }
|
||||||
|
|
||||||
|
@media (max-width: 600px) {
|
||||||
|
nav { padding: 14px 20px; }
|
||||||
|
.nav-links { display: none; }
|
||||||
|
.stats-bar { gap: 30px; }
|
||||||
|
.calc-row { flex-direction: column; align-items: flex-start; }
|
||||||
|
}
|
||||||
|
</style>
|
||||||
|
</head>
|
||||||
|
<body>
|
||||||
|
|
||||||
|
<!-- NAV -->
|
||||||
|
<nav>
|
||||||
|
<div class="nav-logo">Batch<span>Tube</span></div>
|
||||||
|
<div class="nav-links">
|
||||||
|
<a href="/#features">Features</a>
|
||||||
|
<a href="/#pricing">Pricing</a>
|
||||||
|
<a href="/affiliates.html" class="active">Affiliates</a>
|
||||||
|
<a href="/#faq">FAQ</a>
|
||||||
|
</div>
|
||||||
|
<a href="https://qmg.thrivecart.com/affiliate/request-access/batchtube/" class="nav-cta" target="_blank">Join Now →</a>
|
||||||
|
</nav>
|
||||||
|
|
||||||
|
<!-- HERO -->
|
||||||
|
<div class="aff-hero">
|
||||||
|
<div class="aff-badge">💰 Affiliate Program</div>
|
||||||
|
<h1>Earn <span>30% Commission</span><br>On Every BatchTube Sale</h1>
|
||||||
|
<p>Monthly subscriptions. Annual plans. Lifetime deals. You refer once — we pay you every renewal. No cap. No expiry.</p>
|
||||||
|
<a href="https://qmg.thrivecart.com/affiliate/request-access/batchtube/" class="btn-primary" target="_blank">Apply to Become an Affiliate →</a>
|
||||||
|
<a href="#calculator" class="btn-outline">Calculate Your Earnings</a>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<!-- STATS BAR -->
|
||||||
|
<div class="stats-bar">
|
||||||
|
<div class="stat-item">
|
||||||
|
<div class="stat-num">30%</div>
|
||||||
|
<div class="stat-label">Commission Rate</div>
|
||||||
|
</div>
|
||||||
|
<div class="stat-item">
|
||||||
|
<div class="stat-num">$59</div>
|
||||||
|
<div class="stat-label">Max Per Lifetime Sale</div>
|
||||||
|
</div>
|
||||||
|
<div class="stat-item">
|
||||||
|
<div class="stat-num">30 days</div>
|
||||||
|
<div class="stat-label">Cookie Duration</div>
|
||||||
|
</div>
|
||||||
|
<div class="stat-item">
|
||||||
|
<div class="stat-num">Instant</div>
|
||||||
|
<div class="stat-label">ThriveCart Tracking</div>
|
||||||
|
</div>
|
||||||
|
<div class="stat-item">
|
||||||
|
<div class="stat-num">Monthly</div>
|
||||||
|
<div class="stat-label">Payout Schedule</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<!-- HOW IT WORKS -->
|
||||||
|
<section class="section">
|
||||||
|
<div class="section-label">How It Works</div>
|
||||||
|
<h2 class="section-title">Simple. Transparent. Profitable.</h2>
|
||||||
|
<p class="section-sub">Four steps from signup to your first commission check.</p>
|
||||||
|
<div class="steps-grid">
|
||||||
|
<div class="step-card">
|
||||||
|
<div class="step-num">1</div>
|
||||||
|
<div class="step-title">Apply</div>
|
||||||
|
<div class="step-desc">Submit your affiliate application via ThriveCart. Approval is fast — usually within 24 hours.</div>
|
||||||
|
</div>
|
||||||
|
<div class="step-card">
|
||||||
|
<div class="step-num">2</div>
|
||||||
|
<div class="step-title">Get Your Link</div>
|
||||||
|
<div class="step-desc">Receive your unique tracking link. Share it on YouTube, blogs, newsletters, social media — anywhere your audience lives.</div>
|
||||||
|
</div>
|
||||||
|
<div class="step-card">
|
||||||
|
<div class="step-num">3</div>
|
||||||
|
<div class="step-title">Refer & Earn</div>
|
||||||
|
<div class="step-desc">Every time someone buys through your link, you earn 30% commission. Monthly plans pay every renewal cycle.</div>
|
||||||
|
</div>
|
||||||
|
<div class="step-card">
|
||||||
|
<div class="step-num">4</div>
|
||||||
|
<div class="step-title">Get Paid</div>
|
||||||
|
<div class="step-desc">Commissions paid monthly via PayPal or bank transfer through ThriveCart's affiliate payout system.</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</section>
|
||||||
|
|
||||||
|
<!-- COMMISSION TABLE -->
|
||||||
|
<section class="section" style="padding-top:0;">
|
||||||
|
<div class="section-label">Commission Breakdown</div>
|
||||||
|
<h2 class="section-title">What You Earn Per Sale</h2>
|
||||||
|
<p class="section-sub">30% on every plan — monthly, annual, and lifetime.</p>
|
||||||
|
<table class="commission-table">
|
||||||
|
<thead>
|
||||||
|
<tr>
|
||||||
|
<th>Plan</th>
|
||||||
|
<th>Price</th>
|
||||||
|
<th>Your Commission</th>
|
||||||
|
<th>Annual Earnings (10 sales/mo)</th>
|
||||||
|
</tr>
|
||||||
|
</thead>
|
||||||
|
<tbody>
|
||||||
|
<tr>
|
||||||
|
<td><strong>Creator Monthly</strong></td>
|
||||||
|
<td>$19/mo</td>
|
||||||
|
<td class="earn">$5.70/mo per customer</td>
|
||||||
|
<td>$684/yr</td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td><strong>Creator Annual</strong></td>
|
||||||
|
<td>$190/yr</td>
|
||||||
|
<td class="earn">$57 per sale</td>
|
||||||
|
<td>$570/yr</td>
|
||||||
|
</tr>
|
||||||
|
<tr class="featured-row">
|
||||||
|
<td><strong>Pro Monthly</strong></td>
|
||||||
|
<td>$39/mo</td>
|
||||||
|
<td class="earn">$11.70/mo per customer</td>
|
||||||
|
<td>$1,404/yr</td>
|
||||||
|
</tr>
|
||||||
|
<tr class="featured-row">
|
||||||
|
<td><strong>Pro Annual</strong></td>
|
||||||
|
<td>$790/yr</td>
|
||||||
|
<td class="earn">$237 per sale</td>
|
||||||
|
<td>$2,370/yr</td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td><strong>Studio Monthly</strong></td>
|
||||||
|
<td>$79/mo</td>
|
||||||
|
<td class="earn">$23.70/mo per customer</td>
|
||||||
|
<td>$2,844/yr</td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td><strong>Studio Annual</strong></td>
|
||||||
|
<td>$790/yr</td>
|
||||||
|
<td class="earn">$237 per sale</td>
|
||||||
|
<td>$2,370/yr</td>
|
||||||
|
</tr>
|
||||||
|
<tr style="border-top: 2px solid var(--orange);">
|
||||||
|
<td><strong>🔥 Lifetime</strong></td>
|
||||||
|
<td>$197 – $247</td>
|
||||||
|
<td class="earn">$59.10 – $74.10 once</td>
|
||||||
|
<td>$591 – $741 (10 sales)</td>
|
||||||
|
</tr>
|
||||||
|
</tbody>
|
||||||
|
</table>
|
||||||
|
<p style="font-size:13px; color:var(--text-dim);">* Monthly plan commissions recur every billing cycle as long as the customer remains subscribed.</p>
|
||||||
|
</section>
|
||||||
|
|
||||||
|
<!-- CALCULATOR -->
|
||||||
|
<section class="section" id="calculator" style="padding-top:0;">
|
||||||
|
<div class="section-label">Earnings Calculator</div>
|
||||||
|
<h2 class="section-title">How Much Can You Make?</h2>
|
||||||
|
<p class="section-sub">Plug in your numbers. See your potential.</p>
|
||||||
|
<div class="calculator">
|
||||||
|
<h3>🧮 Commission Calculator</h3>
|
||||||
|
<p>Estimate your monthly and annual affiliate earnings</p>
|
||||||
|
<div class="calc-row">
|
||||||
|
<span class="calc-label">Plan type:</span>
|
||||||
|
<select class="calc-input" id="calc-plan" onchange="calcEarnings()">
|
||||||
|
<option value="19">Creator Monthly ($19/mo)</option>
|
||||||
|
<option value="190" data-type="annual">Creator Annual ($190)</option>
|
||||||
|
<option value="39" selected>Pro Monthly ($39/mo)</option>
|
||||||
|
<option value="790" data-type="annual">Pro Annual ($790)</option>
|
||||||
|
<option value="79">Studio Monthly ($79/mo)</option>
|
||||||
|
<option value="790" data-type="annual">Studio Annual ($790)</option>
|
||||||
|
<option value="197" data-type="lifetime">Lifetime ($197)</option>
|
||||||
|
</select>
|
||||||
|
</div>
|
||||||
|
<div class="calc-row">
|
||||||
|
<span class="calc-label">Referrals per month:</span>
|
||||||
|
<input type="number" class="calc-input" id="calc-refs" value="10" min="1" max="10000" oninput="calcEarnings()" />
|
||||||
|
</div>
|
||||||
|
<div class="calc-result" id="calc-result">
|
||||||
|
<div class="monthly-earn" id="monthly-earn">$117.00</div>
|
||||||
|
<div class="annual-earn" id="annual-earn">$1,404.00 / year</div>
|
||||||
|
<div class="label">Estimated affiliate earnings at 30% commission</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</section>
|
||||||
|
|
||||||
|
<!-- PAYOUT INFO -->
|
||||||
|
<section class="section" style="padding-top:0;">
|
||||||
|
<div class="section-label">Payouts</div>
|
||||||
|
<h2 class="section-title">Getting Paid Is Easy</h2>
|
||||||
|
<p class="section-sub">ThriveCart handles all tracking, attribution, and payouts automatically.</p>
|
||||||
|
<div class="payout-grid">
|
||||||
|
<div class="payout-card">
|
||||||
|
<div class="payout-icon">📅</div>
|
||||||
|
<div class="payout-title">Monthly Payouts</div>
|
||||||
|
<div class="payout-desc">Commissions paid out monthly. No waiting 90 days.</div>
|
||||||
|
</div>
|
||||||
|
<div class="payout-card">
|
||||||
|
<div class="payout-icon">🔗</div>
|
||||||
|
<div class="payout-title">30-Day Cookie</div>
|
||||||
|
<div class="payout-desc">Visitors tracked for 30 days after clicking your link.</div>
|
||||||
|
</div>
|
||||||
|
<div class="payout-card">
|
||||||
|
<div class="payout-icon">📊</div>
|
||||||
|
<div class="payout-title">Real-Time Dashboard</div>
|
||||||
|
<div class="payout-desc">Track clicks, conversions, and earnings live in ThriveCart.</div>
|
||||||
|
</div>
|
||||||
|
<div class="payout-card">
|
||||||
|
<div class="payout-icon">💰</div>
|
||||||
|
<div class="payout-title">Recurring Revenue</div>
|
||||||
|
<div class="payout-desc">Monthly subscribers pay you every single month they stay.</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</section>
|
||||||
|
|
||||||
|
<!-- CTA -->
|
||||||
|
<div class="aff-cta">
|
||||||
|
<h2>Ready to Start Earning?</h2>
|
||||||
|
<p>Join the BatchTube affiliate program today. Free to join. No approval wait. Start earning 30% on day one.</p>
|
||||||
|
<a href="https://qmg.thrivecart.com/affiliate/request-access/batchtube/" class="btn-primary" target="_blank">Apply Now — It's Free →</a>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<!-- FOOTER -->
|
||||||
|
<footer>
|
||||||
|
<div class="footer-logo">Batch<span>Tube</span></div>
|
||||||
|
<p style="margin-bottom:12px;">Built by <a href="https://intentures.org">Intentures LLC</a> • <a href="https://mautic.intentures.org/form/1" target="_blank" rel="noopener">Contact Us</a></p>
|
||||||
|
<p>© 2026 Intentures LLC. All rights reserved.</p>
|
||||||
|
</footer>
|
||||||
|
|
||||||
|
<script>
|
||||||
|
function calcEarnings() {
|
||||||
|
const planSelect = document.getElementById('calc-plan');
|
||||||
|
const refs = parseInt(document.getElementById('calc-refs').value) || 0;
|
||||||
|
const price = parseFloat(planSelect.value);
|
||||||
|
const selectedOption = planSelect.options[planSelect.selectedIndex];
|
||||||
|
const type = selectedOption.getAttribute('data-type') || 'monthly';
|
||||||
|
const commission = price * 0.30;
|
||||||
|
|
||||||
|
let monthlyEarn, annualEarn;
|
||||||
|
|
||||||
|
if (type === 'lifetime') {
|
||||||
|
monthlyEarn = commission * refs;
|
||||||
|
annualEarn = monthlyEarn; // one-time
|
||||||
|
document.getElementById('annual-earn').textContent = 'One-time commissions';
|
||||||
|
} else if (type === 'annual') {
|
||||||
|
monthlyEarn = commission * refs;
|
||||||
|
annualEarn = monthlyEarn; // annual sales per month
|
||||||
|
document.getElementById('annual-earn').textContent = '$' + (annualEarn * 12).toLocaleString('en-US', {minimumFractionDigits:2, maximumFractionDigits:2}) + ' / year';
|
||||||
|
} else {
|
||||||
|
// monthly recurring
|
||||||
|
monthlyEarn = commission * refs;
|
||||||
|
annualEarn = monthlyEarn * 12;
|
||||||
|
document.getElementById('annual-earn').textContent = '$' + annualEarn.toLocaleString('en-US', {minimumFractionDigits:2, maximumFractionDigits:2}) + ' / year';
|
||||||
|
}
|
||||||
|
|
||||||
|
document.getElementById('monthly-earn').textContent = '$' + monthlyEarn.toLocaleString('en-US', {minimumFractionDigits:2, maximumFractionDigits:2});
|
||||||
|
}
|
||||||
|
|
||||||
|
// Init
|
||||||
|
calcEarnings();
|
||||||
|
</script>
|
||||||
|
|
||||||
|
</body>
|
||||||
|
</html>
|
||||||
561
web/index.html
Normal file
561
web/index.html
Normal file
@@ -0,0 +1,561 @@
|
|||||||
|
<!DOCTYPE html>
|
||||||
|
<html lang="en">
|
||||||
|
<head>
|
||||||
|
<meta charset="UTF-8" />
|
||||||
|
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
|
||||||
|
|
||||||
|
<!-- SEO -->
|
||||||
|
<title>BatchTube — Bulk YouTube Downloader | Transcripts, MP3s & AI Summaries</title>
|
||||||
|
<meta name="description" content="BatchTube batch downloads entire YouTube playlists, channels, and bulk URL lists — with transcripts, MP3 extraction, and AI summaries. Runs locally on Windows, Mac, and Linux. No cloud. No data leaks." />
|
||||||
|
<meta name="keywords" content="batch download YouTube, YouTube bulk downloader, YouTube playlist downloader, YouTube transcript extractor, YouTube MP3 extractor, bulk YouTube downloader, YouTube channel downloader" />
|
||||||
|
|
||||||
|
<!-- GEO -->
|
||||||
|
<meta name="geo.region" content="US" />
|
||||||
|
<meta name="geo.placename" content="United States" />
|
||||||
|
<link rel="alternate" hreflang="en-us" href="https://batchtube.com/" />
|
||||||
|
<link rel="alternate" hreflang="en-gb" href="https://batchtube.com/" />
|
||||||
|
<link rel="alternate" hreflang="en-ca" href="https://batchtube.com/" />
|
||||||
|
<link rel="alternate" hreflang="en-au" href="https://batchtube.com/" />
|
||||||
|
<link rel="alternate" hreflang="x-default" href="https://batchtube.com/" />
|
||||||
|
|
||||||
|
<!-- Open Graph -->
|
||||||
|
<meta property="og:title" content="BatchTube — Bulk YouTube Downloader" />
|
||||||
|
<meta property="og:description" content="Stop downloading one video at a time. BatchTube processes entire playlists, channels, and bulk URL lists with transcripts, MP3s, and AI summaries built in." />
|
||||||
|
<meta property="og:url" content="https://batchtube.com" />
|
||||||
|
<meta property="og:type" content="website" />
|
||||||
|
<meta property="og:image" content="https://batchtube.com/og-image.png" />
|
||||||
|
|
||||||
|
<!-- Twitter Card -->
|
||||||
|
<meta name="twitter:card" content="summary_large_image" />
|
||||||
|
<meta name="twitter:title" content="BatchTube — Bulk YouTube Downloader" />
|
||||||
|
<meta name="twitter:description" content="Batch download YouTube videos, playlists, transcripts, MP3s and AI summaries. Runs locally. No cloud." />
|
||||||
|
|
||||||
|
<!-- Schema.org -->
|
||||||
|
<script type="application/ld+json">
|
||||||
|
{
|
||||||
|
"@context": "https://schema.org",
|
||||||
|
"@type": "SoftwareApplication",
|
||||||
|
"name": "BatchTube",
|
||||||
|
"applicationCategory": "UtilitiesApplication",
|
||||||
|
"operatingSystem": "Windows, macOS, Linux",
|
||||||
|
"offers": [
|
||||||
|
{"@type": "Offer", "name": "Free", "price": "0", "priceCurrency": "USD"},
|
||||||
|
{"@type": "Offer", "name": "Creator", "price": "19", "priceCurrency": "USD"},
|
||||||
|
{"@type": "Offer", "name": "Pro", "price": "39", "priceCurrency": "USD"},
|
||||||
|
{"@type": "Offer", "name": "Studio", "price": "79", "priceCurrency": "USD"},
|
||||||
|
{"@type": "Offer", "name": "Lifetime", "price": "197", "priceCurrency": "USD"}
|
||||||
|
],
|
||||||
|
"description": "BatchTube batch downloads entire YouTube playlists, channels, and bulk URL lists with transcripts, MP3 extraction, and AI summaries.",
|
||||||
|
"url": "https://batchtube.com"
|
||||||
|
}
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<style>
|
||||||
|
:root {
|
||||||
|
--orange: #ff8822;
|
||||||
|
--orange2: #cc5500;
|
||||||
|
--dark: #0f0f0f;
|
||||||
|
--dark2: #1a1a1a;
|
||||||
|
--dark3: #242424;
|
||||||
|
--border: #2e2e2e;
|
||||||
|
--text: #f0f0f0;
|
||||||
|
--text-dim: #aaa;
|
||||||
|
--radius: 10px;
|
||||||
|
}
|
||||||
|
* { box-sizing: border-box; margin: 0; padding: 0; }
|
||||||
|
body { font-family: 'Segoe UI', system-ui, sans-serif; background: var(--dark); color: var(--text); line-height: 1.6; }
|
||||||
|
a { color: var(--orange); text-decoration: none; }
|
||||||
|
a:hover { text-decoration: underline; }
|
||||||
|
|
||||||
|
/* NAV */
|
||||||
|
nav { display: flex; align-items: center; justify-content: space-between; padding: 18px 40px; border-bottom: 1px solid var(--border); position: sticky; top: 0; background: rgba(15,15,15,0.95); backdrop-filter: blur(10px); z-index: 100; }
|
||||||
|
.nav-logo { display: flex; align-items: center; gap: 10px; font-size: 22px; font-weight: 700; color: var(--text); }
|
||||||
|
.nav-logo span { color: var(--orange); }
|
||||||
|
.nav-links { display: flex; gap: 28px; font-size: 14px; color: var(--text-dim); }
|
||||||
|
.nav-links a { color: var(--text-dim); }
|
||||||
|
.nav-links a:hover { color: var(--orange); text-decoration: none; }
|
||||||
|
.nav-cta { background: var(--orange); color: #fff; padding: 9px 22px; border-radius: 6px; font-weight: 600; font-size: 14px; }
|
||||||
|
.nav-cta:hover { background: var(--orange2); text-decoration: none; }
|
||||||
|
|
||||||
|
/* HERO */
|
||||||
|
.hero { text-align: center; padding: 100px 20px 80px; max-width: 860px; margin: 0 auto; }
|
||||||
|
.hero-badge { display: inline-block; background: rgba(255,136,34,0.15); color: var(--orange); border: 1px solid rgba(255,136,34,0.3); padding: 6px 16px; border-radius: 20px; font-size: 13px; font-weight: 600; margin-bottom: 28px; letter-spacing: 0.5px; }
|
||||||
|
.hero h1 { font-size: clamp(36px, 6vw, 64px); font-weight: 800; line-height: 1.1; margin-bottom: 24px; }
|
||||||
|
.hero h1 span { color: var(--orange); }
|
||||||
|
.hero p { font-size: 20px; color: var(--text-dim); max-width: 640px; margin: 0 auto 40px; }
|
||||||
|
.hero-btns { display: flex; gap: 16px; justify-content: center; flex-wrap: wrap; }
|
||||||
|
.btn-primary { background: var(--orange); color: #fff; padding: 16px 36px; border-radius: 8px; font-size: 17px; font-weight: 700; display: inline-block; transition: background 0.2s; }
|
||||||
|
.btn-primary:hover { background: var(--orange2); text-decoration: none; }
|
||||||
|
.btn-secondary { background: var(--dark3); color: var(--text); padding: 16px 36px; border-radius: 8px; font-size: 17px; font-weight: 600; border: 1px solid var(--border); display: inline-block; }
|
||||||
|
.btn-secondary:hover { border-color: var(--orange); color: var(--orange); text-decoration: none; }
|
||||||
|
.hero-sub { margin-top: 20px; font-size: 13px; color: var(--text-dim); }
|
||||||
|
.hero-stats { display: flex; gap: 40px; justify-content: center; margin-top: 48px; flex-wrap: wrap; }
|
||||||
|
.hero-stat { text-align: center; }
|
||||||
|
.hero-stat-num { font-size: 32px; font-weight: 800; color: var(--orange); }
|
||||||
|
.hero-stat-label { font-size: 13px; color: var(--text-dim); margin-top: 4px; }
|
||||||
|
|
||||||
|
/* DEMO */
|
||||||
|
.demo { max-width: 1000px; margin: 0 auto 80px; padding: 0 20px; }
|
||||||
|
.demo-window { background: var(--dark2); border: 1px solid var(--border); border-radius: 12px; overflow: hidden; box-shadow: 0 20px 60px rgba(0,0,0,0.6); }
|
||||||
|
.demo-bar { background: var(--dark3); padding: 12px 16px; display: flex; align-items: center; gap: 8px; border-bottom: 1px solid var(--border); }
|
||||||
|
.demo-dot { width: 12px; height: 12px; border-radius: 50%; }
|
||||||
|
.demo-dot.red { background: #ff5f57; }
|
||||||
|
.demo-dot.yellow { background: #febc2e; }
|
||||||
|
.demo-dot.green { background: #28c840; }
|
||||||
|
.demo-title { flex: 1; text-align: center; font-size: 13px; color: var(--text-dim); }
|
||||||
|
.demo-body { padding: 32px; }
|
||||||
|
.demo-stats { display: grid; grid-template-columns: repeat(4, 1fr); gap: 16px; margin-bottom: 24px; }
|
||||||
|
.demo-stat-box { background: var(--dark3); border: 1px solid var(--border); border-radius: 8px; padding: 16px; text-align: center; }
|
||||||
|
.demo-stat-num { font-size: 28px; font-weight: 800; color: var(--orange); }
|
||||||
|
.demo-stat-label { font-size: 12px; color: var(--text-dim); margin-top: 4px; }
|
||||||
|
.demo-progress { background: var(--dark3); border: 1px solid var(--border); border-radius: 8px; padding: 16px; }
|
||||||
|
.demo-progress-label { font-size: 13px; color: var(--text-dim); margin-bottom: 10px; }
|
||||||
|
.demo-bar-track { background: var(--border); border-radius: 4px; height: 8px; overflow: hidden; }
|
||||||
|
.demo-bar-fill { background: linear-gradient(90deg, var(--orange), #ffaa44); height: 100%; border-radius: 4px; width: 73%; }
|
||||||
|
.demo-items { margin-top: 16px; display: flex; flex-direction: column; gap: 8px; }
|
||||||
|
.demo-item { display: flex; align-items: center; gap: 12px; font-size: 13px; color: var(--text-dim); }
|
||||||
|
.demo-item-dot { width: 8px; height: 8px; border-radius: 50%; background: var(--orange); flex-shrink: 0; }
|
||||||
|
.demo-item-dot.done { background: #22cc66; }
|
||||||
|
.demo-item-dot.active { background: var(--orange); animation: pulse 1s infinite; }
|
||||||
|
@keyframes pulse { 0%,100% { opacity: 1; } 50% { opacity: 0.4; } }
|
||||||
|
|
||||||
|
/* SECTIONS */
|
||||||
|
.section { max-width: 1100px; margin: 0 auto 80px; padding: 0 20px; }
|
||||||
|
.section-label { font-size: 13px; font-weight: 600; color: var(--orange); letter-spacing: 1px; text-transform: uppercase; margin-bottom: 12px; }
|
||||||
|
.section-title { font-size: clamp(28px, 4vw, 42px); font-weight: 800; margin-bottom: 16px; }
|
||||||
|
.section-sub { font-size: 18px; color: var(--text-dim); max-width: 600px; margin-bottom: 48px; }
|
||||||
|
|
||||||
|
/* FEATURES */
|
||||||
|
.features-grid { display: grid; grid-template-columns: repeat(auto-fit, minmax(300px, 1fr)); gap: 24px; }
|
||||||
|
.feature-card { background: var(--dark2); border: 1px solid var(--border); border-radius: var(--radius); padding: 28px; transition: border-color 0.2s; }
|
||||||
|
.feature-card:hover { border-color: var(--orange); }
|
||||||
|
.feature-icon { font-size: 28px; margin-bottom: 16px; }
|
||||||
|
.feature-title { font-size: 18px; font-weight: 700; margin-bottom: 8px; }
|
||||||
|
.feature-desc { font-size: 14px; color: var(--text-dim); line-height: 1.6; }
|
||||||
|
|
||||||
|
/* HOW IT WORKS */
|
||||||
|
.steps { display: grid; grid-template-columns: repeat(auto-fit, minmax(220px, 1fr)); gap: 32px; }
|
||||||
|
.step { text-align: center; }
|
||||||
|
.step-num { width: 48px; height: 48px; border-radius: 50%; background: rgba(255,136,34,0.15); border: 2px solid var(--orange); color: var(--orange); font-size: 20px; font-weight: 800; display: flex; align-items: center; justify-content: center; margin: 0 auto 16px; }
|
||||||
|
.step-title { font-size: 16px; font-weight: 700; margin-bottom: 8px; }
|
||||||
|
.step-desc { font-size: 14px; color: var(--text-dim); }
|
||||||
|
|
||||||
|
/* MID-PAGE CTA */
|
||||||
|
.mid-cta { background: linear-gradient(135deg, rgba(255,136,34,0.1), rgba(255,136,34,0.05)); border: 1px solid rgba(255,136,34,0.2); border-radius: 16px; padding: 60px 40px; text-align: center; max-width: 800px; margin: 0 auto 80px; }
|
||||||
|
.mid-cta h2 { font-size: clamp(24px, 4vw, 36px); font-weight: 800; margin-bottom: 16px; }
|
||||||
|
.mid-cta p { font-size: 18px; color: var(--text-dim); margin-bottom: 32px; max-width: 560px; margin-left: auto; margin-right: auto; }
|
||||||
|
|
||||||
|
/* TESTIMONIALS */
|
||||||
|
.testimonials-grid { display: grid; grid-template-columns: repeat(auto-fit, minmax(300px, 1fr)); gap: 24px; }
|
||||||
|
.testimonial { background: var(--dark2); border: 1px solid var(--border); border-radius: var(--radius); padding: 28px; }
|
||||||
|
.testimonial-stars { color: var(--orange); font-size: 18px; margin-bottom: 16px; }
|
||||||
|
.testimonial-text { font-size: 15px; color: var(--text-dim); line-height: 1.7; margin-bottom: 20px; font-style: italic; }
|
||||||
|
.testimonial-author { display: flex; align-items: center; gap: 12px; }
|
||||||
|
.testimonial-avatar { width: 40px; height: 40px; border-radius: 50%; background: var(--orange); display: flex; align-items: center; justify-content: center; font-weight: 700; font-size: 16px; color: #fff; flex-shrink: 0; }
|
||||||
|
.testimonial-name { font-weight: 700; font-size: 14px; }
|
||||||
|
.testimonial-role { font-size: 12px; color: var(--text-dim); }
|
||||||
|
|
||||||
|
/* PRICING */
|
||||||
|
.pricing-grid { display: grid; grid-template-columns: repeat(auto-fit, minmax(240px, 1fr)); gap: 24px; align-items: start; }
|
||||||
|
.pricing-card { background: var(--dark2); border: 1px solid var(--border); border-radius: var(--radius); padding: 32px; position: relative; }
|
||||||
|
.pricing-card.featured { border-color: var(--orange); background: rgba(255,136,34,0.04); }
|
||||||
|
.pricing-badge { display: inline-block; background: var(--orange); color: #fff; font-size: 11px; font-weight: 700; padding: 4px 10px; border-radius: 4px; margin-bottom: 16px; letter-spacing: 0.5px; text-transform: uppercase; }
|
||||||
|
.pricing-name { font-size: 20px; font-weight: 700; margin-bottom: 8px; }
|
||||||
|
.pricing-price { font-size: 42px; font-weight: 800; margin-bottom: 4px; }
|
||||||
|
.pricing-price span { font-size: 16px; font-weight: 400; color: var(--text-dim); }
|
||||||
|
.pricing-desc { font-size: 14px; color: var(--text-dim); margin-bottom: 24px; }
|
||||||
|
.pricing-features { list-style: none; margin-bottom: 28px; display: flex; flex-direction: column; gap: 10px; }
|
||||||
|
.pricing-features li { font-size: 14px; display: flex; align-items: center; gap: 8px; }
|
||||||
|
.pricing-features li::before { content: "✓"; color: var(--orange); font-weight: 700; flex-shrink: 0; }
|
||||||
|
.pricing-features li.dim { color: var(--text-dim); }
|
||||||
|
.pricing-features li.dim::before { content: "–"; color: var(--border); }
|
||||||
|
.btn-plan { display: block; text-align: center; padding: 14px 24px; border-radius: 8px; font-size: 15px; font-weight: 700; transition: all 0.2s; }
|
||||||
|
.btn-plan.primary { background: var(--orange); color: #fff; }
|
||||||
|
.btn-plan.primary:hover { background: var(--orange2); text-decoration: none; }
|
||||||
|
.btn-plan.outline { border: 2px solid var(--border); color: var(--text); }
|
||||||
|
.btn-plan.outline:hover { border-color: var(--orange); color: var(--orange); text-decoration: none; }
|
||||||
|
.pricing-guarantee { text-align: center; margin-top: 32px; font-size: 13px; color: var(--text-dim); }
|
||||||
|
|
||||||
|
/* FAQ */
|
||||||
|
.faq { max-width: 760px; margin: 0 auto; }
|
||||||
|
.faq-item { border-bottom: 1px solid var(--border); padding: 24px 0; }
|
||||||
|
.faq-q { font-size: 17px; font-weight: 700; margin-bottom: 12px; }
|
||||||
|
.faq-a { font-size: 15px; color: var(--text-dim); line-height: 1.7; }
|
||||||
|
|
||||||
|
/* BOTTOM CTA */
|
||||||
|
.bottom-cta { text-align: center; padding: 80px 20px; background: linear-gradient(180deg, transparent, rgba(255,136,34,0.05)); }
|
||||||
|
.bottom-cta h2 { font-size: clamp(28px, 4vw, 44px); font-weight: 800; margin-bottom: 16px; }
|
||||||
|
.bottom-cta p { font-size: 18px; color: var(--text-dim); margin-bottom: 40px; max-width: 560px; margin-left: auto; margin-right: auto; }
|
||||||
|
|
||||||
|
/* FOOTER */
|
||||||
|
footer { text-align: center; padding: 40px 20px; border-top: 1px solid var(--border); color: var(--text-dim); font-size: 14px; }
|
||||||
|
.footer-logo { font-size: 20px; font-weight: 700; color: var(--text); margin-bottom: 12px; }
|
||||||
|
.footer-logo span { color: var(--orange); }
|
||||||
|
|
||||||
|
@media (max-width: 600px) {
|
||||||
|
nav { padding: 14px 20px; }
|
||||||
|
.nav-links { display: none; }
|
||||||
|
.demo-stats { grid-template-columns: repeat(2, 1fr); }
|
||||||
|
.hero-stats { gap: 24px; }
|
||||||
|
}
|
||||||
|
|
||||||
|
.pricing-annual { font-size: 13px; color: var(--text-dim); margin-top: -2px; margin-bottom: 20px; }
|
||||||
|
.pricing-annual strong { color: var(--orange); }
|
||||||
|
.scarcity-box { background: rgba(255,60,0,0.1); border: 1px solid rgba(255,60,0,0.35); border-radius: 8px; padding: 12px 16px; margin-bottom: 18px; font-size: 13px; line-height: 1.5; }
|
||||||
|
.scarcity-box strong { color: #ff4422; display: block; font-size: 14px; margin-bottom: 4px; }
|
||||||
|
</style>
|
||||||
|
</head>
|
||||||
|
<body>
|
||||||
|
|
||||||
|
<!-- NAV -->
|
||||||
|
<nav>
|
||||||
|
<div class="nav-logo">Batch<span>Tube</span></div>
|
||||||
|
<div class="nav-links">
|
||||||
|
<a href="#features">Features</a>
|
||||||
|
<a href="#how-it-works">How It Works</a>
|
||||||
|
<a href="#pricing">Pricing</a>
|
||||||
|
<a href="#walkthrough">Demo</a>
|
||||||
|
<a href="#faq">FAQ</a>
|
||||||
|
<a href="/affiliates.html">Affiliates</a>
|
||||||
|
</div>
|
||||||
|
<a href="#pricing" class="nav-cta">Get BatchTube Free</a>
|
||||||
|
</nav>
|
||||||
|
|
||||||
|
<!-- HERO -->
|
||||||
|
<section class="hero">
|
||||||
|
<div class="hero-badge">DESKTOP APP • WINDOWS • MAC • LINUX</div>
|
||||||
|
<h1>Stop Downloading YouTube Videos<br><span>One at a Time.</span></h1>
|
||||||
|
<p>BatchTube processes entire playlists, channels, and bulk URL lists — with transcripts, MP3 extraction, and AI summaries built in. Runs locally. No cloud. No data leaks.</p>
|
||||||
|
<div class="hero-btns">
|
||||||
|
<a href="#pricing" class="btn-primary">Download BatchTube Free →</a>
|
||||||
|
<a href="#features" class="btn-secondary">See Features</a>
|
||||||
|
</div>
|
||||||
|
<p class="hero-sub">Free forever • No account required • Start in 60 seconds</p>
|
||||||
|
<div class="hero-stats">
|
||||||
|
<div class="hero-stat"><div class="hero-stat-num">500+</div><div class="hero-stat-label">Videos per batch</div></div>
|
||||||
|
<div class="hero-stat"><div class="hero-stat-num">6</div><div class="hero-stat-label">Output formats</div></div>
|
||||||
|
<div class="hero-stat"><div class="hero-stat-num">3</div><div class="hero-stat-label">Platforms supported</div></div>
|
||||||
|
<div class="hero-stat"><div class="hero-stat-num">0</div><div class="hero-stat-label">Cloud dependencies</div></div>
|
||||||
|
</div>
|
||||||
|
</section>
|
||||||
|
|
||||||
|
<!-- DEMO WINDOW -->
|
||||||
|
<div class="demo">
|
||||||
|
<div class="demo-window">
|
||||||
|
<div class="demo-bar">
|
||||||
|
<div class="demo-dot red"></div>
|
||||||
|
<div class="demo-dot yellow"></div>
|
||||||
|
<div class="demo-dot green"></div>
|
||||||
|
<div class="demo-title">BatchTube — localhost:8000</div>
|
||||||
|
</div>
|
||||||
|
<div class="demo-body" style="padding: 0; overflow: hidden;">
|
||||||
|
<img src="/batchtube-demo.gif" alt="BatchTube app walkthrough — batch download, queue management, settings" style="width:100%; display:block; border-radius: 0 0 12px 12px;" loading="lazy" />
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<!-- FEATURES -->
|
||||||
|
<section class="section" id="features">
|
||||||
|
<div class="section-label">Features</div>
|
||||||
|
<h2 class="section-title">Everything your YouTube workflow needs.</h2>
|
||||||
|
<p class="section-sub">Six tools in one. All running locally on your machine.</p>
|
||||||
|
<div class="features-grid">
|
||||||
|
<div class="feature-card">
|
||||||
|
<div class="feature-icon">⚡</div>
|
||||||
|
<div class="feature-title">Batch Processing</div>
|
||||||
|
<div class="feature-desc">Paste a playlist URL, a channel URL, or a CSV of hundreds of links. BatchTube queues and processes everything in one run — no babysitting required.</div>
|
||||||
|
</div>
|
||||||
|
<div class="feature-card">
|
||||||
|
<div class="feature-icon">📝</div>
|
||||||
|
<div class="feature-title">Transcript Extraction</div>
|
||||||
|
<div class="feature-desc">Powered by Whisper — OpenAI's speech recognition model running locally. Timestamped, accurate, exportable. Every word from every video, ready to repurpose.</div>
|
||||||
|
</div>
|
||||||
|
<div class="feature-card">
|
||||||
|
<div class="feature-icon">🧠</div>
|
||||||
|
<div class="feature-title">AI Summaries</div>
|
||||||
|
<div class="feature-desc">Get the key points from any video without watching a second of footage. AI summaries extract topics, takeaways, and action items automatically.</div>
|
||||||
|
</div>
|
||||||
|
<div class="feature-card">
|
||||||
|
<div class="feature-icon">📊</div>
|
||||||
|
<div class="feature-title">Metadata Export</div>
|
||||||
|
<div class="feature-desc">Export structured JSON and CSV — titles, descriptions, view counts, upload dates, channel data. Plug directly into your research or analytics workflow.</div>
|
||||||
|
</div>
|
||||||
|
<div class="feature-card">
|
||||||
|
<div class="feature-icon">📷</div>
|
||||||
|
<div class="feature-title">Real-Time Progress</div>
|
||||||
|
<div class="feature-desc">Live WebSocket dashboard shows every download as it happens. Queue status, completion rates, error logs — full visibility into your batch at all times.</div>
|
||||||
|
</div>
|
||||||
|
<div class="feature-card">
|
||||||
|
<div class="feature-icon">🔗</div>
|
||||||
|
<div class="feature-title">MCP Integration</div>
|
||||||
|
<div class="feature-desc">BatchTube ships with a built-in MCP server. Connect it directly to Claude, Cursor, or any AI assistant that supports the Model Context Protocol.</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</section>
|
||||||
|
|
||||||
|
<!-- HOW IT WORKS -->
|
||||||
|
<section class="section" id="how-it-works">
|
||||||
|
<div class="section-label">How It Works</div>
|
||||||
|
<h2 class="section-title">Running in 60 seconds.</h2>
|
||||||
|
<p class="section-sub">No cloud account. No API keys. No configuration headaches.</p>
|
||||||
|
<div class="steps">
|
||||||
|
<div class="step">
|
||||||
|
<div class="step-num">1</div>
|
||||||
|
<div class="step-title">Download & Run</div>
|
||||||
|
<div class="step-desc">Download BatchTube and double-click start.bat (Windows) or run the shell script. Your browser opens automatically.</div>
|
||||||
|
</div>
|
||||||
|
<div class="step">
|
||||||
|
<div class="step-num">2</div>
|
||||||
|
<div class="step-title">Paste Your URLs</div>
|
||||||
|
<div class="step-desc">Paste a YouTube playlist, channel URL, or upload a CSV of hundreds of video links. BatchTube handles the rest.</div>
|
||||||
|
</div>
|
||||||
|
<div class="step">
|
||||||
|
<div class="step-num">3</div>
|
||||||
|
<div class="step-title">Choose Your Output</div>
|
||||||
|
<div class="step-desc">Select video quality, enable transcript extraction, AI summaries, MP3 audio, or metadata export. Mix and match.</div>
|
||||||
|
</div>
|
||||||
|
<div class="step">
|
||||||
|
<div class="step-num">4</div>
|
||||||
|
<div class="step-title">Watch It Run</div>
|
||||||
|
<div class="step-desc">The live dashboard tracks every download in real time. Walk away. Come back to a completed batch — files on your hard drive, yours to keep.</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</section>
|
||||||
|
|
||||||
|
|
||||||
|
<!-- WALKTHROUGH -->
|
||||||
|
<section class="section" id="walkthrough">
|
||||||
|
<div class="section-label">See It In Action</div>
|
||||||
|
<h2 class="section-title">The full workflow. 60 seconds.</h2>
|
||||||
|
<p class="section-sub">Real app. Real interface. No demo smoke and mirrors.</p>
|
||||||
|
|
||||||
|
<!-- Main animated walkthrough -->
|
||||||
|
<div style="max-width:960px;margin:0 auto 48px;border-radius:12px;overflow:hidden;border:1px solid var(--border);box-shadow:0 20px 60px rgba(0,0,0,0.6);">
|
||||||
|
<div style="background:var(--dark3);padding:12px 16px;display:flex;align-items:center;gap:8px;border-bottom:1px solid var(--border);">
|
||||||
|
<div style="width:12px;height:12px;border-radius:50%;background:#ff5f57;"></div>
|
||||||
|
<div style="width:12px;height:12px;border-radius:50%;background:#febc2e;"></div>
|
||||||
|
<div style="width:12px;height:12px;border-radius:50%;background:#28c840;"></div>
|
||||||
|
<div style="flex:1;text-align:center;font-size:13px;color:var(--text-dim);">BatchTube — localhost:8000</div>
|
||||||
|
</div>
|
||||||
|
<img src="/batchtube-walkthrough.gif" alt="BatchTube full feature walkthrough" style="width:100%;display:block;" loading="lazy" />
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<!-- Feature GIF grid -->
|
||||||
|
<div style="display:grid;grid-template-columns:repeat(auto-fit,minmax(280px,1fr));gap:24px;">
|
||||||
|
|
||||||
|
<div style="background:var(--dark2);border:1px solid var(--border);border-radius:var(--radius);overflow:hidden;">
|
||||||
|
<img src="/feature-new-job.gif" alt="Create a new extraction job" style="width:100%;display:block;" loading="lazy" />
|
||||||
|
<div style="padding:16px;">
|
||||||
|
<div style="font-size:15px;font-weight:700;margin-bottom:6px;">⚡ New Extraction Job</div>
|
||||||
|
<div style="font-size:13px;color:var(--text-dim);">Single URL, playlist, channel handle, or CSV list. Configure what to extract in seconds.</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div style="background:var(--dark2);border:1px solid var(--border);border-radius:var(--radius);overflow:hidden;">
|
||||||
|
<img src="/feature-jobs.gif" alt="Track batch processing progress" style="width:100%;display:block;" loading="lazy" />
|
||||||
|
<div style="padding:16px;">
|
||||||
|
<div style="font-size:15px;font-weight:700;margin-bottom:6px;">📊 Live Progress Tracking</div>
|
||||||
|
<div style="font-size:13px;color:var(--text-dim);">Real-time job dashboard. See every batch as it processes — status, progress, completion history.</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div style="background:var(--dark2);border:1px solid var(--border);border-radius:var(--radius);overflow:hidden;">
|
||||||
|
<img src="/feature-settings.gif" alt="MCP server integration and settings" style="width:100%;display:block;" loading="lazy" />
|
||||||
|
<div style="padding:16px;">
|
||||||
|
<div style="font-size:15px;font-weight:700;margin-bottom:6px;">🔗 MCP Server Built In</div>
|
||||||
|
<div style="font-size:13px;color:var(--text-dim);">Connect BatchTube directly to Claude, Cursor, or any AI assistant. One config line. Done.</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
</div>
|
||||||
|
</section>
|
||||||
|
|
||||||
|
<!-- MID-PAGE CTA -->
|
||||||
|
<div class="section">
|
||||||
|
<div class="mid-cta">
|
||||||
|
<h2>Stop doing this manually.</h2>
|
||||||
|
<p>Every hour you spend downloading videos one at a time is an hour you are not creating, researching, or building. BatchTube gives that time back.</p>
|
||||||
|
<a href="#pricing" class="btn-primary">Get BatchTube Free →</a>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<!-- TESTIMONIALS -->
|
||||||
|
<section class="section" id="testimonials">
|
||||||
|
<div class="section-label">What People Are Saying</div>
|
||||||
|
<h2 class="section-title">Built for people who work at scale.</h2>
|
||||||
|
<p class="section-sub">Content creators, researchers, educators — anyone who works with YouTube seriously.</p>
|
||||||
|
<div class="testimonials-grid">
|
||||||
|
<div class="testimonial">
|
||||||
|
<div class="testimonial-stars">★★★★★</div>
|
||||||
|
<p class="testimonial-text">“I research competitor channels for clients every week. BatchTube cut my research time from 6 hours to 45 minutes. I paste the channel URL, walk away, and come back to a full transcript library. Nothing else does this.”</p>
|
||||||
|
<div class="testimonial-author">
|
||||||
|
<div class="testimonial-avatar">M</div>
|
||||||
|
<div><div class="testimonial-name">Marcus T.</div><div class="testimonial-role">YouTube Strategy Consultant</div></div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="testimonial">
|
||||||
|
<div class="testimonial-stars">★★★★★</div>
|
||||||
|
<p class="testimonial-text">“I teach a media studies course and needed to archive 200+ videos for my curriculum before they disappeared. BatchTube downloaded everything overnight — transcripts included. My students now have a searchable library. Incredible tool.”</p>
|
||||||
|
<div class="testimonial-author">
|
||||||
|
<div class="testimonial-avatar">D</div>
|
||||||
|
<div><div class="testimonial-name">Dr. Diane K.</div><div class="testimonial-role">University Media Studies Professor</div></div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="testimonial">
|
||||||
|
<div class="testimonial-stars">★★★★★</div>
|
||||||
|
<p class="testimonial-text">“The MCP integration is what sold me. I connected BatchTube directly to Claude and now I can ask questions about any YouTube channel's content without watching a single video. This is the future of research.”</p>
|
||||||
|
<div class="testimonial-author">
|
||||||
|
<div class="testimonial-avatar">R</div>
|
||||||
|
<div><div class="testimonial-name">Ryan S.</div><div class="testimonial-role">AI-Assisted Content Creator</div></div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</section>
|
||||||
|
|
||||||
|
<!-- PRICING -->
|
||||||
|
<section class="section" id="pricing">
|
||||||
|
<div class="section-label">Pricing</div>
|
||||||
|
<h2 class="section-title">Start free. Scale when you're ready.</h2>
|
||||||
|
<p class="section-sub">Every plan runs locally on your machine. Your data never leaves your hard drive.</p>
|
||||||
|
<div class="pricing-grid">
|
||||||
|
|
||||||
|
<div class="pricing-card">
|
||||||
|
<div class="pricing-name">Free</div>
|
||||||
|
<div class="pricing-price">$0</div>
|
||||||
|
<div class="pricing-desc">Try it. No account required.</div>
|
||||||
|
<ul class="pricing-features">
|
||||||
|
<li>3 videos per batch</li>
|
||||||
|
<li>720p max resolution</li>
|
||||||
|
<li>MP3 extraction</li>
|
||||||
|
<li class="dim">Transcripts</li>
|
||||||
|
<li class="dim">Batch CSV upload</li>
|
||||||
|
<li class="dim">AI summaries</li>
|
||||||
|
<li class="dim">Priority support</li>
|
||||||
|
</ul>
|
||||||
|
<a href="#download" class="btn-plan outline">Download Free — Start Today</a>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="pricing-card featured">
|
||||||
|
<div class="pricing-badge">Most Popular</div>
|
||||||
|
<div class="pricing-name">Creator</div>
|
||||||
|
<div class="pricing-price">$19<span>/mo</span></div>
|
||||||
|
<div class="pricing-annual">Or <strong>$190/yr</strong> — save 2 months</div>
|
||||||
|
<div class="pricing-desc">For serious content creators.</div>
|
||||||
|
<ul class="pricing-features">
|
||||||
|
<li>100 downloads per day</li>
|
||||||
|
<li>1080p max resolution</li>
|
||||||
|
<li>MP3 extraction</li>
|
||||||
|
<li>Transcripts</li>
|
||||||
|
<li>Batch CSV upload</li>
|
||||||
|
<li>AI summaries</li>
|
||||||
|
<li class="dim">Priority support</li>
|
||||||
|
</ul>
|
||||||
|
<a href="https://qmg.thrivecart.com/batchtube-creator/" class="btn-plan primary">Start Creator — $19/mo →</a>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="pricing-card">
|
||||||
|
<div class="pricing-name">Pro</div>
|
||||||
|
<div class="pricing-price">$39<span>/mo</span></div>
|
||||||
|
<div class="pricing-annual">Or <strong>$790/yr</strong> — save with annual</div>
|
||||||
|
<div class="pricing-desc">Unlimited power. Zero limits.</div>
|
||||||
|
<ul class="pricing-features">
|
||||||
|
<li>Unlimited downloads</li>
|
||||||
|
<li>4K max resolution</li>
|
||||||
|
<li>MP3 extraction</li>
|
||||||
|
<li>Transcripts</li>
|
||||||
|
<li>Batch CSV upload</li>
|
||||||
|
<li>AI summaries</li>
|
||||||
|
<li>Priority support</li>
|
||||||
|
</ul>
|
||||||
|
<a href="https://qmg.thrivecart.com/batchtube-pro/" class="btn-plan outline">Go Pro — $39/mo →</a>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
|
||||||
|
<div class="pricing-card" style="border-color: #9933ff; background: rgba(153,51,255,0.04);">
|
||||||
|
<div class="pricing-badge" style="background:#9933ff;">🌟 Studio</div>
|
||||||
|
<div class="pricing-name">Studio</div>
|
||||||
|
<div class="pricing-price">$79<span>/mo</span></div>
|
||||||
|
<div class="pricing-annual">Or <strong>$790/yr</strong> — save 2 months</div>
|
||||||
|
<div class="pricing-desc">For agencies & power teams.</div>
|
||||||
|
<ul class="pricing-features">
|
||||||
|
<li>Unlimited downloads</li>
|
||||||
|
<li>4K max resolution</li>
|
||||||
|
<li>MP3 extraction</li>
|
||||||
|
<li>Transcripts</li>
|
||||||
|
<li>Batch CSV upload</li>
|
||||||
|
<li>AI summaries</li>
|
||||||
|
<li>3 team seats</li>
|
||||||
|
<li>API access</li>
|
||||||
|
<li>Priority support</li>
|
||||||
|
</ul>
|
||||||
|
<a href="https://qmg.thrivecart.com/batchtube-studio/" class="btn-plan primary" style="background:#9933ff;">Get Studio — $79/mo →</a>
|
||||||
|
</div>
|
||||||
|
<div class="pricing-card" style="border-color: #ffcc00; background: rgba(255,204,0,0.03);">
|
||||||
|
<div class="pricing-badge" style="background:#ffcc00; color:#000;">🔥 Best Value</div>
|
||||||
|
<div class="pricing-name">Lifetime</div>
|
||||||
|
<div class="pricing-price">$197<span> once</span></div>
|
||||||
|
<div class="pricing-desc">Pay once. Own it forever.</div>
|
||||||
|
<div class="scarcity-box"><strong>🔥 FOUNDING MEMBER PRICE — First 100 licenses only</strong>After 100 licenses: price goes to $247. Forever.</div>
|
||||||
|
<ul class="pricing-features">
|
||||||
|
<li>Unlimited downloads</li>
|
||||||
|
<li>4K max resolution</li>
|
||||||
|
<li>MP3 extraction</li>
|
||||||
|
<li>Transcripts</li>
|
||||||
|
<li>Batch CSV upload</li>
|
||||||
|
<li>AI summaries</li>
|
||||||
|
<li>Lifetime updates</li>
|
||||||
|
</ul>
|
||||||
|
<a href="https://qmg.thrivecart.com/batchtube-lifetime/" class="btn-plan primary" style="background:#ffcc00; color:#000;">⚡ Lock in $197 before it's gone →</a>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
</div>
|
||||||
|
<p class="pricing-guarantee">🛡 30-Day Money-Back Guarantee on all paid plans • No questions asked</p>
|
||||||
|
</section>
|
||||||
|
|
||||||
|
<!-- FAQ -->
|
||||||
|
<section class="section" id="faq">
|
||||||
|
<div class="section-label">FAQ</div>
|
||||||
|
<h2 class="section-title">Questions answered.</h2>
|
||||||
|
<div class="faq">
|
||||||
|
<div class="faq-item">
|
||||||
|
<div class="faq-q">Is downloading YouTube videos legal?</div>
|
||||||
|
<div class="faq-a">Downloading YouTube videos for personal use, research, education, and archival purposes is widely practiced and legally protected in many jurisdictions under fair use doctrine. BatchTube is used by researchers, educators, journalists, and content archivists worldwide. We do not scrape YouTube's platform or violate rate limits. Use BatchTube responsibly, within the bounds of your intended purpose.</div>
|
||||||
|
</div>
|
||||||
|
<div class="faq-item">
|
||||||
|
<div class="faq-q">Does BatchTube work on Mac and Linux?</div>
|
||||||
|
<div class="faq-a">Yes. BatchTube runs on Windows, macOS, and Linux. The application runs a local server that opens in your browser — the same interface works identically across all three platforms. Windows users get a one-click start.bat launcher. Mac and Linux users run a shell script.</div>
|
||||||
|
</div>
|
||||||
|
<div class="faq-item">
|
||||||
|
<div class="faq-q">Does BatchTube violate YouTube's Terms of Service?</div>
|
||||||
|
<div class="faq-a">BatchTube is powered by a robust open-source engine maintained by a global developer community. YouTube’s ToS restricts commercial redistribution of downloaded content — not personal use or research. BatchTube does not redistribute content. It downloads to your local machine for your own use. Consult your own legal counsel if you have specific compliance questions.</div>
|
||||||
|
</div>
|
||||||
|
<div class="faq-item">
|
||||||
|
<div class="faq-q">Does BatchTube require an internet connection?</div>
|
||||||
|
<div class="faq-a">BatchTube needs an internet connection to download content from YouTube — that is the nature of the task. But the application itself runs entirely locally on your machine. Your downloaded files, transcripts, and AI summaries are stored on your hard drive. No cloud account required. No data sent to our servers. Your content stays yours.</div>
|
||||||
|
</div>
|
||||||
|
<div class="faq-item">
|
||||||
|
<div class="faq-q">How accurate are the transcripts and AI summaries?</div>
|
||||||
|
<div class="faq-a">Transcripts are generated by Whisper — OpenAI's speech recognition model — running locally on your machine. Accuracy is typically 95%+ for clear English audio. AI summaries extract key points, topics, and takeaways from the transcript automatically. Both outputs are editable and exportable.</div>
|
||||||
|
</div>
|
||||||
|
<div class="faq-item">
|
||||||
|
<div class="faq-q">What happens if YouTube changes something and BatchTube breaks?</div>
|
||||||
|
<div class="faq-a">BatchTube’s download engine is powered by a robust open-source engine maintained by a global developer community that pushes updates within hours of any YouTube change. Creator and Pro subscribers receive automatic updates. Lifetime customers receive every update forever. Your workflow stays uninterrupted.</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</section>
|
||||||
|
|
||||||
|
<!-- BOTTOM CTA -->
|
||||||
|
<div class="bottom-cta">
|
||||||
|
<h2>Your competitors are already automating their research.</h2>
|
||||||
|
<p>Are you still downloading one video at a time?</p>
|
||||||
|
<a href="#pricing" class="btn-primary" style="font-size:18px; padding:18px 44px;">Download BatchTube Now — Free to Start →</a>
|
||||||
|
<p style="margin-top:16px; font-size:13px; color:var(--text-dim);">No account required • Windows, Mac & Linux • 30-day guarantee on paid plans</p>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<!-- FOOTER -->
|
||||||
|
<footer>
|
||||||
|
<div class="footer-logo">Batch<span>Tube</span></div>
|
||||||
|
<p style="margin-bottom:12px;">Built by <a href="https://intentures.org">Intentures LLC</a> • <a href="https://mautic.intentures.org/form/2" target="_blank" rel="noopener">Contact Us</a></p>
|
||||||
|
<p>© 2026 Intentures LLC. All rights reserved.</p>
|
||||||
|
</footer>
|
||||||
|
|
||||||
|
</body>
|
||||||
|
</html>
|
||||||
Reference in New Issue
Block a user