Video seperti Reel Beyond Studio bisa dibuat lewat pipeline kode yang bisa diperiksa, bukan cuma hasil prompt video generatif. AI menulis kode animasinya, Canvas 2D menggambar tiap frame, Playwright menangkap frame, dan FFmpeg menyusunnya jadi video. Narasi, subtitle, musik, dan perbandingan akhir diselesaikan di editor.
Tutorial ini terinspirasi oleh Reel karya @beyondstudioid dan halaman Beyond Studio. Tutorial ini tidak berafiliasi dengan Beyond Studio dan tidak menyalin merek atau artwork mereka. Fokusnya adalah membedah metode produksi dan membuat contoh roket original dari awal.
1. Apa yang akan dibuat
Kamu akan membuat animasi pixel-art vertikal 12 detik, 30 fps, total 360 frame. Canvas kerja berukuran 270x480, lalu dinaikkan ke 1080x1920 saat encoding. Tiap frame berasal dari renderFrame(frameNumber), jadi frame 120 selalu tampil sama meski dirender di waktu berbeda.
Bukti dari Reel: tampilannya memperlihatkan HTML Canvas 2D, JavaScript, requestAnimationFrame, Playwright, Headless Chromium, FFmpeg, 30 fps, 360 frame, output 1080x1920, dan referensi kerja 270x480. Narasi menyebut satu prompt, animasi 12 detik, serta batas maksimal 16 warna.
Inferensi dan pilihan tutorial: struktur file, implementasi starter, metode audit Pillow, urutan editing, dan command di bawah ini adalah rancangan tutorial yang direkomendasikan. Jangan membacanya sebagai klaim bahwa source Reel memakai kode yang identik.
Asal suara Reel tidak bisa dipastikan dari bukti yang ada. Suaranya mungkin TTS atau suara manusia yang diproses. Tutorial ini menyediakan kedua jalur tanpa menyatakan salah satunya sebagai fakta sumber.
2. Peta alat dari ide sampai video final
| Tahap | Alat | Input | Output | Tanda selesai |
|---|---|---|---|---|
| Brief | Dokumen teks | Ide, aturan, durasi | Prompt produksi | Semua batasan tertulis |
| Generasi kode | Claude atau Gemini | Prompt yang sama | HTML dan JavaScript | Kode bisa dibuka lokal |
| Render | Canvas 2D | frameNumber |
Gambar 270x480 | Frame tertentu selalu identik |
| Capture | Playwright + Chromium | Halaman lokal | 360 PNG | Nama frame 000-359 lengkap |
| Encode | FFmpeg | Urutan PNG | MP4 tanpa audio | 12 detik, 30 fps, 1080x1920 |
| Narasi | Mic atau TTS | Naskah lisan | WAV/M4A | Jelas, tanpa clipping |
| Editing | CapCut atau DaVinci Resolve | Video, suara, subtitle | Timeline final | Sinkron dan aman di 9:16 |
| Ekspor | Editor atau FFmpeg | Timeline final | MP4 final | Playback lolos QA |
3. Prasyarat dan struktur folder
Yang perlu kamu siapkan: Node.js 18+, npm, FFmpeg, Python 3, Pillow, dan Chromium yang dipasang lewat Playwright. Jalankan proyek demo di folder terpisah supaya dependency tidak bercampur dengan proyek utama.
mkdir video-ai-demo
cd video-ai-demo
npm init -y
npm install playwright
npx playwright install chromium
python3 -m pip install Pillow
mkdir frames
Struktur minimum:
video-ai-demo/
├── index.html
├── animation.js
├── capture.mjs
├── audit_colors.py
├── frames/
└── package.json
Pillow bisa dipasang lewat package manager atau virtual environment kalau instalasi global dibatasi OS. Tanda selesai: node --version, ffmpeg -version, dan python3 -c "from PIL import Image" jalan tanpa error.
4. Storyboard video perbandingan 60-120 detik
Contoh ini berdurasi 100 detik. Animasi yang dibandingkan tetap 12 detik; sisa durasi untuk menjelaskan aturan, memperlihatkan kode, mengaudit hasil, dan menyimpulkan.
| Waktu | Adegan | Visual | Narasi utama | Check |
|---|---|---|---|---|
| 0-8 dtk | Hook | Dua hasil, dipotong cepat | “Satu prompt yang sama. Apakah dua model mengikuti aturan yang sama?” | Konflik langsung terbaca |
| 8-20 dtk | Aturan | 12 detik, 30 fps, 16 warna | Jelaskan batas eksperimen | Angka tampil cukup lama |
| 20-35 dtk | Prompt | Bagian prompt penting | Tekankan tanpa aset luar dan tanpa revisi | Bukan screenshot teks kecil |
| 35-58 dtk | Reveal | Split-screen sinkron | Biarkan penonton melihat gerak | Kedua sisi mulai frame sama |
| 58-82 dtk | Audit | Frame, palet, hitung warna | Bedakan bagus secara visual dan patuh aturan | Bukti terlihat |
| 82-100 dtk | Kesimpulan + CTA | Ringkasan dan pertanyaan | Nilai berdasarkan tujuan, lalu ajak komentar | Tidak membuat klaim berlebihan |
5. Prompt produksi siap salin
Kirim prompt yang sama ke kedua model yang dibandingkan. Simpan respons mentah dan jangan memperbaiki satu hasil saja kalau tujuan videonya memang menguji percobaan pertama.
Buat animasi pixel-art original tentang roket yang lepas landas menuju orbit.
Output wajib berupa tiga file lengkap: index.html, animation.js, dan catatan cara menjalankan. Jangan memakai framework, library gambar, font web, gambar, video, shader, atau aset eksternal.
Batas teknis:
- Rasio 9:16.
- Durasi tepat 12 detik.
- Frame rate 30 fps.
- Total tepat 360 frame, bernomor 0 sampai 359.
- Canvas kerja tepat 270 × 480 piksel.
- Maksimal 16 warna RGB unik pada frame hasil render.
- Tidak boleh memakai gradient, shadow blur, filter, transparansi parsial, compositing yang menghasilkan warna campuran, atau CSS yang mengubah pixel Canvas.
- Set ctx.imageSmoothingEnabled = false.
- Semua bentuk berada pada koordinat integer dan ukuran integer.
- Hindari arc, ellipse, rotasi Canvas, dan garis subpixel. Bentuk membulat harus disusun manual dari persegi panjang/pixel.
- Definisikan palet sebagai array konstanta. Semua fillStyle dan strokeStyle wajib mengambil nilai dari palet itu.
- Sediakan fungsi global renderFrame(frameNumber). Fungsi harus deterministik: input frame yang sama menghasilkan piksel yang sama, tanpa Date.now(), performance.now(), Math.random(), requestAnimationFrame sebagai sumber waktu, atau state dari frame sebelumnya.
- renderFrame harus membersihkan dan menggambar seluruh frame dari awal.
- Boleh memakai requestAnimationFrame hanya untuk preview interaktif; preview harus menghitung frame lalu memanggil renderFrame(frameNumber).
- Tampilkan roket, landasan, langit, bintang, api, dan gerak kamera sederhana tanpa meniru karya atau merek tertentu.
Kriteria selesai:
1. Membuka index.html menampilkan preview.
2. Memanggil renderFrame(0), renderFrame(180), dan renderFrame(359) bekerja tanpa error.
3. Canvas selalu 270 × 480.
4. Tidak ada request jaringan.
5. Sertakan penjelasan singkat bagian yang berisiko menambah warna dan cara mengaudit hasil PNG.
Jangan mengklaim jumlah warna sudah patuh sebelum PNG hasil render benar-benar dihitung.
6. Starter runnable
Starter ini sengaja minimal. Adegan sederhana supaya kamu bisa memahami cara kerja determinisme sebelum minta AI menambah detail.
index.html:
<!doctype html>
<html lang="id">
<head>
<meta charset="utf-8" />
<meta name="viewport" content="width=device-width, initial-scale=1" />
<title>Rocket frame renderer</title>
<style>
html, body { margin: 0; min-height: 100%; background: #171a2b; display: grid; place-items: center; }
canvas { width: min(90vw, 540px); height: auto; image-rendering: pixelated; }
</style>
</head>
<body>
<canvas id="scene" width="270" height="480" aria-label="Animasi pixel art roket"></canvas>
<script src="animation.js"></script>
</body>
</html>
animation.js:
const canvas = document.querySelector('#scene');
const ctx = canvas.getContext('2d', { alpha: false });
ctx.imageSmoothingEnabled = false;
const W = 270;
const H = 480;
const FPS = 30;
const TOTAL_FRAMES = 360;
const C = {
sky: '#10182b', dark: '#20283a', blue: '#2855d9', pale: '#fbf7ed',
orange: '#f47b35', yellow: '#dfc05c', gray: '#7a8499', white: '#ffffff'
};
function rect(x, y, w, h, color) {
ctx.fillStyle = color;
ctx.fillRect(Math.round(x), Math.round(y), Math.round(w), Math.round(h));
}
function renderFrame(frameNumber) {
const frame = Math.max(0, Math.min(TOTAL_FRAMES - 1, Math.floor(frameNumber)));
const t = frame / (TOTAL_FRAMES - 1);
rect(0, 0, W, H, C.sky);
for (let i = 0; i < 24; i++) {
const x = (i * 47 + 19) % W;
const y = (i * 83 + 31 + Math.floor(t * 40)) % 300;
rect(x, y, 2, 2, i % 3 ? C.white : C.yellow);
}
const groundY = Math.min(H, 410 + Math.floor(t * 150));
rect(0, groundY, W, H - groundY, C.dark);
rect(35, groundY - 12, 200, 12, C.gray);
const rocketY = Math.round(330 - t * 310);
rect(119, rocketY, 32, 70, C.pale);
rect(126, rocketY - 16, 18, 16, C.orange);
rect(111, rocketY + 48, 8, 22, C.blue);
rect(151, rocketY + 48, 8, 22, C.blue);
rect(128, rocketY + 18, 14, 14, C.blue);
const flame = 16 + (frame % 3) * 6;
rect(126, rocketY + 70, 18, flame, C.orange);
rect(131, rocketY + 70, 8, Math.max(6, flame - 7), C.yellow);
return frame;
}
window.renderFrame = renderFrame;
window.animationSpec = { width: W, height: H, fps: FPS, totalFrames: TOTAL_FRAMES };
const startedAt = performance.now();
function preview(now) {
const elapsed = (now - startedAt) / 1000;
renderFrame(Math.floor(elapsed * FPS) % TOTAL_FRAMES);
requestAnimationFrame(preview);
}
requestAnimationFrame(preview);
capture.mjs:
import { chromium } from 'playwright';
import fs from 'node:fs/promises';
import path from 'node:path';
import { pathToFileURL } from 'node:url';
const root = process.cwd();
const output = path.join(root, 'frames');
await fs.mkdir(output, { recursive: true });
const browser = await chromium.launch({ headless: true });
const page = await browser.newPage({ viewport: { width: 270, height: 480 }, deviceScaleFactor: 1 });
await page.goto(pathToFileURL(path.join(root, 'index.html')).href);
await page.waitForFunction(() => typeof window.renderFrame === 'function');
await page.locator('#scene').evaluate((canvas) => {
canvas.style.width = '270px';
canvas.style.height = '480px';
});
const spec = await page.evaluate(() => window.animationSpec);
if (spec.width !== 270 || spec.height !== 480 || spec.fps !== 30 || spec.totalFrames !== 360) {
throw new Error(`Animation spec tidak sesuai: ${JSON.stringify(spec)}`);
}
const canvas = page.locator('#scene');
for (let frame = 0; frame < spec.totalFrames; frame++) {
await page.evaluate((n) => window.renderFrame(n), frame);
const name = `frame-${String(frame).padStart(3, '0')}.png`;
await canvas.screenshot({ path: path.join(output, name), animations: 'disabled' });
}
await browser.close();
console.log(`Captured ${spec.totalFrames} frames at ${spec.width}x${spec.height}.`);
Jalankan:
node capture.mjs
Untuk cek cepat, ubah loop sementara jadi [0, 180, 359], tapi kembalikan ke 360 frame sebelum encoding. Tanda selesai: frames/frame-000.png, frame-180.png, dan frame-359.png berukuran 270x480; capture penuh berisi 360 file.
7. Anatomi pixel art Canvas dan sumber warna ekstra
Canvas tidak tahu apa itu “pixel art”. Ia cuma meraster bentuk. Beberapa operasi bisa menghasilkan warna di luar palet:
arc()danellipse()menghaluskan tepi lingkaran dengan piksel campuran.rotate()membuat tepi bentuk jatuh di antara grid piksel.- Koordinat pecahan, garis dengan ketebalan ganjil, dan scaling non-integer bisa menyentuh subpixel.
globalAlpha, shadow, filter, gradient, dan compositing mencampurkan warna.imageSmoothingEnabled = falsemembantu saat gambar diperbesar, tapi tidak otomatis mematikan antialiasing semua bentuk vektor.- Encoding video mengubah representasi warna. Audit batas palet dilakukan pada PNG frame asli, bukan pada frame hasil decode H.264.
Pakai persegi panjang integer, palet konstanta, dan gambar ulang seluruh adegan dari input frame. Kalau butuh lingkaran pixel-art, bentuk siluetnya dari baris persegi panjang, bukan ctx.arc().
8. Audit warna dengan Pillow
Audit ini menghitung warna RGB unik setelah tiap PNG dikomposisikan di atas latar hitam (kalau ada alpha). Pendekatan itu membuat asumsi komposit jadi eksplisit. Kalau desainmu butuh transparansi, pilih warna latar final yang sebenarnya.
audit_colors.py:
from pathlib import Path
from PIL import Image
LIMIT = 16
failed = []
for file in sorted(Path('frames').glob('frame-*.png')):
with Image.open(file) as source:
rgba = source.convert('RGBA')
background = Image.new('RGBA', rgba.size, (0, 0, 0, 255))
rgb = Image.alpha_composite(background, rgba).convert('RGB')
colors = rgb.getcolors(maxcolors=rgb.width * rgb.height)
count = len(colors) if colors is not None else rgb.width * rgb.height + 1
if count > LIMIT:
failed.append((file.name, count))
if failed:
for name, count in failed[:20]:
print(f'FAIL {name}: {count} warna RGB')
raise SystemExit(f'{len(failed)} frame melewati batas {LIMIT} warna')
print(f'PASS: semua frame memakai maksimal {LIMIT} warna RGB')
Jalankan:
python3 audit_colors.py
Audit jumlah warna belum membuktikan bahwa warna yang dipakai memang palet yang dimaksud. Untuk kontrol lebih kuat, bandingkan set RGB aktual dengan daftar palet yang disetujui. Alpha parsial sering lolos jadi banyak warna baru setelah komposit; itu perilaku nyata, bukan kesalahan auditor.
9. Encode 1080x1920 dengan FFmpeg
Encode video tanpa audio:
ffmpeg -framerate 30 -start_number 0 -i frames/frame-%03d.png \
-vf "scale=1080:1920:flags=neighbor" \
-c:v libx264 -preset medium -crf 18 -pix_fmt yuv420p \
-movflags +faststart -r 30 -frames:v 360 -an output.mp4
Yang perlu kamu perhatikan:
-framerate 30membaca sequence sebagai 30 frame per detik.-start_number 0cocok dengan file pertamaframe-000.png.scale=...:flags=neighbormemperbesar pixel art tanpa interpolasi halus.libx264menghasilkan H.264;-crf 18adalah titik awal kualitas tinggi, bukan aturan platform.yuv420pmeningkatkan kompatibilitas di pemutar umum.+faststartmemindahkan metadata supaya pemutaran web bisa mulai lebih cepat.-frames:v 360mencegah frame tambahan masuk tanpa sengaja.-anmemastikan tahap ini tidak membawa audio.
Gabungkan narasi atau mix final:
ffmpeg -i output.mp4 -i final-audio.wav \
-c:v copy -c:a aac -b:a 192k -shortest \
-movflags +faststart final.mp4
-c:v copy tidak encode ulang video. -shortest berhenti saat stream terpendek selesai; periksa durasi karena audio yang terlalu pendek akan memotong hasil. Dokumentasi lengkap ada di FFmpeg Documentation.
10. Workflow narasi yang terdengar natural
Turunkan naskah lisan dari storyboard, bukan dari artikel panjang. Tiap scene cukup bawa satu gagasan. Kalimat pendek lebih mudah direkam ulang, ditiming untuk subtitle, dan diproses TTS.
Template narasi:
[Hook]
Satu prompt yang sama, dua animasi yang berbeda. Tapi mana yang benar-benar mengikuti aturan?
[Aturan]
Keduanya diminta membuat roket pixel art selama dua belas detik, tiga puluh frame per detik, maksimal enam belas warna, seluruhnya dari kode.
[Transisi]
Sebelum melihat hasil, perhatikan satu hal: tampilan yang lebih ramai belum tentu lebih patuh.
[Perbandingan]
Di kiri ada hasil pertama. Di kanan ada hasil kedua. Keduanya bergerak, tetapi cara menggambarnya berbeda.
[Audit]
Sekarang saya ambil frame PNG aslinya dan menghitung warna RGB. Tepi halus, rotasi, dan transparansi dapat membuat warna campuran yang tidak terlihat di daftar palet.
[Disclosure]
Ini satu percobaan untuk satu tugas. Hasilnya tidak mewakili semua kemampuan model.
[CTA]
Menurut kamu, untuk tugas dengan aturan ketat, hasil mana yang lebih berguna? Tulis alasannya, bukan hanya nama modelnya.
Target awal yang nyaman sekitar 125-155 kata per menit, lalu sesuaikan dengan artikulasi pembicara. Pecah naskah per kalimat. Beri jeda 150-300 ms setelah koma penting dan 300-600 ms antarbagian sebagai titik awal, bukan angka mutlak. Jangan memaksa kecepatan hanya demi mengejar durasi; lebih baik potong kalimat yang tidak membawa informasi.
Catat pengucapan sebelum rekam: “Canvas” bisa dibaca “kanvas”, “FFmpeg” dieja konsisten, “H.264” dibaca “H dua enam empat”, dan nama model ikut pengucapan resminya kalau tersedia. Jangan mencampur cara baca dalam satu video.
Opsi A, suara manusia: pilih ruangan yang tenang dan tidak bergema, matikan sumber dengung, taruh mic sekitar 10-20 cm dari mulut dengan sedikit sudut untuk mengurangi plosive, jaga posisi tetap, dan atur gain supaya puncak tidak clipping. Rekam beberapa detik room tone. Ambil ulang per kalimat, jangan memaksakan satu take panjang.
Opsi B, TTS: pilih suara Indonesia netral yang lisensinya cocok untuk penggunaanmu. Render per kalimat supaya jeda bisa diedit. Beri tanda baca yang natural, cek pengucapan istilah teknis, dan simpan naskah beserta setting. Jangan mengkloning suara siapa pun tanpa izin eksplisit.
11. Pemrosesan dan mixing audio
Urutan praktis:
- Potong napas atau kesalahan yang mengganggu, tapi pertahankan ritme manusiawi.
- Pakai noise reduction secukupnya. Artefak berair lebih buruk daripada noise ruangan yang sangat kecil.
- High-pass atau EQ itu opsional. Kurangi rumble kalau memang ada; jangan pakai preset hanya karena tersedia.
- Kompresor ringan meratakan volume kata pelan dan keras. Dengarkan consonant dan napas setelahnya.
- Limiter menangkap puncak tersisa dan mencegah clipping.
- Pakai loudness sekitar -16 sampai -14 LUFS integrated dan true peak sekitar -1 dBTP sebagai titik awal praktis, bukan persyaratan absolut semua platform. Ukur, lalu dengarkan di speaker ponsel dan headphone.
Musik harus lebih pelan dari narasi. Automasi volume atau ducking bisa menurunkannya saat suara masuk. Pakai musik yang kamu buat sendiri, berlisensi tepat, atau dari pustaka yang mengizinkan jenis publikasimu. Simpan bukti lisensi; “tersedia online” bukan izin pakai.
12. Subtitle yang mudah dibaca
Timing bisa berasal dari transkripsi rekaman final atau dari naskah yang diselaraskan manual. Transkripsi lebih cepat, tapi nama model dan istilah teknis tetap harus dikoreksi.
Pakai maksimal dua baris, pecah di batas frasa, beri kontras tinggi, dan jangan taruh teks terlalu dekat tepi atau area UI aplikasi. Untuk 1080x1920, mulai dengan margin horizontal sekitar 80-120 px dan area bawah yang cukup jauh dari tombol platform; cek di preview aplikasi nyata karena overlay bisa berubah.
Contoh subtitle.srt:
1
00:00:00,000 --> 00:00:03,800
Satu prompt yang sama,
dua animasi yang berbeda.
2
00:00:03,800 --> 00:00:08,000
Tapi mana yang benar-benar
mengikuti aturan?
3
00:00:08,000 --> 00:00:13,500
Dua belas detik, tiga puluh fps,
dan maksimal enam belas warna.
Tanda selesai: subtitle terbaca sekali lihat, tidak menutup objek penting, dan ejaannya cocok dengan audio.
13. Editing di CapCut atau DaVinci Resolve
CapCut biasanya lebih cepat dipelajari untuk pemotongan, subtitle, dan format sosial. DaVinci Resolve memberi kontrol lebih detail untuk track, color, Fairlight audio, dan delivery. Itu perbedaan alur kerja, bukan klaim bahwa satu aplikasi selalu lebih bagus hasilnya.
Langkah yang sama di keduanya:
- Buat timeline 1080x1920, 30 fps. Jangan ubah fps setelah timeline terisi.
- Taruh hasil A dan B di track video terpisah. Crop masing-masing jadi separuh layar untuk split-screen.
- Sinkronkan frame awal dan durasi kedua animasi. Tambahkan label yang netral.
- Pakai zoom atau callout hanya saat menjelaskan detail, misalnya tepi antialias atau angka audit.
- Tampilkan before/after atau frame pembanding cukup lama supaya terbaca.
- Taruh subtitle di track sendiri, dalam safe area, maksimal dua baris.
- Susun narasi sebagai audio utama dan musik di track bawah. Lakukan ducking saat narasi aktif.
- Ekspor H.264, 1080x1920, 30 fps, audio AAC. Tinjau file ekspor, bukan cuma timeline.
14. Checklist QA
- Durasi animasi tepat 12 detik.
- Frame rate 30 fps dan total 360 frame.
- Frame 000 sampai 359 lengkap, tanpa nomor ganda atau hilang.
- Frame yang sama identik saat dirender ulang.
- Tiap PNG berukuran 270x480 sebelum upscale.
- Audit warna dijalankan pada PNG, bukan cuma membaca palet di kode.
- Output final 1080x1920 dan
yuv420p. - Tidak ada objek, label, atau subtitle terpotong.
- Teks berada dalam safe area dan terbaca di layar ponsel.
- Narasi sinkron dengan reveal dan audit.
- Nama model, angka, dan istilah subtitle sudah diperiksa manual.
- Audio tidak clipping; loudness diukur dan didengar ulang.
- Musik cukup rendah saat narasi aktif.
- Sumber, lisensi aset, dan izin suara tercatat.
- File ekspor diputar dari awal sampai akhir di luar editor.
- Tutorial menyebut pilihan rekomendasi terpisah dari bukti Reel.
15. Kegagalan umum dan perbaikan tepat
| Gejala | Penyebab umum | Perbaikan |
|---|---|---|
| Capture menghasilkan frame sama | Preview terus menggambar setelah renderFrame() manual |
Matikan loop preview saat mode capture atau panggil screenshot segera setelah render sinkron |
| Hasil berbeda tiap run | Math.random() atau waktu nyata |
Turunkan semua keadaan dari frameNumber; pakai pola pseudo-acak berbasis indeks kalau perlu |
| Warna jauh di atas 16 | Arc, rotasi, alpha, gradient, shadow | Ganti dengan rect integer dan warna solid dari palet |
| Kode menyebut 16 warna, PNG tidak | Audit cuma menghitung konstanta | Hitung warna pada PNG hasil capture |
| Pixel art jadi buram | Scaling bilinear | Pakai imageSmoothingEnabled=false, CSS image-rendering: pixelated, dan FFmpeg flags=neighbor |
| Durasi 11,97 atau 12,03 detik | Timestamp atau frame rate tidak konsisten | Input 30 fps, output 30 fps, dan batasi 360 frame |
| FFmpeg tidak menemukan file | Pola nama berbeda | Pastikan frame-%03d.png cocok dengan frame-000.png |
| Video tidak diputar di perangkat tertentu | Pixel format tidak kompatibel | Encode H.264 dengan -pix_fmt yuv420p |
| Audio memotong video | -shortest dan audio lebih pendek |
Tambahkan room tone/silence atau samakan durasi sebelum mux |
| Subtitle tertutup UI platform | Posisi terlalu rendah | Naikkan safe area dan uji di preview perangkat/platform |
| TTS terdengar terburu-buru | Paragraf dirender sekaligus | Pecah per kalimat, atur jeda, edit timing manual |
| Noise reduction terdengar berair | Reduksi terlalu agresif | Kurangi amount; prioritaskan rekaman yang lebih bersih |
16. Biaya
Jangan pakai angka harga atau promosi dari Reel sebagai patokan pembelian. Harga model, paket langganan, kuota, pajak, dan promosi berubah. Periksa halaman harga resmi Claude, Gemini, penyedia TTS, editor, dan layanan musik pada hari kamu berlangganan. Catat juga biaya non-uang: waktu revisi, kecepatan capture, kapasitas penyimpanan frame, dan hak komersial aset.
Untuk latihan ini, komponen kode utama bisa dijalankan lokal dengan Canvas, Playwright, Python/Pillow, dan FFmpeg. Akses ke model AI dan editor tertentu mungkin memerlukan akun atau paket berbeda.
17. Sumber dan bacaan resmi
- MDN Canvas API, konsep dan referensi Canvas 2D.
- MDN Window.requestAnimationFrame, loop preview yang mengikuti repaint browser.
- MDN CanvasRenderingContext2D.imageSmoothingEnabled, kontrol smoothing saat gambar diskalakan.
- Playwright Screenshots, screenshot halaman dan elemen.
- FFmpeg Documentation, input image sequence, filter, codec, dan muxing.
- Reel Beyond Studio, sumber inspirasi eksperimen.
- Beyond Studio, halaman inspirasi dan konteks kreator.
Yang paling penting di sini bukan soal memilih model “pemenang”. Kuncinya adalah membuat brief yang bisa diuji, render deterministik, menyimpan bukti frame, mengaudit klaim, lalu menyunting semuanya jadi cerita yang jujur.