Preview (Live GSAP Timeline)
Preview memakai srcdoc. Untuk render final 4K/MP4/MOV gunakan Google Colab notebook yang disediakan.
Idea → Native HTML/GSAP → Microstock Ready
Preview memakai srcdoc. Untuk render final 4K/MP4/MOV gunakan Google Colab notebook yang disediakan.
`); iframe.srcdoc = enhanced; } function playPreview() { const iframe = document.getElementById('preview-frame'); try { iframe.contentWindow.hfPlay(); } catch(e){} } function pausePreview() { const iframe = document.getElementById('preview-frame'); try { iframe.contentWindow.hfPause(); } catch(e){} } function seekPreview(t) { const iframe = document.getElementById('preview-frame'); try { iframe.contentWindow.hfSeek(t); } catch(e){} } function copyCode() { const code = editor.getValue(); navigator.clipboard.writeText(code).then(() => { setStatus('Copied to clipboard!', 'ok'); }); } function downloadHTML() { const code = editor.getValue(); const blob = new Blob([code], { type: 'text/html' }); const a = document.createElement('a'); a.href = URL.createObjectURL(blob); a.download = 'hyperframes-motion.html'; a.click(); } function downloadColab() { // Generate a ready-to-use Colab notebook (as JSON .ipynb) const htmlCode = editor.getValue().replace(/`/g, '\\`'); const notebook = { "nbformat": 4, "nbformat_minor": 0, "metadata": { "colab": { "provenance": [] }, "kernelspec": { "name": "python3", "display_name": "Python 3" } }, "cells": [ { "cell_type": "markdown", "metadata": {}, "source": [ "# HyperFrames → MP4 / MOV Renderer (Google Colab)\\n", "Render HTML motion graphic ke video 4K high-bitrate untuk microstock.\\n", "\\n", "**Cara pakai:**\\n", "1. Runtime → Change runtime type → GPU (opsional, lebih cepat)\\n", "2. Jalankan cell berurutan\\n", "3. Upload HTML-mu atau paste di cell yang disediakan\\n", "4. Pilih format MP4 atau MOV (alpha)\\n" ] }, { "cell_type": "code", "metadata": {}, "source": [ "!pip install -q playwright\n", "!playwright install chromium\n", "!apt-get update -qq && apt-get install -y -qq ffmpeg > /dev/null" ], "execution_count": null, "outputs": [] }, { "cell_type": "code", "metadata": {}, "source": [ "from google.colab import files\n", "import os\n", "\n", "# Upload your hyperframes-motion.html\n", "uploaded = files.upload()\n", "html_filename = list(uploaded.keys())[0]\n", "print('Uploaded:', html_filename)" ], "execution_count": null, "outputs": [] }, { "cell_type": "code", "metadata": {}, "source": [ "# ===== CONFIG =====\n", "WIDTH = 3840 # 4K\n", "HEIGHT = 2160\n", "FPS = 30\n", "DURATION = 6.0 # seconds (match your HTML data-duration)\n", "BITRATE = '50M' # high bitrate for microstock\n", "FORMAT = 'mp4' # 'mp4' or 'mov' (mov for alpha/transparency)\n", "OUTPUT_NAME = 'motion_4k'\n", "\n", "# ==================\n", "from playwright.async_api import async_playwright\n", "import asyncio, subprocess, math\n", "\n", "async def render():\n", " async with async_playwright() as p:\n", " browser = await p.chromium.launch(headless=True)\n", " page = await browser.new_page(viewport={'width': WIDTH, 'height': HEIGHT})\n", " await page.goto(f'file://{os.path.abspath(html_filename)}')\n", " await page.wait_for_timeout(1000) # wait GSAP ready\n", "\n", " # Seek & capture frames\n", " total_frames = int(DURATION * FPS)\n", " os.makedirs('frames', exist_ok=True)\n", "\n", " for i in range(total_frames):\n", " t = i / FPS\n", " await page.evaluate(f'''() => {{\n", " const tl = window.__timelines && window.__timelines[\"main\"];\n", " if (tl) tl.seek({t});\n", " }}''')\n", " await page.wait_for_timeout(30)\n", " await page.screenshot(path=f'frames/frame_{i:05d}.png', full_page=False)\n", " if i % 30 == 0:\n", " print(f'Frame {i}/{total_frames}')\n", "\n", " await browser.close()\n", "\n", "asyncio.get_event_loop().run_until_complete(render())\n", "print('Frames captured!')" ], "execution_count": null, "outputs": [] }, { "cell_type": "code", "metadata": {}, "source": [ "# Encode with FFmpeg (high quality)\n", "if FORMAT == 'mp4':\n", " cmd = f'''ffmpeg -y -framerate {FPS} -i frames/frame_%05d.png \\\n", " -c:v libx264 -preset slow -crf 12 -pix_fmt yuv420p \\\n", " -b:v {BITRATE} -maxrate {BITRATE} -bufsize 100M \\\n", " {OUTPUT_NAME}.mp4'''\n", "else:\n", " # MOV with alpha (ProRes 4444 style via qtrle or png)\n", " cmd = f'''ffmpeg -y -framerate {FPS} -i frames/frame_%05d.png \\\n", " -c:v qtrle -pix_fmt argb {OUTPUT_NAME}.mov'''\n", "\n", "subprocess.run(cmd, shell=True, check=True)\n", "print('Done! Downloading...')\n", "files.download(f'{OUTPUT_NAME}.{FORMAT}')" ], "execution_count": null, "outputs": [] } ] }; const blob = new Blob([JSON.stringify(notebook, null, 2)], { type: 'application/json' }); const a = document.createElement('a'); a.href = URL.createObjectURL(blob); a.download = 'HyperFrames_Colab_Renderer.ipynb'; a.click(); setStatus('Colab notebook downloaded!', 'ok'); }